Make the remaining explicit-instantiation semantic action use

CheckSpecializationInstantiationRedecl to check for
redeclarations/instantiations. Also fixes a longstanding issue where
our explicit-instantiation location information wasn't as good as it
could have been.

llvm-svn: 84216
This commit is contained in:
Douglas Gregor 2009-10-15 22:53:21 +00:00
parent a614915632
commit 12e49d3250
3 changed files with 22 additions and 56 deletions

View File

@ -3630,54 +3630,18 @@ Sema::ActOnExplicitInstantiation(Scope *S,
ClassTemplateSpecializationDecl *Specialization = 0;
bool SpecializationRequiresInstantiation = true;
if (PrevDecl) {
if (PrevDecl->getSpecializationKind()
== TSK_ExplicitInstantiationDefinition) {
// This particular specialization has already been declared or
// instantiated. We cannot explicitly instantiate it.
Diag(TemplateNameLoc, diag::err_explicit_instantiation_duplicate)
<< Context.getTypeDeclType(PrevDecl);
Diag(PrevDecl->getLocation(),
diag::note_previous_explicit_instantiation);
bool SuppressNew = false;
if (CheckSpecializationInstantiationRedecl(*this, TemplateNameLoc, TSK,
PrevDecl,
PrevDecl->getSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
SuppressNew))
return DeclPtrTy::make(PrevDecl);
}
if (PrevDecl->getSpecializationKind() == TSK_ExplicitSpecialization) {
// C++ DR 259, C++0x [temp.explicit]p4:
// For a given set of template parameters, if an explicit
// instantiation of a template appears after a declaration of
// an explicit specialization for that template, the explicit
// instantiation has no effect.
if (!getLangOptions().CPlusPlus0x) {
Diag(TemplateNameLoc,
diag::ext_explicit_instantiation_after_specialization)
<< Context.getTypeDeclType(PrevDecl);
Diag(PrevDecl->getLocation(),
diag::note_previous_template_specialization);
}
// Create a new class template specialization declaration node
// for this explicit specialization. This node is only used to
// record the existence of this explicit instantiation for
// accurate reproduction of the source code; we don't actually
// use it for anything, since it is semantically irrelevant.
Specialization
= ClassTemplateSpecializationDecl::Create(Context,
ClassTemplate->getDeclContext(),
TemplateNameLoc,
ClassTemplate,
Converted, 0);
Specialization->setLexicalDeclContext(CurContext);
CurContext->addDecl(Specialization);
if (SuppressNew)
return DeclPtrTy::make(PrevDecl);
}
// If we have already (implicitly) instantiated this
// specialization, there is less work to do.
if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation)
SpecializationRequiresInstantiation = false;
if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation ||
PrevDecl->getSpecializationKind() == TSK_Undeclared) {
// Since the only prior class template specialization with these
@ -3688,7 +3652,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setLocation(TemplateNameLoc);
PrevDecl = 0;
}
}
}
if (!Specialization) {
// Create a new class template specialization declaration node for
@ -3741,11 +3705,13 @@ Sema::ActOnExplicitInstantiation(Scope *S,
//
// This check comes when we actually try to perform the
// instantiation.
if (SpecializationRequiresInstantiation)
ClassTemplateSpecializationDecl *Def
= cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition(Context));
if (!Def)
InstantiateClassTemplateSpecialization(Specialization, TSK);
else // Instantiate the members of this class template specialization.
InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization,
TSK);
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
return DeclPtrTy::make(Specialization);
}
@ -3836,7 +3802,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
return TagD;
}
if (!Record->getDefinition(Context)) {
CXXRecordDecl *RecordDef
= cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
if (!RecordDef) {
// C++ [temp.explicit]p3:
// A definition of a member class of a class template shall be in scope
// at the point of an explicit instantiation of the member class.
@ -3848,12 +3816,12 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Diag(Pattern->getLocation(), diag::note_forward_declaration)
<< Pattern;
return true;
} else if (InstantiateClass(TemplateLoc, Record, Def,
} else if (InstantiateClass(NameLoc, Record, Def,
getTemplateInstantiationArgs(Record),
TSK))
return true;
} else // Instantiate all of the members of the class.
InstantiateClassMembers(TemplateLoc, Record,
InstantiateClassMembers(NameLoc, RecordDef,
getTemplateInstantiationArgs(Record), TSK);
// FIXME: We don't have any representation for explicit instantiations of

View File

@ -29,16 +29,14 @@ void test_intptr(X0<int*> xi, X0<int*>::Inner xii) {
xii.g(0);
}
// FIXME: we would like the notes to point to the explicit instantiation at the
// bottom.
extern template class X0<long*>; // expected-note 2{{instantiation}}
extern template class X0<long*>;
void test_longptr(X0<long*> xl, X0<long*>::Inner xli) {
xl.f(0);
xli.g(0);
}
template class X0<long*>;
template class X0<long*>; // expected-note 2{{instantiation}}
template<typename T>
class X1 {

View File

@ -14,6 +14,6 @@ template struct TS2<int, int>;
template <typename = int, typename ...> struct TS3 {}; // expected-note{{template parameter is declared here}}
template struct TS3<>; // expected-note{{previous explicit instantiation is here}}
template struct TS3<int>; // expected-error{{duplicate explicit instantiation of 'TS3<>'}}
template struct TS3<int>; // expected-error{{duplicate explicit instantiation of 'TS3}}
template struct TS3<int, int>;
template struct TS3<10>; // expected-error{{template argument for template type parameter must be a type}}