diff options
author | Matt Beaumont-Gay <matthewbg@google.com> | 2013-06-25 22:19:15 +0000 |
---|---|---|
committer | Matt Beaumont-Gay <matthewbg@google.com> | 2013-06-25 22:19:15 +0000 |
commit | 35779955b3b845f0d72d0b63bda482c5f64f21f0 (patch) | |
tree | aa72271aeab9021b0db8e7eddc30a344a893a4ca /clang/lib/AST/ASTContext.cpp | |
parent | ba8f17ac1037d1c554f906801e0d1fa6b009f22c (diff) | |
download | bcm5719-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.cpp | 37 |
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); + } } } |