Only set the point of instantiation for an implicit or explicit

instantiation once we have committed to performing the
instantiation. As part of this, make our makeshift
template-instantiation location information suck slightly less.

Fixes PR5264.

llvm-svn: 85209
This commit is contained in:
Douglas Gregor 2009-10-27 06:26:26 +00:00
parent d169e6c281
commit ef6ab417c1
7 changed files with 48 additions and 34 deletions

View File

@ -3189,7 +3189,7 @@ public:
bool Complain = true);
bool
InstantiateClassTemplateSpecialization(
InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool Complain = true);

View File

@ -3726,8 +3726,6 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->setLexicalDeclContext(CurContext);
CurContext->addDecl(Specialization);
Specialization->setPointOfInstantiation(TemplateNameLoc);
// C++ [temp.explicit]p3:
// A definition of a class template or class member template
// shall be in scope at the point of the explicit instantiation of
@ -3739,7 +3737,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
= cast_or_null<ClassTemplateSpecializationDecl>(
Specialization->getDefinition(Context));
if (!Def)
InstantiateClassTemplateSpecialization(Specialization, TSK);
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
else // Instantiate the members of this class template specialization.
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
@ -4280,6 +4278,13 @@ namespace {
/// \brief Returns the name of the entity whose type is being rebuilt.
DeclarationName getBaseEntity() { return Entity; }
/// \brief Sets the "base" location and entity when that
/// information is known based on another transformation.
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
this->Entity = Entity;
}
/// \brief Transforms an expression by returning the expression itself
/// (an identity function).
///

View File

@ -392,6 +392,13 @@ namespace {
/// \brief Returns the name of the entity being instantiated, if any.
DeclarationName getBaseEntity() { return Entity; }
/// \brief Sets the "base" location and entity when that
/// information is known based on another transformation.
void setBase(SourceLocation Loc, DeclarationName Entity) {
this->Loc = Loc;
this->Entity = Entity;
}
/// \brief Transform the given declaration by instantiating a reference to
/// this declaration.
Decl *TransformDecl(Decl *D);
@ -849,6 +856,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
= Instantiation->getMemberSpecializationInfo()) {
MSInfo->setTemplateSpecializationKind(TSK);
MSInfo->setPointOfInstantiation(PointOfInstantiation);
} else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) {
Spec->setTemplateSpecializationKind(TSK);
Spec->setPointOfInstantiation(PointOfInstantiation);
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);
@ -915,6 +926,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
bool
Sema::InstantiateClassTemplateSpecialization(
SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool Complain) {
@ -932,10 +944,9 @@ Sema::InstantiateClassTemplateSpecialization(
// declaration (C++0x [temp.explicit]p10); go ahead and perform the
// explicit instantiation.
ClassTemplateSpec->setSpecializationKind(TSK);
InstantiateClassTemplateSpecializationMembers(
/*FIXME?*/ClassTemplateSpec->getPointOfInstantiation(),
ClassTemplateSpec,
TSK);
InstantiateClassTemplateSpecializationMembers(PointOfInstantiation,
ClassTemplateSpec,
TSK);
return false;
}
@ -1019,8 +1030,7 @@ Sema::InstantiateClassTemplateSpecialization(
if (Ambiguous) {
// Partial ordering did not produce a clear winner. Complain.
ClassTemplateSpec->setInvalidDecl();
Diag(ClassTemplateSpec->getPointOfInstantiation(),
diag::err_partial_spec_ordering_ambiguous)
Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous)
<< ClassTemplateSpec;
// Print the matching partial specializations.
@ -1053,12 +1063,9 @@ Sema::InstantiateClassTemplateSpecialization(
Pattern = OrigTemplate->getTemplatedDecl();
}
// Note that this is an instantiation.
ClassTemplateSpec->setSpecializationKind(TSK);
bool Result = InstantiateClass(ClassTemplateSpec->getPointOfInstantiation(),
ClassTemplateSpec, Pattern,
getTemplateInstantiationArgs(ClassTemplateSpec),
bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec,
Pattern,
getTemplateInstantiationArgs(ClassTemplateSpec),
TSK,
Complain);

View File

@ -1694,13 +1694,10 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
if (const RecordType *Record = T->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) {
if (Loc.isValid())
ClassTemplateSpec->setPointOfInstantiation(Loc);
return InstantiateClassTemplateSpecialization(ClassTemplateSpec,
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
}
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) {
@ -1708,13 +1705,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
assert(MSInfo && "Missing member specialization information?");
// This record was instantiated from a class within a template.
if (MSInfo->getTemplateSpecializationKind()
!= TSK_ExplicitSpecialization) {
MSInfo->setPointOfInstantiation(Loc);
!= TSK_ExplicitSpecialization)
return InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
}
}
}
}

View File

@ -1884,6 +1884,7 @@ TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
return Arg;
case TemplateArgument::Type: {
TemporaryBase Rebase(*this, Arg.getLocation(), DeclarationName());
QualType T = getDerived().TransformType(Arg.getAsType());
if (T.isNull())
return TemplateArgument();
@ -1891,6 +1892,10 @@ TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
}
case TemplateArgument::Declaration: {
DeclarationName Name;
if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
Name = ND->getDeclName();
TemporaryBase Rebase(*this, Arg.getLocation(), Name);
Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
if (!D)
return TemplateArgument();

View File

@ -9,14 +9,12 @@ template void f0(int); // okay
// template shall be in scope at the point of the explicit instantiation of
// the member function template.
struct X0; // expected-note 2{{forward declaration}}
template<typename> struct X1; // expected-note 2{{declared here}} \
// expected-note 3{{forward declaration}}
template<typename> struct X1; // expected-note 5{{declared here}}
// FIXME: Repeated diagnostics here!
template void X0::f0<int>(int); // expected-error 2{{incomplete type}} \
// expected-error{{invalid token after}}
template void X1<int>::f0<int>(int); // expected-error{{implicit instantiation of undefined template}} \
// expected-error{{incomplete type}} \\
template void X1<int>::f0<int>(int); // expected-error 2{{implicit instantiation of undefined template}} \
// expected-error{{invalid token}}
// A definition of a class template or class member template shall be in scope
@ -37,10 +35,10 @@ template struct X2<int>::Inner<float>; // expected-error{{explicit instantiation
// A definition of a class template shall be in scope at the point of an
// explicit instantiation of a member function or a static data member of the
// class template.
template void X1<int>::f1(int); // expected-error{{incomplete type}} \
template void X1<int>::f1(int); // expected-error{{undefined template}} \
// expected-error{{does not refer}}
template int X1<int>::member; // expected-error{{incomplete type}} \
template int X1<int>::member; // expected-error{{undefined template}} \
// expected-error{{does not refer}}
// A definition of a member class of a class template shall be in scope at the

View File

@ -20,8 +20,7 @@ int test_incomplete_specs(A<double, double> *a1,
A<double> *a2)
{
(void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
(void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}} \
// expected-note{{first required here}}
(void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
}
typedef float FLOAT;
@ -71,8 +70,7 @@ namespace N {
}
// Diagnose specialization errors
struct A<double> { }; // expected-error{{template specialization requires 'template<>'}} \
// expected-error{{after instantiation}}
struct A<double> { }; // expected-error{{template specialization requires 'template<>'}}
template<> struct ::A<double>;
@ -100,3 +98,9 @@ template<> struct N::B<char> {
int testf(int x) { return f(x); }
};
// PR5264
template <typename T> class Foo;
Foo<int>* v;
Foo<int>& F() { return *v; }
template <typename T> class Foo {};
Foo<int> x;