[cfe-commits] r147225 - in /cfe/trunk: include/clang/AST/DeclTemplate.h lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp

Nico Weber nicolasweber at gmx.de
Fri Dec 23 12:58:05 PST 2011


Author: nico
Date: Fri Dec 23 14:58:04 2011
New Revision: 147225

URL: http://llvm.org/viewvc/llvm-project?rev=147225&view=rev
Log:
Fix several issues related to specializations and explicit instantiations.

Explicit instantiations following specializations are no-ops and hence have
no PointOfInstantiation. That was done correctly in most cases, but for a
specialization -> instantiation decl -> instantiation definition chain, the
definition didn't realize that it was a no-op. Fix that.

Also, when printing diagnostics for these no-ops, get the diag location from
the decl name location.

Add many test cases, one of them not yet passing (but it failed the same way
before this change). Fixes http://llvm.org/pr11558 and more.


Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=147225&r1=147224&r2=147225&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Fri Dec 23 14:58:04 2011
@@ -1607,7 +1607,7 @@
 
 public:
   static ClassTemplatePartialSpecializationDecl *
-  Create(ASTContext &Context, TagKind TK,DeclContext *DC,
+  Create(ASTContext &Context, TagKind TK, DeclContext *DC,
          SourceLocation StartLoc, SourceLocation IdLoc,
          TemplateParameterList *Params,
          ClassTemplateDecl *SpecializedTemplate,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=147225&r1=147224&r2=147225&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Dec 23 14:58:04 2011
@@ -5344,9 +5344,17 @@
       //   translation unit, the definition shall follow the declaration.
       Diag(NewLoc,
            diag::err_explicit_instantiation_declaration_after_definition);
-      Diag(PrevPointOfInstantiation,
-           diag::note_explicit_instantiation_definition_here);
-      assert(PrevPointOfInstantiation.isValid() &&
+
+      // Explicit instantiations following a specialization have no effect and
+      // hence no PrevPointOfInstantiation. In that case, walk decl backwards
+      // until a valid name loc is found.
+      SourceLocation PrevDiagLoc = PrevPointOfInstantiation;
+      for (NamedDecl *Prev = PrevDecl; Prev && !PrevDiagLoc.isValid();
+          Prev = getPreviousDecl(Prev)) {
+        PrevDiagLoc = Prev->getLocation();
+      }
+      Diag(PrevDiagLoc, diag::note_explicit_instantiation_definition_here);
+      assert(PrevDiagLoc.isValid() &&
              "Explicit instantiation without point of instantiation?");
       HasNoEffect = true;
       return false;
@@ -5383,6 +5391,20 @@
     case TSK_ExplicitInstantiationDeclaration:
       // We're explicity instantiating a definition for something for which we
       // were previously asked to suppress instantiations. That's fine.
+
+      // 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.
+      for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) {
+        // Is there any previous explicit specialization declaration?
+        if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) {
+          HasNoEffect = true;
+          break;
+        }
+      }
+
       return false;
 
     case TSK_ExplicitInstantiationDefinition:
@@ -5677,7 +5699,7 @@
 
   // C++ [temp.expl.spec]p6:
   //   If a template, a member template or the member of a class template is
-  //   explicitly specialized then that spe- cialization shall be declared
+  //   explicitly specialized then that specialization shall be declared
   //   before the first use of that specialization that would cause an implicit
   //   instantiation to take place, in every translation unit in which such a
   //   use occurs; no diagnostic is required.

Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp?rev=147225&r1=147224&r2=147225&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp Fri Dec 23 14:58:04 2011
@@ -207,3 +207,131 @@
     static void foo();
   };
 }
