No longer triggering a checked iterator assert on Windows when using std::copy while deserializing attributed statements with more than one attribute.

llvm-svn: 208702
This commit is contained in:
Aaron Ballman 2014-05-13 14:55:01 +00:00
parent b9bd76b85d
commit f3d9b09dea
4 changed files with 35 additions and 9 deletions

View File

@ -819,21 +819,25 @@ class AttributedStmt : public Stmt {
Stmt *SubStmt; Stmt *SubStmt;
SourceLocation AttrLoc; SourceLocation AttrLoc;
unsigned NumAttrs; unsigned NumAttrs;
const Attr *Attrs[1];
friend class ASTStmtReader; friend class ASTStmtReader;
AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt) AttributedStmt(SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt)
: Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc), : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc),
NumAttrs(Attrs.size()) { NumAttrs(Attrs.size()) {
memcpy(this->Attrs, Attrs.data(), Attrs.size() * sizeof(Attr*)); memcpy(getAttrArrayPtr(), Attrs.data(), Attrs.size() * sizeof(Attr *));
} }
explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs)
: Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) {
memset(Attrs, 0, NumAttrs * sizeof(Attr*)); memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *));
} }
Attr *const *getAttrArrayPtr() const {
return reinterpret_cast<Attr *const *>(this + 1);
}
Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); }
public: public:
static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs, Stmt *SubStmt); ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
@ -842,7 +846,7 @@ public:
SourceLocation getAttrLoc() const { return AttrLoc; } SourceLocation getAttrLoc() const { return AttrLoc; }
ArrayRef<const Attr*> getAttrs() const { ArrayRef<const Attr*> getAttrs() const {
return ArrayRef<const Attr*>(Attrs, NumAttrs); return ArrayRef<const Attr*>(getAttrArrayPtr(), NumAttrs);
} }
Stmt *getSubStmt() { return SubStmt; } Stmt *getSubStmt() { return SubStmt; }
const Stmt *getSubStmt() const { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; }

View File

@ -285,8 +285,8 @@ const char *LabelStmt::getName() const {
AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
ArrayRef<const Attr*> Attrs, ArrayRef<const Attr*> Attrs,
Stmt *SubStmt) { Stmt *SubStmt) {
void *Mem = C.Allocate(sizeof(AttributedStmt) + assert(!Attrs.empty() && "Attrs should not be empty");
sizeof(Attr*) * (Attrs.size() - 1), void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(),
llvm::alignOf<AttributedStmt>()); llvm::alignOf<AttributedStmt>());
return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
} }
@ -294,8 +294,7 @@ AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
unsigned NumAttrs) { unsigned NumAttrs) {
assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
void *Mem = C.Allocate(sizeof(AttributedStmt) + void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs,
sizeof(Attr*) * (NumAttrs - 1),
llvm::alignOf<AttributedStmt>()); llvm::alignOf<AttributedStmt>());
return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
} }

View File

@ -176,7 +176,7 @@ void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) {
(void)NumAttrs; (void)NumAttrs;
assert(NumAttrs == S->NumAttrs); assert(NumAttrs == S->NumAttrs);
assert(NumAttrs == Attrs.size()); assert(NumAttrs == Attrs.size());
std::copy(Attrs.begin(), Attrs.end(), S->Attrs); std::copy(Attrs.begin(), Attrs.end(), S->getAttrArrayPtr());
S->SubStmt = Reader.ReadSubStmt(); S->SubStmt = Reader.ReadSubStmt();
S->AttrLoc = ReadSourceLocation(Record, Idx); S->AttrLoc = ReadSourceLocation(Record, Idx);
} }

View File

@ -0,0 +1,23 @@
// RUN: %clang_cc1 -std=c++11 -emit-pch -o %t.a %s
// RUN: %clang_cc1 -std=c++11 -include-pch %t.a %s -ast-print -o - | FileCheck %s
#ifndef HEADER
#define HEADER
inline void test(int i) {
switch (i) {
case 1:
// Notice that the NullStmt has two attributes.
[[clang::fallthrough]][[clang::fallthrough]];
case 2:
break;
}
}
#else
void foo(void) {
test(1);
}
#endif