]> granicus.if.org Git - clang/commitdiff
Make the remaining explicit-instantiation semantic action use
authorDouglas Gregor <dgregor@apple.com>
Thu, 15 Oct 2009 22:53:21 +0000 (22:53 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 15 Oct 2009 22:53:21 +0000 (22:53 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84216 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplate.cpp
test/SemaTemplate/extern-templates.cpp
test/SemaTemplate/variadic-class-template-2.cpp

index 730fea30b5aafbd6230c9f8f985c2db6bdeaf19d..520d60686027ddb5ab782e60addfba4e39929176 100644 (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
index 28fda1a11e6bb94ff852b466d70490eab472451f..44728d188a24b77d7f6b3aba33c8bb0753ab61d6 100644 (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 {
index eadea901c7fef2056e3a93a2b8130b5459c90a76..b1ac71b88bda4c771878e3fa4fd30261e46f05e2 100644 (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}}