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));
}
// 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));
}
}
// 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));
}
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);
// 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>
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;
} 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;
}
} 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;
}