]> granicus.if.org Git - clang/commitdiff
Only set the point of instantiation for an implicit or explicit
authorDouglas Gregor <dgregor@apple.com>
Tue, 27 Oct 2009 06:26:26 +0000 (06:26 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 27 Oct 2009 06:26:26 +0000 (06:26 +0000)
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

lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaType.cpp
lib/Sema/TreeTransform.h
test/CXX/temp/temp.spec/temp.explicit/p3.cpp
test/SemaTemplate/class-template-spec.cpp

index f108878676c64131f4f5165c8b6b5bbcc909c3a6..a40cdf390c84de91b7c0c990839186cf6ba5cc39 100644 (file)
@@ -3189,7 +3189,7 @@ public:
                    bool Complain = true);
 
   bool
-  InstantiateClassTemplateSpecialization(
+  InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
                            TemplateSpecializationKind TSK,
                            bool Complain = true);
index 2bb790dda4efd1311c2272a742c7490d61ece299..4419ad04a2506ec6f021eb8c0011feb0b2e56ee8 100644 (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).
     ///
index 1790d27eeb34a61a66c727b9670648f9a66754c5..22d1e165f0e4d3ecbd94a8dd812552085529ebde 100644 (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);
 
index 029aecc0456b9a733d96fc4f3ce9c2f553c80d35..8e960a43f7aac6b7c35a7f8a6e4caad2fceee09f 100644 (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);
-        }
       }
     }
   }
index 872b3c0189b26af75816833ee4652c54b6e0557a..15b1520447205062aae86735d7780c2a884f2ece 100644 (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();
index 2bd781bbed284cf14f637e4f816b170728427c1b..00484e9894ffb22066520ee49c157101a4ee5ad2 100644 (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 
index e44115c748c3949be269b5ef216980d1f2d8e891..4cd43b469ae0c32be72b918a193fed6c813916fd 100644 (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;