diff options
-rw-r--r-- | include/clang/AST/Type.h | 7 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 17 |
3 files changed, 35 insertions, 33 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index c2d492b3bb..c1b8a775a6 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1179,6 +1179,10 @@ public: /// (C++0x [basic.types]p9) bool isTrivialType() const; + /// \brief Test if this type is a standard-layout type. + /// (C++0x [basic.type]p9) + bool isStandardLayoutType() const; + /// isCXX11PODType() - Return true if this is a POD type according to the /// more relaxed rules of the C++11 standard, regardless of the current /// compilation's language. @@ -2842,9 +2846,6 @@ public: // const, it needs to return false. bool hasConstFields() const { return false; } - /// \brief Whether this class has standard layout - bool hasStandardLayout() const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 55f01e5822..dbced252aa 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -943,9 +943,36 @@ bool Type::isTrivialType() const { return false; } -// This is effectively the intersection of isTrivialType and hasStandardLayout. -// We implement it dircetly to avoid redundant conversions from a type to -// a CXXRecordDecl. +bool Type::isStandardLayoutType() const { + if (isIncompleteType()) + return false; + + // C++0x [basic.types]p9: + // Scalar types, standard-layout class types, arrays of such types, and + // cv-qualified versions of these types are collectively called + // standard-layout types. + const Type *BaseTy = getBaseElementTypeUnsafe(); + assert(BaseTy && "NULL element type"); + if (BaseTy->isScalarType()) return true; + if (const RecordType *RT = BaseTy->getAs<RecordType>()) { + if (const CXXRecordDecl *ClassDecl = + dyn_cast<CXXRecordDecl>(RT->getDecl())) + if (!ClassDecl->hasStandardLayout()) + return false; + + // Default to 'true' for non-C++ class types. + // FIXME: This is a bit dubious, but plain C structs should trivially meet + // all the requirements of standard layout classes. + return true; + } + + // No other types can match. + return false; +} + +// This is effectively the intersection of isTrivialType and +// isStandardLayoutType. We implement it dircetly to avoid redundant +// conversions from a type to a CXXRecordDecl. bool Type::isCXX11PODType() const { if (isIncompleteType()) return false; @@ -1448,17 +1475,6 @@ static uint64_t countBasesWithFields(QualType BaseType) { return BasesWithFields; } -bool RecordType::hasStandardLayout() const { - CXXRecordDecl *RD = cast<CXXRecordDecl>(getDecl()); - if (! RD) { - assert(cast<RecordDecl>(getDecl()) && - "RecordType does not have a corresponding RecordDecl"); - return true; - } - - return RD->hasStandardLayout(); -} - bool EnumType::classof(const TagType *TT) { return isa<EnumDecl>(TT->getDecl()); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d975a155cd..d87752081b 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2438,22 +2438,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, case UTT_IsSigned: return T->isSignedIntegerType(); case UTT_IsStandardLayout: - // Error if T is an incomplete type. - if (Self.RequireCompleteType(KeyLoc, T, diag::err_incomplete_typeid)) - return false; - - // A standard layout type is: - // - a scalar type - // - an array of standard layout types - // - a standard layout class type: - if (EvaluateUnaryTypeTrait(Self, UTT_IsScalar, T, KeyLoc)) - return true; - if (EvaluateUnaryTypeTrait(Self, UTT_IsScalar, C.getBaseElementType(T), - KeyLoc)) - return true; - if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) - return RT->hasStandardLayout(); - return false; + return T->isStandardLayoutType(); case UTT_IsUnsigned: return T->isUnsignedIntegerType(); case UTT_IsVoid: |