forked from OSchip/llvm-project
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:
parent
b9bd76b85d
commit
f3d9b09dea
|
@ -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; }
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue