aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/RecordLayoutBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r--lib/AST/RecordLayoutBuilder.cpp57
1 files changed, 49 insertions, 8 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp
index 72851dfa1e..42c3ba31bc 100644
--- a/lib/AST/RecordLayoutBuilder.cpp
+++ b/lib/AST/RecordLayoutBuilder.cpp
@@ -2411,6 +2411,48 @@ RecordLayoutBuilder::Diag(SourceLocation Loc, unsigned DiagID) {
return Context.getDiagnostics().Report(Loc, DiagID);
}
+/// Does the target C++ ABI require us to skip over the tail-padding
+/// of the given class (considering it as a base class) when allocating
+/// objects?
+static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) {
+ switch (ABI.getTailPaddingUseRules()) {
+ case TargetCXXABI::AlwaysUseTailPadding:
+ return false;
+
+ case TargetCXXABI::UseTailPaddingUnlessPOD03:
+ // FIXME: To the extent that this is meant to cover the Itanium ABI
+ // rules, we should implement the restrictions about over-sized
+ // bitfields:
+ //
+ // http://mentorembedded.github.com/cxx-abi/abi.html#POD :
+ // In general, a type is considered a POD for the purposes of
+ // layout if it is a POD type (in the sense of ISO C++
+ // [basic.types]). However, a POD-struct or POD-union (in the
+ // sense of ISO C++ [class]) with a bitfield member whose
+ // declared width is wider than the declared type of the
+ // bitfield is not a POD for the purpose of layout. Similarly,
+ // an array type is not a POD for the purpose of layout if the
+ // element type of the array is not a POD for the purpose of
+ // layout.
+ //
+ // Where references to the ISO C++ are made in this paragraph,
+ // the Technical Corrigendum 1 version of the standard is
+ // intended.
+ return RD->isPOD();
+
+ case TargetCXXABI::UseTailPaddingUnlessPOD11:
+ // This is equivalent to RD->getTypeForDecl().isCXX11PODType(),
+ // but with a lot of abstraction penalty stripped off. This does
+ // assume that these properties are set correctly even in C++98
+ // mode; fortunately, that is true because we want to assign
+ // consistently semantics to the type-traits intrinsics (or at
+ // least as many of them as possible).
+ return RD->isTrivial() && RD->isStandardLayout();
+ }
+
+ llvm_unreachable("bad tail-padding use kind");
+}
+
/// getASTRecordLayout - Get or compute information about the layout of the
/// specified record (struct/union/class), which indicates its size and field
/// position information.
@@ -2455,18 +2497,17 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const {
Builder.Layout(RD);
}
- // FIXME: This is not always correct. See the part about bitfields at
- // http://www.codesourcery.com/public/cxx-abi/abi.html#POD for more info.
- // FIXME: IsPODForThePurposeOfLayout should be stored in the record layout.
- // This does not affect the calculations of MSVC layouts
- bool IsPODForThePurposeOfLayout =
- (!Builder.isMicrosoftCXXABI() && cast<CXXRecordDecl>(D)->isPOD());
+ // In certain situations, we are allowed to lay out objects in the
+ // tail-padding of base classes. This is ABI-dependent.
+ // FIXME: this should be stored in the record layout.
+ bool skipTailPadding =
+ mustSkipTailPadding(getTargetInfo().getCXXABI(), cast<CXXRecordDecl>(D));
// FIXME: This should be done in FinalizeLayout.
CharUnits DataSize =
- IsPODForThePurposeOfLayout ? Builder.getSize() : Builder.getDataSize();
+ skipTailPadding ? Builder.getSize() : Builder.getDataSize();
CharUnits NonVirtualSize =
- IsPODForThePurposeOfLayout ? DataSize : Builder.NonVirtualSize;
+ skipTailPadding ? DataSize : Builder.NonVirtualSize;
NewEntry =
new (*this) ASTRecordLayout(*this, Builder.getSize(),