From 4b5accafd49e79c3a63e9238545f727c9f7f2a1b Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 13 May 2014 14:55:01 +0000 Subject: [PATCH] No longer triggering a checked iterator assert on Windows when using std::copy while deserializing attributed statements with more than one attribute. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208702 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Stmt.h | 12 ++++++++---- lib/AST/Stmt.cpp | 7 +++---- lib/Serialization/ASTReaderStmt.cpp | 2 +- test/PCH/stmt-attrs.cpp | 23 +++++++++++++++++++++++ 4 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 test/PCH/stmt-attrs.cpp diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 10afca4fbd..88cbb21b81 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -819,21 +819,25 @@ class AttributedStmt : public Stmt { Stmt *SubStmt; SourceLocation AttrLoc; unsigned NumAttrs; - const Attr *Attrs[1]; friend class ASTStmtReader; AttributedStmt(SourceLocation Loc, ArrayRef Attrs, Stmt *SubStmt) : Stmt(AttributedStmtClass), SubStmt(SubStmt), AttrLoc(Loc), 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) : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { - memset(Attrs, 0, NumAttrs * sizeof(Attr*)); + memset(getAttrArrayPtr(), 0, NumAttrs * sizeof(Attr *)); } + Attr *const *getAttrArrayPtr() const { + return reinterpret_cast(this + 1); + } + Attr **getAttrArrayPtr() { return reinterpret_cast(this + 1); } + public: static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, ArrayRef Attrs, Stmt *SubStmt); @@ -842,7 +846,7 @@ public: SourceLocation getAttrLoc() const { return AttrLoc; } ArrayRef getAttrs() const { - return ArrayRef(Attrs, NumAttrs); + return ArrayRef(getAttrArrayPtr(), NumAttrs); } Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index e6468f760a..8588dda363 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -285,8 +285,8 @@ const char *LabelStmt::getName() const { AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, ArrayRef Attrs, Stmt *SubStmt) { - void *Mem = C.Allocate(sizeof(AttributedStmt) + - sizeof(Attr*) * (Attrs.size() - 1), + assert(!Attrs.empty() && "Attrs should not be empty"); + void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * Attrs.size(), llvm::alignOf()); 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, unsigned NumAttrs) { assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); - void *Mem = C.Allocate(sizeof(AttributedStmt) + - sizeof(Attr*) * (NumAttrs - 1), + void *Mem = C.Allocate(sizeof(AttributedStmt) + sizeof(Attr *) * NumAttrs, llvm::alignOf()); return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index ce44fea84a..3501817916 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -176,7 +176,7 @@ void ASTStmtReader::VisitAttributedStmt(AttributedStmt *S) { (void)NumAttrs; assert(NumAttrs == S->NumAttrs); 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->AttrLoc = ReadSourceLocation(Record, Idx); } diff --git a/test/PCH/stmt-attrs.cpp b/test/PCH/stmt-attrs.cpp new file mode 100644 index 0000000000..9cf6642709 --- /dev/null +++ b/test/PCH/stmt-attrs.cpp @@ -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 -- 2.40.0