]> granicus.if.org Git - clang/commitdiff
Don't try to get the layout of an invalid decl in getDeclAlign.
authorMatt Beaumont-Gay <matthewbg@google.com>
Tue, 25 Jun 2013 22:19:15 +0000 (22:19 +0000)
committerMatt Beaumont-Gay <matthewbg@google.com>
Tue, 25 Jun 2013 22:19:15 +0000 (22:19 +0000)
When the decl that we're getting alignment for is a FieldDecl, and the field's
parent record is invalid, skip the actual field alignment calculation (and
return 1-byte alignment in the general case).

Also, assert in in getASTRecordLayout that the decl is valid. This was
inspired by PR16292; see also r184581 and r184751.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184883 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTContext.cpp
lib/AST/RecordLayoutBuilder.cpp
test/SemaCXX/alignof.cpp

index 91059400761f90c45d45b19b0a22a79d4e4653e1..b5ef5fa2adc42ca89f5468ee37de7ce1bcd16bdf 100644 (file)
@@ -1321,24 +1321,27 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const {
     // a max-field-alignment constraint (#pragma pack).  So calculate
     // the actual alignment of the field within the struct, and then
     // (as we're expected to) constrain that by the alignment of the type.
-    if (const FieldDecl *field = dyn_cast<FieldDecl>(VD)) {
-      // So calculate the alignment of the field.
-      const ASTRecordLayout &layout = getASTRecordLayout(field->getParent());
-
-      // Start with the record's overall alignment.
-      unsigned fieldAlign = toBits(layout.getAlignment());
-
-      // Use the GCD of that and the offset within the record.
-      uint64_t offset = layout.getFieldOffset(field->getFieldIndex());
-      if (offset > 0) {
-        // Alignment is always a power of 2, so the GCD will be a power of 2,
-        // which means we get to do this crazy thing instead of Euclid's.
-        uint64_t lowBitOfOffset = offset & (~offset + 1);
-        if (lowBitOfOffset < fieldAlign)
-          fieldAlign = static_cast<unsigned>(lowBitOfOffset);
-      }
+    if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) {
+      const RecordDecl *Parent = Field->getParent();
+      // We can only produce a sensible answer if the record is valid.
+      if (!Parent->isInvalidDecl()) {
+        const ASTRecordLayout &Layout = getASTRecordLayout(Parent);
+
+        // Start with the record's overall alignment.
+        unsigned FieldAlign = toBits(Layout.getAlignment());
+
+        // Use the GCD of that and the offset within the record.
+        uint64_t Offset = Layout.getFieldOffset(Field->getFieldIndex());
+        if (Offset > 0) {
+          // Alignment is always a power of 2, so the GCD will be a power of 2,
+          // which means we get to do this crazy thing instead of Euclid's.
+          uint64_t LowBitOfOffset = Offset & (~Offset + 1);
+          if (LowBitOfOffset < FieldAlign)
+            FieldAlign = static_cast<unsigned>(LowBitOfOffset);
+        }
 
-      Align = std::min(Align, fieldAlign);
+        Align = std::min(Align, FieldAlign);
+      }
     }
   }
 
index 4cd05b7f60f01115466be3731a24329f00febcd5..c4ee565c8ad0e586cd09dd02318c948f070f5e74 100644 (file)
@@ -2468,6 +2468,7 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
     
   D = D->getDefinition();
   assert(D && "Cannot get layout of forward declarations!");
+  assert(!D->isInvalidDecl() && "Cannot get layout of invalid decl!");
   assert(D->isCompleteDefinition() && "Cannot layout type before complete!");
 
   // Look up this layout, if already laid out, return what we have.
index a9de1ad07c9f41abc0307547176be3eeb91c8af6..ca673c42ebd7e15ff1dfbf90c15ebf53d62ff0fc 100644 (file)
@@ -9,7 +9,7 @@ struct S0 {
   auto test2() -> char(&)[__alignof__(x)]; // expected-error {{invalid application of 'alignof' to a field of a class still being defined}}
 };
 
-struct S1; // expected-note 5 {{forward declaration}}
+struct S1; // expected-note 6 {{forward declaration}}
 extern S1 s1;
 const int test3 = __alignof__(s1); // expected-error {{invalid application of 'alignof' to an incomplete type 'S1'}}
 
@@ -50,3 +50,11 @@ struct S4 {
   static const int test1 = __alignof__(S0::x);
   auto test2() -> char(&)[__alignof__(x)];
 };
+
+// Regression test for asking for the alignment of a field within an invalid
+// record.
+struct S5 {
+  S1 s;  // expected-error {{incomplete type}}
+  int x;
+};
+const int test8 = __alignof__(S5::x);