]> granicus.if.org Git - clang/commitdiff
No longer triggering a checked iterator assert on Windows when using std::copy while...
authorAaron Ballman <aaron@aaronballman.com>
Tue, 13 May 2014 14:55:01 +0000 (14:55 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Tue, 13 May 2014 14:55:01 +0000 (14:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208702 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Stmt.h
lib/AST/Stmt.cpp
lib/Serialization/ASTReaderStmt.cpp
test/PCH/stmt-attrs.cpp [new file with mode: 0644]

index 10afca4fbd139778b8a1d9e871ac028481e33c62..88cbb21b81100dad54246a0b001190d7d1801af5 100644 (file)
@@ -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<const Attr*> 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<Attr *const *>(this + 1);
+  }
+  Attr **getAttrArrayPtr() { return reinterpret_cast<Attr **>(this + 1); }
+
 public:
   static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc,
                                 ArrayRef<const Attr*> Attrs, Stmt *SubStmt);
@@ -842,7 +846,7 @@ public:
 
   SourceLocation getAttrLoc() const { return AttrLoc; }
   ArrayRef<const Attr*> getAttrs() const {
-    return ArrayRef<const Attr*>(Attrs, NumAttrs);
+    return ArrayRef<const Attr*>(getAttrArrayPtr(), NumAttrs);
   }
   Stmt *getSubStmt() { return SubStmt; }
   const Stmt *getSubStmt() const { return SubStmt; }
index e6468f760a5b5f786c62a20228fe76f8171d4d01..8588dda363c2b02dbfdf90b0d82dc8363fa9f127 100644 (file)
@@ -285,8 +285,8 @@ const char *LabelStmt::getName() const {
 AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
                                        ArrayRef<const Attr*> 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<AttributedStmt>());
   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<AttributedStmt>());
   return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
 }
index ce44fea84a1399cbe42ccb0323aad036f99f4503..3501817916eb2dc4bda10727bbed2adfb561fc1e 100644 (file)
@@ -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 (file)
index 0000000..9cf6642
--- /dev/null
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++11 -emit-pch -o %t.a %s\r
+// RUN: %clang_cc1 -std=c++11 -include-pch %t.a %s -ast-print -o - | FileCheck %s\r
+\r
+#ifndef HEADER\r
+#define HEADER\r
+\r
+inline void test(int i) {\r
+  switch (i) {\r
+    case 1:\r
+      // Notice that the NullStmt has two attributes.\r
+      [[clang::fallthrough]][[clang::fallthrough]];\r
+    case 2:\r
+      break;\r
+  }\r
+}\r
+\r
+#else\r
+\r
+void foo(void) {\r
+  test(1);\r
+}\r
+\r
+#endif\r