Index: include/clang/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -45,6 +45,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" +#include "llvm/Support/TrailingObjects.h" #include #include #include @@ -1591,6 +1592,16 @@ enum { NumTypeWithKeywordBits = 8 }; + class ElaboratedTypeBitfields { + friend class ElaboratedType; + + unsigned : NumTypeBits; + unsigned : NumTypeWithKeywordBits; + + /// Whether the ElaboratedType has a trailing OwnedTagDecl. + unsigned HasOwnedTagDecl : 1; + }; + class VectorTypeBitfields { friend class VectorType; friend class DependentVectorType; @@ -1687,6 +1698,7 @@ ObjCObjectTypeBitfields ObjCObjectTypeBits; ReferenceTypeBitfields ReferenceTypeBits; TypeWithKeywordBitfields TypeWithKeywordBits; + ElaboratedTypeBitfields ElaboratedTypeBits; VectorTypeBitfields VectorTypeBits; SubstTemplateTypeParmPackTypeBitfields SubstTemplateTypeParmPackTypeBits; TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits; @@ -1712,6 +1724,8 @@ "ReferenceTypeBitfields is larger than 8 bytes!"); static_assert(sizeof(TypeWithKeywordBitfields) <= 8, "TypeWithKeywordBitfields is larger than 8 bytes!"); + static_assert(sizeof(ElaboratedTypeBitfields) <= 8, + "ElaboratedTypeBitfields is larger than 8 bytes!"); static_assert(sizeof(VectorTypeBitfields) <= 8, "VectorTypeBitfields is larger than 8 bytes!"); static_assert(sizeof(SubstTemplateTypeParmPackTypeBitfields) <= 8, @@ -5015,8 +5029,12 @@ /// source code, including tag keywords and any nested-name-specifiers. /// The type itself is always "sugar", used to express what was written /// in the source code but containing no additional semantic information. -class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { +class ElaboratedType final + : public TypeWithKeyword, + public llvm::FoldingSetNode, + private llvm::TrailingObjects { friend class ASTContext; // ASTContext creates these + friend TrailingObjects; /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -5024,26 +5042,29 @@ /// The type that this qualified name refers to. QualType NamedType; - /// The (re)declaration of this tag type owned by this occurrence, or nullptr - /// if none. - TagDecl *OwnedTagDecl; + /// The (re)declaration of this tag type owned by this occurrence is stored + /// as a trailing object if there is one. Use getOwnedTagDecl to obtain + /// it, or obtain a null pointer if there is none. ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl) - : TypeWithKeyword(Keyword, Elaborated, CanonType, - NamedType->isDependentType(), - NamedType->isInstantiationDependentType(), - NamedType->isVariablyModifiedType(), - NamedType->containsUnexpandedParameterPack()), - NNS(NNS), NamedType(NamedType), OwnedTagDecl(OwnedTagDecl) { + : TypeWithKeyword(Keyword, Elaborated, CanonType, + NamedType->isDependentType(), + NamedType->isInstantiationDependentType(), + NamedType->isVariablyModifiedType(), + NamedType->containsUnexpandedParameterPack()), + NNS(NNS), NamedType(NamedType) { + ElaboratedTypeBits.HasOwnedTagDecl = false; + if (OwnedTagDecl) { + ElaboratedTypeBits.HasOwnedTagDecl = true; + *getTrailingObjects() = OwnedTagDecl; + } assert(!(Keyword == ETK_None && NNS == nullptr) && "ElaboratedType cannot have elaborated type keyword " "and name qualifier both null."); } public: - ~ElaboratedType(); - /// Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -5057,11 +5078,14 @@ bool isSugared() const { return true; } /// Return the (re)declaration of this type owned by this occurrence of this - /// type, or nullptr if none. - TagDecl *getOwnedTagDecl() const { return OwnedTagDecl; } + /// type, or nullptr if there is none. + TagDecl *getOwnedTagDecl() const { + return ElaboratedTypeBits.HasOwnedTagDecl ? *getTrailingObjects() + : nullptr; + } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getKeyword(), NNS, NamedType, OwnedTagDecl); + Profile(ID, getKeyword(), NNS, NamedType, getOwnedTagDecl()); } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, @@ -5073,9 +5097,7 @@ ID.AddPointer(OwnedTagDecl); } - static bool classof(const Type *T) { - return T->getTypeClass() == Elaborated; - } + static bool classof(const Type *T) { return T->getTypeClass() == Elaborated; } }; /// Represents a qualified type name for which the type name is Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -4133,8 +4133,10 @@ (void)CheckT; } - T = new (*this, TypeAlignment) - ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl); + void *Mem = Allocate(ElaboratedType::totalSizeToAlloc(!!OwnedTagDecl), + TypeAlignment); + T = new (Mem) ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl); + Types.push_back(T); ElaboratedTypes.InsertNode(T, InsertPos); return QualType(T, 0);