Index: lib/Serialization/ASTReaderDecl.cpp =================================================================== --- lib/Serialization/ASTReaderDecl.cpp +++ lib/Serialization/ASTReaderDecl.cpp @@ -440,6 +440,14 @@ }; } // end anonymous namespace +/// Inherit the default template argument from \p From to \p To. Returns +/// \c false if there is no default template for \p From. +/// It is an error to call this method more than once on \p To, with differing +/// \p From decls. +template +static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From, + Decl *ToD); + template static llvm::iterator_range> merged_redecls(DeclT *D) { @@ -2239,6 +2247,11 @@ if (Record.readInt()) D->setDefaultArgument(GetTypeSourceInfo()); + + if (Record.readInt()) { + inheritDefaultTemplateArgument( + Reader.getContext(), Record.readDeclAs(), D); + } } void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { @@ -2256,8 +2269,14 @@ } else { // Rest of NonTypeTemplateParmDecl. D->ParameterPack = Record.readInt(); + if (Record.readInt()) D->setDefaultArgument(Record.readExpr()); + + if (Record.readInt()) { + inheritDefaultTemplateArgument( + Reader.getContext(), Record.readDeclAs(), D); + } } } @@ -2275,9 +2294,16 @@ } else { // Rest of TemplateTemplateParmDecl. D->ParameterPack = Record.readInt(); + if (Record.readInt()) D->setDefaultArgument(Reader.getContext(), Record.readTemplateArgumentLoc()); + + if (Record.readInt()) { + inheritDefaultTemplateArgument( + Reader.getContext(), Record.readDeclAs(), + D); + } } } @@ -3256,12 +3282,20 @@ /// Inherit the default template argument from \p From to \p To. Returns /// \c false if there is no default template for \p From. +/// It is an error to call this method more than once on \p To, with differing +/// \p From decls. template static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From, Decl *ToD) { auto *To = cast(ToD); if (!From->hasDefaultArgument()) return false; + auto const &DA = To->getDefaultArgStorage(); + if (DA.isSet() && DA.isInherited()) { + assert(DA.getInheritedFrom() == From && + "template arg already inherits from a different decl"); + return true; + } To->setInheritedDefaultArgument(Context, From); return true; } Index: lib/Serialization/ASTWriterDecl.cpp =================================================================== --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -1538,11 +1538,24 @@ Record.push_back(D->wasDeclaredWithTypename()); - bool OwnsDefaultArg = D->hasDefaultArgument() && - !D->defaultArgumentWasInherited(); - Record.push_back(OwnsDefaultArg); - if (OwnsDefaultArg) - Record.AddTypeSourceInfo(D->getDefaultArgumentInfo()); + TypeSourceInfo *ownedDefaultArg = nullptr; + Decl const *inheritsFromDecl = nullptr; + if (D->hasDefaultArgument()) { + if (D->defaultArgumentWasInherited()) { + inheritsFromDecl = D->getDefaultArgStorage().getInheritedFrom(); + } else { + ownedDefaultArg = D->getDefaultArgumentInfo(); + } + } + + Record.push_back(bool(ownedDefaultArg != nullptr)); + if (ownedDefaultArg) { + Record.AddTypeSourceInfo(ownedDefaultArg); + } + Record.push_back(bool(inheritsFromDecl != nullptr)); + if (inheritsFromDecl) { + Record.AddDeclRef(inheritsFromDecl); + } Code = serialization::DECL_TEMPLATE_TYPE_PARM; } @@ -1569,11 +1582,26 @@ } else { // Rest of NonTypeTemplateParmDecl. Record.push_back(D->isParameterPack()); - bool OwnsDefaultArg = D->hasDefaultArgument() && - !D->defaultArgumentWasInherited(); - Record.push_back(OwnsDefaultArg); - if (OwnsDefaultArg) - Record.AddStmt(D->getDefaultArgument()); + + Expr *ownedDefaultArg = nullptr; + Decl const *inheritsFromDecl = nullptr; + if (D->hasDefaultArgument()) { + if (D->defaultArgumentWasInherited()) { + inheritsFromDecl = D->getDefaultArgStorage().getInheritedFrom(); + } else { + ownedDefaultArg = D->getDefaultArgument(); + } + } + + Record.push_back(bool(ownedDefaultArg != nullptr)); + if (ownedDefaultArg) { + Record.AddStmt(ownedDefaultArg); + } + Record.push_back(bool(inheritsFromDecl != nullptr)); + if (inheritsFromDecl) { + Record.AddDeclRef(inheritsFromDecl); + } + Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; } } @@ -1598,11 +1626,26 @@ } else { // Rest of TemplateTemplateParmDecl. Record.push_back(D->isParameterPack()); - bool OwnsDefaultArg = D->hasDefaultArgument() && - !D->defaultArgumentWasInherited(); - Record.push_back(OwnsDefaultArg); - if (OwnsDefaultArg) - Record.AddTemplateArgumentLoc(D->getDefaultArgument()); + + llvm::Optional ownedDefaultArg; + Decl const *inheritsFromDecl = nullptr; + if (D->hasDefaultArgument()) { + if (D->defaultArgumentWasInherited()) { + inheritsFromDecl = D->getDefaultArgStorage().getInheritedFrom(); + } else { + ownedDefaultArg = D->getDefaultArgument(); + } + } + + Record.push_back(bool(ownedDefaultArg.hasValue())); + if (ownedDefaultArg.hasValue()) { + Record.AddTemplateArgumentLoc(*ownedDefaultArg); + } + Record.push_back(bool(inheritsFromDecl != nullptr)); + if (inheritsFromDecl) { + Record.AddDeclRef(inheritsFromDecl); + } + Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM; } } Index: test/PCH/cxx-templates.h =================================================================== --- test/PCH/cxx-templates.h +++ test/PCH/cxx-templates.h @@ -361,3 +361,38 @@ namespace MemberSpecializationLocation { template struct A { static int n; }; } + +// https://bugs.llvm.org/show_bug.cgi?id=34728 +namespace PR34728 { + +// case 1: defaulted `NonTypeTemplateParmDecl`, non-defaulted 2nd tpl param +template +int func1(T const &); + +template +int func1(T const &) { + return foo; +} + +// case 2: defaulted `TemplateTypeParmDecl`, non-defaulted 2nd tpl param +template +A func2(B const &); + +template +A func2(B const &) { + return 69; +} + +// case 3: defaulted `TemplateTemplateParmDecl`, non-defaulted 2nd tpl param +template +struct Container { T const &item; }; + +template