From: Douglas Gregor Date: Tue, 27 Oct 2009 06:26:26 +0000 (+0000) Subject: Only set the point of instantiation for an implicit or explicit X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=972e6ce33c7e307f4b0da12bd6079bbd6ef76948;p=clang 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 --- 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( 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(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()) { if (ClassTemplateSpecializationDecl *ClassTemplateSpec = dyn_cast(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(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::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::TransformTemplateArgument(const TemplateArgument &Arg) { } case TemplateArgument::Declaration: { + DeclarationName Name; + if (NamedDecl *ND = dyn_cast(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 struct X1; // expected-note 2{{declared here}} \ - // expected-note 3{{forward declaration}} +template struct X1; // expected-note 5{{declared here}} // FIXME: Repeated diagnostics here! template void X0::f0(int); // expected-error 2{{incomplete type}} \ // expected-error{{invalid token after}} -template void X1::f0(int); // expected-error{{implicit instantiation of undefined template}} \ - // expected-error{{incomplete type}} \\ +template void X1::f0(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::Inner; // 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::f1(int); // expected-error{{incomplete type}} \ +template void X1::f1(int); // expected-error{{undefined template}} \ // expected-error{{does not refer}} -template int X1::member; // expected-error{{incomplete type}} \ +template int X1::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 *a1, A *a2) { (void)a1->x; // expected-error{{incomplete definition of type 'A'}} - (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A'}} \ - // expected-note{{first required here}} + (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A'}} } typedef float FLOAT; @@ -71,8 +70,7 @@ namespace N { } // Diagnose specialization errors -struct A { }; // expected-error{{template specialization requires 'template<>'}} \ - // expected-error{{after instantiation}} +struct A { }; // expected-error{{template specialization requires 'template<>'}} template<> struct ::A; @@ -100,3 +98,9 @@ template<> struct N::B { int testf(int x) { return f(x); } }; +// PR5264 +template class Foo; +Foo* v; +Foo& F() { return *v; } +template class Foo {}; +Foo x;