r295118 - Do not implicitly instantiate the definition of a class template specialization

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 14 15:27:45 PST 2017


Author: rsmith
Date: Tue Feb 14 17:27:44 2017
New Revision: 295118

URL: http://llvm.org/viewvc/llvm-project?rev=295118&view=rev
Log:
Do not implicitly instantiate the definition of a class template specialization
that has been explicitly specialized!

We assume in various places that we can tell the template specialization kind
of a class type by looking at the declaration produced by TagType::getDecl.
That was previously not quite true: for an explicit specialization, we could
have first seen a template-id denoting the specialization (with a use that does
not trigger an implicit instantiation of the defintiion) and then seen the
first explicit specialization declaration. TagType::getDecl would previously
return an arbitrary declaration when called on a not-yet-defined class; it
now consistently returns the most recent declaration in that case.

Modified:
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=295118&r1=295117&r2=295118&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Feb 14 17:27:44 2017
@@ -3023,8 +3023,10 @@ static TagDecl *getInterestingTagDecl(Ta
     if (I->isCompleteDefinition() || I->isBeingDefined())
       return I;
   }
-  // If there's no definition (not even in progress), return what we have.
-  return decl;
+  // If there's no definition (not even in progress), return the most recent
+  // declaration. This is important for template specializations, in order to
+  // pick the declaration with the most complete TemplateSpecializationKind.
+  return decl->getMostRecentDecl();
 }
 
 TagDecl *TagType::getDecl() const {

Modified: cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp?rev=295118&r1=295117&r2=295118&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp (original)
+++ cfe/trunk/test/SemaTemplate/explicit-specialization-member.cpp Tue Feb 14 17:27:44 2017
@@ -57,3 +57,14 @@ template<typename T> struct Helper {
 template<typename T> void Helper<T>::func<2>() {} // expected-error {{cannot specialize a member}} \
                                                   // expected-error {{no function template matches}}
 }
+
+namespace b35070233 {
+  template <typename T> struct Cls {
+    static void f() {}
+  };
+
+  void g(Cls<int>);
+
+  template<> struct Cls<int>; // expected-note {{forward declaration}}
+  template<> void Cls<int>::f(); // expected-error {{incomplete type}}
+}




More information about the cfe-commits mailing list