From 1469b9196ce4394486371b39e9fa5d44975d3a29 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 10 Jun 2015 00:29:03 +0000 Subject: [PATCH] Refactor storage of default template arguments. This is just a preparatory step towards fixing visibility for default template arguments in modules builds. llvm-svn: 239447 --- clang/include/clang/AST/DeclTemplate.h | 162 ++++++++++++++------- clang/lib/AST/DeclTemplate.cpp | 23 +-- clang/lib/Sema/SemaTemplate.cpp | 22 +-- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 +- clang/lib/Serialization/ASTReaderDecl.cpp | 35 +++-- clang/lib/Serialization/ASTWriterDecl.cpp | 20 ++- .../test/Modules/Inputs/template-default-args/a.h | 1 + .../Inputs/template-default-args/module.modulemap | 6 +- clang/test/Modules/template-default-args.cpp | 6 + 9 files changed, 181 insertions(+), 102 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 90cfb20..324f0e8 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -217,6 +217,57 @@ public: } }; +/// Storage for a default argument. +template +class DefaultArgStorage { + llvm::PointerUnion ValueOrInherited; + + static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) { + const DefaultArgStorage &Storage = Parm->getDefaultArgStorage(); + if (auto *Prev = Storage.ValueOrInherited.template dyn_cast()) + Parm = Prev; + assert( + Parm->getDefaultArgStorage().ValueOrInherited.template is() && + "should only be one level of indirection"); + return Parm; + } + +public: + DefaultArgStorage() : ValueOrInherited(ArgType()) {} + + /// Determine whether there is a default argument for this parameter. + bool isSet() const { return !ValueOrInherited.isNull(); } + /// Determine whether the default argument for this parameter was inherited + /// from a previous declaration of the same entity. + bool isInherited() const { return ValueOrInherited.template is(); } + /// Get the default argument's value. + ArgType get() const { + const DefaultArgStorage *Storage = this; + if (auto *Prev = ValueOrInherited.template dyn_cast()) + Storage = &Prev->getDefaultArgStorage(); + return Storage->ValueOrInherited.template get(); + } + /// Get the parameter from which we inherit the default argument, if any. + /// This is the parameter on which the default argument was actually written. + const ParmDecl *getInheritedFrom() const { + return ValueOrInherited.template dyn_cast(); + } + /// Set the default argument. + void set(ArgType Arg) { + assert(!isSet() && "default argument already set"); + ValueOrInherited = Arg; + } + /// Set that the default argument was inherited from another parameter. + void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) { + assert(!isSet() && "default argument already set"); + ValueOrInherited = getParmOwningDefaultArg(InheritedFrom); + } + /// Remove the default argument, even if it was inherited. + void clear() { + ValueOrInherited = ArgType(); + } +}; + //===----------------------------------------------------------------------===// // Kinds of Templates //===----------------------------------------------------------------------===// @@ -942,18 +993,16 @@ class TemplateTypeParmDecl : public TypeDecl { /// If false, it was declared with the 'class' keyword. bool Typename : 1; - /// \brief Whether this template type parameter inherited its - /// default argument. - bool InheritedDefault : 1; - /// \brief The default template argument, if any. - TypeSourceInfo *DefaultArgument; + typedef DefaultArgStorage + DefArgStorage; + DefArgStorage DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, SourceLocation IdLoc, IdentifierInfo *Id, bool Typename) : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), - InheritedDefault(false), DefaultArgument() { } + DefaultArgument() { } /// Sema creates these on the stack during auto type deduction. friend class Sema; @@ -974,35 +1023,45 @@ public: /// If not, it was declared with the 'class' keyword. bool wasDeclaredWithTypename() const { return Typename; } + const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } + /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument != nullptr; } + bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. - QualType getDefaultArgument() const { return DefaultArgument->getType(); } + QualType getDefaultArgument() const { + return DefaultArgument.get()->getType(); + } /// \brief Retrieves the default argument's source information, if any. - TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; } + TypeSourceInfo *getDefaultArgumentInfo() const { + return DefaultArgument.get(); + } /// \brief Retrieves the location of the default argument declaration. SourceLocation getDefaultArgumentLoc() const; /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. - bool defaultArgumentWasInherited() const { return InheritedDefault; } + bool defaultArgumentWasInherited() const { + return DefaultArgument.isInherited(); + } - /// \brief Set the default argument for this template parameter, and - /// whether that default argument was inherited from another - /// declaration. - void setDefaultArgument(TypeSourceInfo *DefArg, bool Inherited) { - DefaultArgument = DefArg; - InheritedDefault = Inherited; + /// \brief Set the default argument for this template parameter. + void setDefaultArgument(TypeSourceInfo *DefArg) { + DefaultArgument.set(DefArg); + } + /// \brief Set that this default argument was inherited from another + /// parameter. + void setInheritedDefaultArgument(const ASTContext &C, + TemplateTypeParmDecl *Prev) { + DefaultArgument.setInherited(C, Prev); } /// \brief Removes the default argument of this template parameter. void removeDefaultArgument() { - DefaultArgument = nullptr; - InheritedDefault = false; + DefaultArgument.clear(); } /// \brief Set whether this template type parameter was declared with @@ -1034,7 +1093,8 @@ class NonTypeTemplateParmDecl : public DeclaratorDecl, protected TemplateParmPosition { /// \brief The default template argument, if any, and whether or not /// it was inherited. - llvm::PointerIntPair DefaultArgumentAndInherited; + typedef DefaultArgStorage DefArgStorage; + DefArgStorage DefaultArgument; // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index // down here to save memory. @@ -1055,9 +1115,8 @@ class NonTypeTemplateParmDecl IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false), - ParameterPack(ParameterPack), ExpandedParameterPack(false), - NumExpandedTypes(0) + TemplateParmPosition(D, P), ParameterPack(ParameterPack), + ExpandedParameterPack(false), NumExpandedTypes(0) { } NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, @@ -1097,16 +1156,14 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } + /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { - return DefaultArgumentAndInherited.getPointer() != nullptr; - } + bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { - return DefaultArgumentAndInherited.getPointer(); - } + Expr *getDefaultArgument() const { return DefaultArgument.get(); } /// \brief Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; @@ -1114,22 +1171,20 @@ public: /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { - return DefaultArgumentAndInherited.getInt(); + return DefaultArgument.isInherited(); } /// \brief Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(Expr *DefArg, bool Inherited) { - DefaultArgumentAndInherited.setPointer(DefArg); - DefaultArgumentAndInherited.setInt(Inherited); + void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); } + void setInheritedDefaultArgument(const ASTContext &C, + NonTypeTemplateParmDecl *Parm) { + DefaultArgument.setInherited(C, Parm); } /// \brief Removes the default argument of this template parameter. - void removeDefaultArgument() { - DefaultArgumentAndInherited.setPointer(nullptr); - DefaultArgumentAndInherited.setInt(false); - } + void removeDefaultArgument() { DefaultArgument.clear(); } /// \brief Whether this parameter is a non-type template parameter pack. /// @@ -1217,10 +1272,10 @@ class TemplateTemplateParmDecl : public TemplateDecl, { void anchor() override; - /// DefaultArgument - The default template argument, if any. - TemplateArgumentLoc DefaultArgument; - /// Whether or not the default argument was inherited. - bool DefaultArgumentWasInherited; + /// \brief The default template argument, if any. + typedef DefaultArgStorage + DefArgStorage; + DefArgStorage DefaultArgument; /// \brief Whether this parameter is a parameter pack. bool ParameterPack; @@ -1237,8 +1292,7 @@ class TemplateTemplateParmDecl : public TemplateDecl, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument(), - DefaultArgumentWasInherited(false), ParameterPack(ParameterPack), + TemplateParmPosition(D, P), ParameterPack(ParameterPack), ExpandedParameterPack(false), NumExpandedParams(0) { } @@ -1322,15 +1376,16 @@ public: return reinterpret_cast(this + 1)[I]; } + const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } + /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { - return !DefaultArgument.getArgument().isNull(); - } + bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. const TemplateArgumentLoc &getDefaultArgument() const { - return DefaultArgument; + static const TemplateArgumentLoc None; + return DefaultArgument.isSet() ? *DefaultArgument.get() : None; } /// \brief Retrieve the location of the default argument, if any. @@ -1339,22 +1394,21 @@ public: /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { - return DefaultArgumentWasInherited; + return DefaultArgument.isInherited(); } /// \brief Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(const TemplateArgumentLoc &DefArg, bool Inherited) { - DefaultArgument = DefArg; - DefaultArgumentWasInherited = Inherited; + void setDefaultArgument(const ASTContext &C, + const TemplateArgumentLoc &DefArg); + void setInheritedDefaultArgument(const ASTContext &C, + TemplateTemplateParmDecl *Prev) { + DefaultArgument.setInherited(C, Prev); } /// \brief Removes the default argument of this template parameter. - void removeDefaultArgument() { - DefaultArgument = TemplateArgumentLoc(); - DefaultArgumentWasInherited = false; - } + void removeDefaultArgument() { DefaultArgument.clear(); } SourceRange getSourceRange() const override LLVM_READONLY { SourceLocation End = getLocation(); diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 6374a92..c4e2c00 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -504,14 +504,14 @@ TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { return hasDefaultArgument() - ? DefaultArgument->getTypeLoc().getBeginLoc() - : SourceLocation(); + ? getDefaultArgumentInfo()->getTypeLoc().getBeginLoc() + : SourceLocation(); } SourceRange TemplateTypeParmDecl::getSourceRange() const { if (hasDefaultArgument() && !defaultArgumentWasInherited()) return SourceRange(getLocStart(), - DefaultArgument->getTypeLoc().getEndLoc()); + getDefaultArgumentInfo()->getTypeLoc().getEndLoc()); else return TypeDecl::getSourceRange(); } @@ -543,10 +543,8 @@ NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(DeclContext *DC, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos) : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), - TemplateParmPosition(D, P), DefaultArgumentAndInherited(nullptr, false), - ParameterPack(true), ExpandedParameterPack(true), - NumExpandedTypes(NumExpandedTypes) -{ + TemplateParmPosition(D, P), ParameterPack(true), + ExpandedParameterPack(true), NumExpandedTypes(NumExpandedTypes) { if (ExpandedTypes && ExpandedTInfos) { void **TypesAndInfos = reinterpret_cast(this + 1); for (unsigned I = 0; I != NumExpandedTypes; ++I) { @@ -621,8 +619,7 @@ TemplateTemplateParmDecl::TemplateTemplateParmDecl( IdentifierInfo *Id, TemplateParameterList *Params, unsigned NumExpansions, TemplateParameterList * const *Expansions) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument(), - DefaultArgumentWasInherited(false), ParameterPack(true), + TemplateParmPosition(D, P), ParameterPack(true), ExpandedParameterPack(true), NumExpandedParams(NumExpansions) { if (Expansions) std::memcpy(reinterpret_cast(this + 1), Expansions, @@ -663,6 +660,14 @@ TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, nullptr, NumExpansions, nullptr); } +void TemplateTemplateParmDecl::setDefaultArgument( + const ASTContext &C, const TemplateArgumentLoc &DefArg) { + if (DefArg.getArgument().isNull()) + DefaultArgument.set(nullptr); + else + DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg)); +} + //===----------------------------------------------------------------------===// // TemplateArgumentList Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 19c0f2a..941672c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -602,7 +602,7 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, return Param; } - Param->setDefaultArgument(DefaultTInfo, false); + Param->setDefaultArgument(DefaultTInfo); } return Param; @@ -723,7 +723,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, } Default = DefaultRes.get(); - Param->setDefaultArgument(Default, false); + Param->setDefaultArgument(Default); } return Param; @@ -799,7 +799,7 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, UPPC_DefaultArgument)) return Param; - Param->setDefaultArgument(DefaultArg, false); + Param->setDefaultArgument(Context, DefaultArg); } return Param; @@ -1328,8 +1328,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(), - true); + NewTypeParm->setInheritedDefaultArgument(Context, OldTypeParm); PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc(); } else if (NewTypeParm->hasDefaultArgument()) { SawDefaultArgument = true; @@ -1375,12 +1374,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - // FIXME: We need to create a new kind of "default argument" - // expression that points to a previous non-type template - // parameter. - NewNonTypeParm->setDefaultArgument( - OldNonTypeParm->getDefaultArgument(), - /*Inherited=*/ true); + NewNonTypeParm->setInheritedDefaultArgument(Context, OldNonTypeParm); PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc(); } else if (NewNonTypeParm->hasDefaultArgument()) { SawDefaultArgument = true; @@ -1424,11 +1418,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) { // Merge the default argument from the old declaration to the // new declaration. - // FIXME: We need to create a new kind of "default argument" expression - // that points to a previous template template parameter. - NewTemplateParm->setDefaultArgument( - OldTemplateParm->getDefaultArgument(), - /*Inherited=*/ true); + NewTemplateParm->setInheritedDefaultArgument(Context, OldTemplateParm); PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgument().getLocation(); } else if (NewTemplateParm->hasDefaultArgument()) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5c994f8..d0a5739 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1927,7 +1927,7 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs, D->getDefaultArgumentLoc(), D->getDeclName()); if (InstantiatedDefaultArg) - Inst->setDefaultArgument(InstantiatedDefaultArg, false); + Inst->setDefaultArgument(InstantiatedDefaultArg); } // Introduce this template parameter's instantiation into the instantiation @@ -2081,7 +2081,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( if (D->hasDefaultArgument()) { ExprResult Value = SemaRef.SubstExpr(D->getDefaultArgument(), TemplateArgs); if (!Value.isInvalid()) - Param->setDefaultArgument(Value.get(), false); + Param->setDefaultArgument(Value.get()); } // Introduce this template parameter's instantiation into the instantiation @@ -2215,10 +2215,10 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( D->getDefaultArgument().getTemplateNameLoc(), TemplateArgs); if (!TName.isNull()) Param->setDefaultArgument( + SemaRef.Context, TemplateArgumentLoc(TemplateArgument(TName), D->getDefaultArgument().getTemplateQualifierLoc(), - D->getDefaultArgument().getTemplateNameLoc()), - false); + D->getDefaultArgument().getTemplateNameLoc())); } Param->setAccess(AS_public); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 02273ed..63841fb 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2033,9 +2033,13 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { D->setDeclaredWithTypename(Record[Idx++]); - bool Inherited = Record[Idx++]; - TypeSourceInfo *DefArg = GetTypeSourceInfo(Record, Idx); - D->setDefaultArgument(DefArg, Inherited); + if (Record[Idx++]) + // FIXME: Rebuild inherited default argument chain when linking together + // the redecl chain. + D->setInheritedDefaultArgument( + Reader.getContext(), ReadDeclAs(Record, Idx)); + else + D->setDefaultArgument(GetTypeSourceInfo(Record, Idx)); } void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { @@ -2052,11 +2056,14 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { } else { // Rest of NonTypeTemplateParmDecl. D->ParameterPack = Record[Idx++]; - if (Record[Idx++]) { - Expr *DefArg = Reader.ReadExpr(F); - bool Inherited = Record[Idx++]; - D->setDefaultArgument(DefArg, Inherited); - } + if (Record[Idx++]) + // FIXME: Rebuild inherited default argument chain when linking together + // the redecl chain. + D->setInheritedDefaultArgument( + Reader.getContext(), + ReadDeclAs(Record, Idx)); + else + D->setDefaultArgument(Reader.ReadExpr(F)); } } @@ -2072,10 +2079,16 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { Data[I] = Reader.ReadTemplateParameterList(F, Record, Idx); } else { // Rest of TemplateTemplateParmDecl. - TemplateArgumentLoc Arg = Reader.ReadTemplateArgumentLoc(F, Record, Idx); - bool IsInherited = Record[Idx++]; - D->setDefaultArgument(Arg, IsInherited); D->ParameterPack = Record[Idx++]; + if (Record[Idx++]) + // FIXME: Rebuild inherited default argument chain when linking together + // the redecl chain. + D->setInheritedDefaultArgument( + Reader.getContext(), + ReadDeclAs(Record, Idx)); + else + D->setDefaultArgument(Reader.getContext(), + Reader.ReadTemplateArgumentLoc(F, Record, Idx)); } } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 0fa4f93..f08f140 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1381,7 +1381,10 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { Record.push_back(D->wasDeclaredWithTypename()); Record.push_back(D->defaultArgumentWasInherited()); - Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record); + if (D->defaultArgumentWasInherited()) + Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record); + else + Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record); Code = serialization::DECL_TEMPLATE_TYPE_PARM; } @@ -1408,11 +1411,11 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { } else { // Rest of NonTypeTemplateParmDecl. Record.push_back(D->isParameterPack()); - Record.push_back(D->getDefaultArgument() != nullptr); - if (D->getDefaultArgument()) { + Record.push_back(D->defaultArgumentWasInherited()); + if (D->defaultArgumentWasInherited()) + Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record); + else Writer.AddStmt(D->getDefaultArgument()); - Record.push_back(D->defaultArgumentWasInherited()); - } Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; } } @@ -1437,9 +1440,12 @@ void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK; } else { // Rest of TemplateTemplateParmDecl. - Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record); - Record.push_back(D->defaultArgumentWasInherited()); Record.push_back(D->isParameterPack()); + Record.push_back(D->defaultArgumentWasInherited()); + if (D->defaultArgumentWasInherited()) + Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record); + else + Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record); Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM; } } diff --git a/clang/test/Modules/Inputs/template-default-args/a.h b/clang/test/Modules/Inputs/template-default-args/a.h index 1ef1ea5..3e41535 100644 --- a/clang/test/Modules/Inputs/template-default-args/a.h +++ b/clang/test/Modules/Inputs/template-default-args/a.h @@ -2,3 +2,4 @@ template struct A {}; template struct B {}; template struct C; template struct D; +template struct E; diff --git a/clang/test/Modules/Inputs/template-default-args/module.modulemap b/clang/test/Modules/Inputs/template-default-args/module.modulemap index 6182e6b..d54dfc3 100644 --- a/clang/test/Modules/Inputs/template-default-args/module.modulemap +++ b/clang/test/Modules/Inputs/template-default-args/module.modulemap @@ -1 +1,5 @@ -module X { module A { header "a.h" } module B { header "b.h" } } +module X { + module A { header "a.h" } + module B { header "b.h" } + module C { header "c.h" } +} diff --git a/clang/test/Modules/template-default-args.cpp b/clang/test/Modules/template-default-args.cpp index 63187b8..97569f0 100644 --- a/clang/test/Modules/template-default-args.cpp +++ b/clang/test/Modules/template-default-args.cpp @@ -7,6 +7,7 @@ template struct A; template struct B; template struct C; template struct D; +template struct E {}; #include "b.h" @@ -15,8 +16,13 @@ template struct B {}; template struct B; template struct C; template struct D {}; +template struct F {}; + +#include "c.h" A<> a; B<> b; extern C<> c; D<> d; +E<> e; +F<> f; -- 2.7.4