[modules] Reconstruct template default argument inheritance on reload rather

than wasting storage and triggering eager deserializations by serializing it.

llvm-svn: 239454
This commit is contained in:
Richard Smith 2015-06-10 01:47:58 +00:00
parent 4881e8b239
commit 8346e52f89
2 changed files with 57 additions and 29 deletions

View File

@ -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<TemplateTypeParmDecl>(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<NonTypeTemplateParmDecl>(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<TemplateTemplateParmDecl>(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 <typename ParmDecl>
static bool inheritDefaultTemplateArgument(ASTContext &Context, ParmDecl *From,
Decl *ToD) {
auto *To = cast<ParmDecl>(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<TemplateTypeParmDecl>(FromParam)) {
if (inheritDefaultTemplateArgument(Context, FTTP, ToParam))
break;
} else if (auto *FNTTP = dyn_cast<NonTypeTemplateParmDecl>(FromParam)) {
if (inheritDefaultTemplateArgument(Context, FNTTP, ToParam))
break;
} else {
if (inheritDefaultTemplateArgument(
Context, cast<TemplateTemplateParmDecl>(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<TemplateDecl>(D))
inheritDefaultTemplateArguments(Reader.getContext(),
cast<TemplateDecl>(Previous), TD);
}
template<typename DeclT>

View File

@ -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;
}