// 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);
+ }
}
}
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'}}
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);