Index: cfe/trunk/include/clang/AST/Type.h =================================================================== --- cfe/trunk/include/clang/AST/Type.h +++ cfe/trunk/include/clang/AST/Type.h @@ -1571,6 +1571,8 @@ unsigned Keyword : 8; }; + enum { NumTypeWithKeywordBits = 8 }; + class VectorTypeBitfields { friend class VectorType; friend class DependentVectorType; @@ -1624,6 +1626,22 @@ unsigned NumArgs; }; + class DependentTemplateSpecializationTypeBitfields { + friend class DependentTemplateSpecializationType; + + unsigned : NumTypeBits; + unsigned : NumTypeWithKeywordBits; + + /// The number of template arguments named in this class template + /// specialization, which is expected to be able to hold at least 1024 + /// according to [implimits]. However, as this limit is somewhat easy to + /// hit with template metaprogramming we'd prefer to keep it as large + /// as possible. At the moment it has been left as a non-bitfield since + /// this type safely fits in 64 bits as an unsigned, so there is no reason + /// to introduce the performance impact of a bitfield. + unsigned NumArgs; + }; + class PackExpansionTypeBitfields { friend class PackExpansionType; @@ -1655,6 +1673,8 @@ TypeWithKeywordBitfields TypeWithKeywordBits; VectorTypeBitfields VectorTypeBits; TemplateSpecializationTypeBitfields TemplateSpecializationTypeBits; + DependentTemplateSpecializationTypeBitfields + DependentTemplateSpecializationTypeBits; PackExpansionTypeBitfields PackExpansionTypeBits; static_assert(sizeof(TypeBitfields) <= 8, @@ -1680,6 +1700,9 @@ static_assert(sizeof(TemplateSpecializationTypeBitfields) <= 8, "TemplateSpecializationTypeBitfields is larger" " than 8 bytes!"); + static_assert(sizeof(DependentTemplateSpecializationTypeBitfields) <= 8, + "DependentTemplateSpecializationTypeBitfields is larger" + " than 8 bytes!"); static_assert(sizeof(PackExpansionTypeBitfields) <= 8, "PackExpansionTypeBitfields is larger than 8 bytes"); }; @@ -5123,10 +5146,6 @@ /// The identifier of the template. const IdentifierInfo *Name; - /// The number of template arguments named in this class template - /// specialization. - unsigned NumArgs; - DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, @@ -5151,12 +5170,14 @@ } /// Retrieve the number of template arguments. - unsigned getNumArgs() const { return NumArgs; } + unsigned getNumArgs() const { + return DependentTemplateSpecializationTypeBits.NumArgs; + } const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h ArrayRef template_arguments() const { - return {getArgs(), NumArgs}; + return {getArgs(), getNumArgs()}; } using iterator = const TemplateArgument *; @@ -5168,7 +5189,7 @@ QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { - Profile(ID, Context, getKeyword(), NNS, Name, {getArgs(), NumArgs}); + Profile(ID, Context, getKeyword(), NNS, Name, {getArgs(), getNumArgs()}); } static void Profile(llvm::FoldingSetNodeID &ID, Index: cfe/trunk/lib/AST/Type.cpp =================================================================== --- cfe/trunk/lib/AST/Type.cpp +++ cfe/trunk/lib/AST/Type.cpp @@ -2604,7 +2604,8 @@ : TypeWithKeyword(Keyword, DependentTemplateSpecialization, Canon, true, true, /*VariablyModified=*/false, NNS && NNS->containsUnexpandedParameterPack()), - NNS(NNS), Name(Name), NumArgs(Args.size()) { + NNS(NNS), Name(Name) { + DependentTemplateSpecializationTypeBits.NumArgs = Args.size(); assert((!NNS || NNS->isDependent()) && "DependentTemplateSpecializatonType requires dependent qualifier"); TemplateArgument *ArgBuffer = getArgBuffer();