From d24ffe47c9a2b5947a97e9c4c4c2fad7e7611c29 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 10 Jun 2015 01:47:58 +0000 Subject: [PATCH] [modules] Reconstruct template default argument inheritance on reload rather than wasting storage and triggering eager deserializations by serializing it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@239454 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTReaderDecl.cpp | 61 +++++++++++++++++++++-------- lib/Serialization/ASTWriterDecl.cpp | 25 ++++++------ 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 63841fbca1..af125cf660 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -2034,11 +2034,6 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { D->setDeclaredWithTypename(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(GetTypeSourceInfo(Record, Idx)); } @@ -2057,12 +2052,6 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { // Rest of NonTypeTemplateParmDecl. 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.ReadExpr(F)); } } @@ -2081,12 +2070,6 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { // Rest of TemplateTemplateParmDecl. 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)); } @@ -2917,6 +2900,44 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader, ...) { llvm_unreachable("attachPreviousDecl on non-redeclarable declaration"); } +/// Inherit the default template argument from \p From to \p To. Returns +/// \c false if there is no default template for \p From. +template +static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From, + Decl *ToD) { + auto *To = cast(ToD); + if (!From->hasDefaultArgument()) + return false; + if (!To->hasDefaultArgument()) + To->setInheritedDefaultArgument(Context, From); + return true; +} + +static void inheritDefaultTemplateArguments(ASTContext &Context, + TemplateDecl *From, + TemplateDecl *To) { + auto *FromTP = From->getTemplateParameters(); + auto *ToTP = To->getTemplateParameters(); + assert(FromTP->size() == ToTP->size() && "merged mismatched templates?"); + + for (unsigned I = 0, N = FromTP->size(); I != N; ++I) { + NamedDecl *FromParam = FromTP->getParam(N - I - 1); + NamedDecl *ToParam = ToTP->getParam(N - I - 1); + + if (auto *FTTP = dyn_cast(FromParam)) { + if (inheritDefaultTemplateArgument(Context, FTTP, ToParam)) + break; + } else if (auto *FNTTP = dyn_cast(FromParam)) { + if (inheritDefaultTemplateArgument(Context, FNTTP, ToParam)) + break; + } else { + if (inheritDefaultTemplateArgument( + Context, cast(FromParam), ToParam)) + break; + } + } +} + void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous, Decl *Canon) { assert(D && Previous); @@ -2943,6 +2964,12 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, // be too. if (Previous->Used) D->Used = true; + + // If the declaration declares a template, it may inherit default arguments + // from the previous declaration. + if (TemplateDecl *TD = dyn_cast(D)) + inheritDefaultTemplateArguments(Reader.getContext(), + cast(Previous), TD); } template diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index f08f140991..29b948d321 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -1380,10 +1380,11 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { VisitTypeDecl(D); Record.push_back(D->wasDeclaredWithTypename()); - Record.push_back(D->defaultArgumentWasInherited()); - if (D->defaultArgumentWasInherited()) - Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record); - else + + bool OwnsDefaultArg = D->hasDefaultArgument() && + !D->defaultArgumentWasInherited(); + Record.push_back(OwnsDefaultArg); + if (OwnsDefaultArg) Writer.AddTypeSourceInfo(D->getDefaultArgumentInfo(), Record); Code = serialization::DECL_TEMPLATE_TYPE_PARM; @@ -1411,10 +1412,10 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { } else { // Rest of NonTypeTemplateParmDecl. Record.push_back(D->isParameterPack()); - Record.push_back(D->defaultArgumentWasInherited()); - if (D->defaultArgumentWasInherited()) - Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record); - else + bool OwnsDefaultArg = D->hasDefaultArgument() && + !D->defaultArgumentWasInherited(); + Record.push_back(OwnsDefaultArg); + if (OwnsDefaultArg) Writer.AddStmt(D->getDefaultArgument()); Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; } @@ -1441,10 +1442,10 @@ void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { } else { // Rest of TemplateTemplateParmDecl. Record.push_back(D->isParameterPack()); - Record.push_back(D->defaultArgumentWasInherited()); - if (D->defaultArgumentWasInherited()) - Writer.AddDeclRef(D->getDefaultArgStorage().getInheritedFrom(), Record); - else + bool OwnsDefaultArg = D->hasDefaultArgument() && + !D->defaultArgumentWasInherited(); + Record.push_back(OwnsDefaultArg); + if (OwnsDefaultArg) Writer.AddTemplateArgumentLoc(D->getDefaultArgument(), Record); Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM; } -- 2.50.1