summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
authorMatt Beaumont-Gay <matthewbg@google.com>2013-06-25 22:19:15 +0000
committerMatt Beaumont-Gay <matthewbg@google.com>2013-06-25 22:19:15 +0000
commit35779955b3b845f0d72d0b63bda482c5f64f21f0 (patch)
treeaa72271aeab9021b0db8e7eddc30a344a893a4ca /clang/lib/AST/ASTContext.cpp
parentba8f17ac1037d1c554f906801e0d1fa6b009f22c (diff)
downloadbcm5719-llvm-35779955b3b845f0d72d0b63bda482c5f64f21f0.tar.gz
bcm5719-llvm-35779955b3b845f0d72d0b63bda482c5f64f21f0.zip
Don't try to get the layout of an invalid decl in getDeclAlign.
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. llvm-svn: 184883
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r--clang/lib/AST/ASTContext.cpp37
1 files changed, 20 insertions, 17 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 91059400761..b5ef5fa2adc 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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);
+ }
}
}
OpenPOWER on IntegriCloud