aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-10-27 06:26:26 +0000
committerDouglas Gregor <dgregor@apple.com>2009-10-27 06:26:26 +0000
commit972e6ce33c7e307f4b0da12bd6079bbd6ef76948 (patch)
treef41ba0ba00f71fac8ed72f642bdfb8741b891b54
parent9a4c1055fcf5b7d56a4549925a022089d086becb (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85209 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/Sema.h2
-rw-r--r--lib/Sema/SemaTemplate.cpp11
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp31
-rw-r--r--lib/Sema/SemaType.cpp11
-rw-r--r--lib/Sema/TreeTransform.h5
-rw-r--r--test/CXX/temp/temp.spec/temp.explicit/p3.cpp10
-rw-r--r--test/SemaTemplate/class-template-spec.cpp12
7 files changed, 48 insertions, 34 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index f108878676..a40cdf390c 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3189,7 +3189,7 @@ public:
bool Complain = true);
bool
- InstantiateClassTemplateSpecialization(
+ InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK,
bool Complain = true);
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 2bb790dda4..4419ad04a2 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -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).
///
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 1790d27eeb..22d1e165f0 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 029aecc045..8e960a43f7 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -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);
- }
}
}
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 872b3c0189..15b1520447 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -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();
diff --git a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
index 2bd781bbed..00484e9894 100644
--- a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
+++ b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
@@ -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
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index e44115c748..4cd43b469a 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -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;