PD->ParmVarDeclBits.HasInheritedDefaultArg = Record[Idx++];
if (Record[Idx++]) // hasUninstantiatedDefaultArg.
PD->setUninstantiatedDefaultArg(Reader.ReadExpr(F));
+
+ // FIXME: If this is a redeclaration of a function from another module, handle
+ // inheritance of default arguments.
}
void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) {
TemplateParameterList* TemplateParams
= Reader.ReadTemplateParameterList(F, Record, Idx);
D->init(TemplatedDecl, TemplateParams);
+
+ // FIXME: If this is a redeclaration of a template from another module, handle
+ // inheritance of default template arguments.
}
ASTDeclReader::RedeclarableResult
return LocalOffset + M.GlobalBitOffset;
}
+static bool isSameTemplateParameterList(const TemplateParameterList *X,
+ const TemplateParameterList *Y);
+
+/// \brief Determine whether two template parameters are similar enough
+/// that they may be used in declarations of the same template.
+static bool isSameTemplateParameter(const NamedDecl *X,
+ const NamedDecl *Y) {
+ if (X->getKind() != Y->getKind())
+ return false;
+
+ if (const TemplateTypeParmDecl *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
+ const TemplateTypeParmDecl *TY = cast<TemplateTypeParmDecl>(Y);
+ return TX->isParameterPack() == TY->isParameterPack();
+ }
+
+ if (const NonTypeTemplateParmDecl *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
+ const NonTypeTemplateParmDecl *TY = cast<NonTypeTemplateParmDecl>(Y);
+ return TX->isParameterPack() == TY->isParameterPack() &&
+ TX->getASTContext().hasSameType(TX->getType(), TY->getType());
+ }
+
+ const TemplateTemplateParmDecl *TX = cast<TemplateTemplateParmDecl>(X);
+ const TemplateTemplateParmDecl *TY = cast<TemplateTemplateParmDecl>(Y);
+ return TX->isParameterPack() == TY->isParameterPack() &&
+ isSameTemplateParameterList(TX->getTemplateParameters(),
+ TY->getTemplateParameters());
+}
+
+/// \brief Determine whether two template parameter lists are similar enough
+/// that they may be used in declarations of the same template.
+static bool isSameTemplateParameterList(const TemplateParameterList *X,
+ const TemplateParameterList *Y) {
+ if (X->size() != Y->size())
+ return false;
+
+ for (unsigned I = 0, N = X->size(); I != N; ++I)
+ if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
+ return false;
+
+ return true;
+}
+
/// \brief Determine whether the two declarations refer to the same entity.
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
// Identical template names and kinds match if their template parameter lists
// and patterns match.
if (TemplateDecl *TemplateX = dyn_cast<TemplateDecl>(X)) {
- TemplateDecl *TemplateY = dyn_cast<TemplateDecl>(Y);
- // FIXME: Check template parameter lists.
+ TemplateDecl *TemplateY = cast<TemplateDecl>(Y);
return isSameEntity(TemplateX->getTemplatedDecl(),
- TemplateY->getTemplatedDecl());
+ TemplateY->getTemplatedDecl()) &&
+ isSameTemplateParameterList(TemplateX->getTemplateParameters(),
+ TemplateY->getTemplateParameters());
}
// FIXME: Many other cases to implement.
@import cxx_templates_a;
@import cxx_templates_b;
+template<typename, char> struct Tmpl_T_C {};
+template<typename, int, int> struct Tmpl_T_I_I {};
+
+template<typename A, typename B, A> struct Tmpl_T_T_A {};
+template<typename A, typename B, B> struct Tmpl_T_T_B {};
+
void g() {
f(0);
f<double>(1.0);
N::f(); // expected-error {{no matching function}}
// expected-note@Inputs/cxx-templates-a.h:4 {{couldn't infer template argument}}
// expected-note@Inputs/cxx-templates-a.h:5 {{requires 1 argument, but 0 were provided}}
+
+ template_param_kinds_1<0>(); // ok, from cxx-templates-a.h
+ template_param_kinds_1<int>(); // ok, from cxx-templates-b.h
+
+ template_param_kinds_2<Tmpl_T_C>(); // expected-error {{no matching function}}
+ // expected-note@Inputs/cxx-templates-a.h:9 {{invalid explicitly-specified argument}}
+ // expected-note@Inputs/cxx-templates-b.h:9 {{invalid explicitly-specified argument}}
+
+ template_param_kinds_2<Tmpl_T_I_I>(); // expected-error {{ambiguous}}
+ // expected-note@Inputs/cxx-templates-a.h:9 {{candidate}}
+ // expected-note@Inputs/cxx-templates-b.h:9 {{candidate}}
+
+ // FIXME: This should be valid, but we incorrectly match the template template
+ // argument against both template template parameters.
+ template_param_kinds_3<Tmpl_T_T_A>(); // expected-error {{ambiguous}}
+ // expected-note@Inputs/cxx-templates-a.h:10 {{candidate}}
+ // expected-note@Inputs/cxx-templates-b.h:10 {{candidate}}
+ template_param_kinds_3<Tmpl_T_T_B>(); // expected-error {{ambiguous}}
+ // expected-note@Inputs/cxx-templates-a.h:10 {{candidate}}
+ // expected-note@Inputs/cxx-templates-b.h:10 {{candidate}}
}
// FIXME: There should only be two 'f's here.