+
+
+namespace spec_vs_expl_inst {
+
+  // Test all permutations of Specialization,
+  // explicit instantiation Declaration, and explicit instantiation defInition.
+
+  namespace SDI {  // PR11558
+    template <typename STRING_TYPE> class BasicStringPiece;
+    template <> class BasicStringPiece<int> { };
+    extern template class BasicStringPiece<int>;
+    template class BasicStringPiece<int>;
+  }
+
+  namespace SID {
+    template <typename STRING_TYPE> class BasicStringPiece;
+    template <> class BasicStringPiece<int> { };
+    template class BasicStringPiece<int>;  // expected-note {{explicit instantiation definition is here}}
+    extern template class BasicStringPiece<int>;  // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
+  }
+
+  namespace ISD {
+    template <typename STRING_TYPE> class BasicStringPiece;  // expected-note {{template is declared here}}
+    template class BasicStringPiece<int>;  // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::ISD::BasicStringPiece<int>'}}
+    template <> class BasicStringPiece<int> { };
+    extern template class BasicStringPiece<int>;
+  }
+
+  namespace IDS {
+    template <typename STRING_TYPE> class BasicStringPiece;  // expected-note {{template is declared here}}
+    template class BasicStringPiece<int>;  // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::IDS::BasicStringPiece<int>'}}  // expected-note {{explicit instantiation definition is here}}
+    extern template class BasicStringPiece<int>;  // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
+    template <> class BasicStringPiece<int> { };
+  }
+
+  namespace DIS {
+    template <typename STRING_TYPE> class BasicStringPiece;  // expected-note {{template is declared here}}
+    extern template class BasicStringPiece<int>;  // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DIS::BasicStringPiece<int>'}}
+    template class BasicStringPiece<int>;
+    template <> class BasicStringPiece<int> { };
+  }
+
+  namespace DSI {
+    template <typename STRING_TYPE> class BasicStringPiece;  // expected-note {{template is declared here}}
+    extern template class BasicStringPiece<int>;  // expected-error {{explicit instantiation of undefined template 'spec_vs_expl_inst::DSI::BasicStringPiece<int>'}}
+    template <> class BasicStringPiece<int> { };
+    template class BasicStringPiece<int>;
+  }
+
+  // The same again, with a defined template class.
+
+  namespace SDI_WithDefinedTemplate {
+    template <typename STRING_TYPE> class BasicStringPiece {};
+    template <> class BasicStringPiece<int> { };
+    extern template class BasicStringPiece<int>;
+    template class BasicStringPiece<int>;
+  }
+
+  namespace SID_WithDefinedTemplate {
+    template <typename STRING_TYPE> class BasicStringPiece {};
+    template <> class BasicStringPiece<int> { };
+    template class BasicStringPiece<int>;  // expected-note {{explicit instantiation definition is here}}
+    extern template class BasicStringPiece<int>;  // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
+  }
+
+  namespace ISD_WithDefinedTemplate {
+    template <typename STRING_TYPE> class BasicStringPiece {};
+    template class BasicStringPiece<int>;  // expected-note {{explicit instantiation first required here}}
+    template <> class BasicStringPiece<int> { };  // expected-error {{explicit specialization of 'spec_vs_expl_inst::ISD_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}}
+    extern template class BasicStringPiece<int>;
+  }
+
+  namespace IDS_WithDefinedTemplate {
+    template <typename STRING_TYPE> class BasicStringPiece {};
+    template class BasicStringPiece<int>;  // expected-note {{explicit instantiation definition is here}} expected-note {{previous definition is here}}
+    extern template class BasicStringPiece<int>;  // expected-error {{explicit instantiation declaration (with 'extern') follows explicit instantiation definition (without 'extern')}}
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::IDS_WithDefinedTemplate::BasicStringPiece<int>'}}
+  }
+
+  namespace DIS_WithDefinedTemplate {
+    template <typename STRING_TYPE> class BasicStringPiece {};
+    extern template class BasicStringPiece<int>;  // expected-note {{explicit instantiation first required here}}
+    template class BasicStringPiece<int>;
+    template <> class BasicStringPiece<int> { };  // expected-error {{explicit specialization of 'spec_vs_expl_inst::DIS_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}}
+  }
+
+  namespace DSI_WithDefinedTemplate {
+    template <typename STRING_TYPE> class BasicStringPiece {};
+    extern template class BasicStringPiece<int>;  // expected-note {{explicit instantiation first required here}}
+    template <> class BasicStringPiece<int> { };  // expected-error {{explicit specialization of 'spec_vs_expl_inst::DSI_WithDefinedTemplate::BasicStringPiece<int>' after instantiation}}
+    template class BasicStringPiece<int>;
+  }
+
+  // And some more random tests.
+
+// FIXME: Enable this test. The error is printed fine, but the note is at some
+// weird source location that causes "previous explicit instantiation is here"
+// without anything after it to be printed. That happened before this patch too.
+//  namespace SII_WithDefinedTemplate {
+//    template <typename STRING_TYPE> class BasicStringPiece {};
+//    template <> class BasicStringPiece<int> { };
+//    template class BasicStringPiece<int>;
+//    template class BasicStringPiece<int>;
+//  }
+
+  namespace SIS {
+    template <typename STRING_TYPE> class BasicStringPiece;
+    template <> class BasicStringPiece<int> { };  // expected-note {{previous definition is here}}
+    template class BasicStringPiece<int>;
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::SIS::BasicStringPiece<int>'}}
+  }
+
+  namespace SDS {
+    template <typename STRING_TYPE> class BasicStringPiece;
+    template <> class BasicStringPiece<int> { };  // expected-note {{previous definition is here}}
+    extern template class BasicStringPiece<int>;
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::SDS::BasicStringPiece<int>'}}
+  }
+
+  namespace SDIS {
+    template <typename STRING_TYPE> class BasicStringPiece;
+    template <> class BasicStringPiece<int> { };  // expected-note {{previous definition is here}}
+    extern template class BasicStringPiece<int>;
+    template class BasicStringPiece<int>;
+    template <> class BasicStringPiece<int> { };  // expected-error {{redefinition of 'spec_vs_expl_inst::SDIS::BasicStringPiece<int>'}}
+  }
+
+}





More information about the cfe-commits mailing list