diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -103,12 +103,14 @@ /// The kind of template argument we're storing. struct DA { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; void *QT; ValueDecl *D; }; struct I { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; // We store a decomposed APSInt with the data allocated by ASTContext if // BitWidth > 64. The memory may be shared between multiple // TemplateArgument instances. @@ -124,17 +126,20 @@ void *Type; }; struct A { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; unsigned NumArgs; const TemplateArgument *Args; }; struct TA { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; unsigned NumExpansions; void *Name; }; struct TV { - unsigned Kind; + unsigned Kind : 31; + unsigned IsDefaulted : 1; uintptr_t V; }; union { @@ -147,11 +152,12 @@ public: /// Construct an empty, invalid template argument. - constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} + constexpr TemplateArgument() : TypeOrValue({Null, /* IsDefaulted */ 0, 0}) {} /// Construct a template type argument. TemplateArgument(QualType T, bool isNullPtr = false) { TypeOrValue.Kind = isNullPtr ? NullPtr : Type; + TypeOrValue.IsDefaulted = false; TypeOrValue.V = reinterpret_cast(T.getAsOpaquePtr()); } @@ -161,6 +167,7 @@ TemplateArgument(ValueDecl *D, QualType QT) { assert(D && "Expected decl"); DeclArg.Kind = Declaration; + DeclArg.IsDefaulted = false; DeclArg.QT = QT.getAsOpaquePtr(); DeclArg.D = D; } @@ -186,6 +193,7 @@ /// \param Name The template name. TemplateArgument(TemplateName Name) { TemplateArg.Kind = Template; + TemplateArg.IsDefaulted = false; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = 0; } @@ -203,6 +211,7 @@ /// instantiating TemplateArgument(TemplateName Name, Optional NumExpansions) { TemplateArg.Kind = TemplateExpansion; + TemplateArg.IsDefaulted = false; TemplateArg.Name = Name.getAsVoidPointer(); if (NumExpansions) TemplateArg.NumExpansions = *NumExpansions + 1; @@ -217,6 +226,7 @@ /// occur in a non-dependent, canonical template argument list. TemplateArgument(Expr *E) { TypeOrValue.Kind = Expression; + TypeOrValue.IsDefaulted = false; TypeOrValue.V = reinterpret_cast(E); } @@ -226,6 +236,7 @@ /// outlives the TemplateArgument itself. explicit TemplateArgument(ArrayRef Args) { this->Args.Kind = Pack; + this->Args.IsDefaulted = false; this->Args.Args = Args.data(); this->Args.NumArgs = Args.size(); } @@ -334,6 +345,10 @@ Integer.Type = T.getAsOpaquePtr(); } + void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; } + + bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; } + /// If this is a non-type template argument, get its type. Otherwise, /// returns a null QualType. QualType getNonTypeTemplateArgumentType() const; diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -162,6 +162,7 @@ TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type) { Integer.Kind = Integral; + Integer.IsDefaulted = false; // Copy the APSInt value into our decomposed form. Integer.BitWidth = Value.getBitWidth(); Integer.IsUnsigned = Value.isUnsigned();