r304951 - When determining the target function of an explicit instantiation, make

John McCall via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 7 16:00:06 PDT 2017


Author: rjmccall
Date: Wed Jun  7 18:00:05 2017
New Revision: 304951

URL: http://llvm.org/viewvc/llvm-project?rev=304951&view=rev
Log:
When determining the target function of an explicit instantiation, make
sure that non-template functions don't end up in the candidate set.

Fixes PR14211.

Patch by Don Hinton!

Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=304951&r1=304950&r2=304951&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Jun  7 18:00:05 2017
@@ -8957,7 +8957,8 @@ DeclResult Sema::ActOnExplicitInstantiat
   //   A member function [...] of a class template can be explicitly
   //  instantiated from the member definition associated with its class
   //  template.
-  UnresolvedSet<8> Matches;
+  UnresolvedSet<8> TemplateMatches;
+  FunctionDecl *NonTemplateMatch = nullptr;
   AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
   TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
   for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
@@ -8968,11 +8969,13 @@ DeclResult Sema::ActOnExplicitInstantiat
         QualType Adjusted = adjustCCAndNoReturn(R, Method->getType(),
                                                 /*AdjustExceptionSpec*/true);
         if (Context.hasSameUnqualifiedType(Method->getType(), Adjusted)) {
-          Matches.clear();
-
-          Matches.addDecl(Method, P.getAccess());
-          if (Method->getTemplateSpecializationKind() == TSK_Undeclared)
-            break;
+          if (Method->getPrimaryTemplate()) {
+            TemplateMatches.addDecl(Method, P.getAccess());
+          } else {
+            // FIXME: Can this assert ever happen?  Needs a test.
+            assert(!NonTemplateMatch && "Multiple NonTemplateMatches");
+            NonTemplateMatch = Method;
+          }
         }
       }
     }
@@ -9011,22 +9014,25 @@ DeclResult Sema::ActOnExplicitInstantiat
       continue;
     }
 
-    Matches.addDecl(Specialization, P.getAccess());
+    TemplateMatches.addDecl(Specialization, P.getAccess());
   }
 
-  // Find the most specialized function template specialization.
-  UnresolvedSetIterator Result = getMostSpecialized(
-      Matches.begin(), Matches.end(), FailedCandidates,
-      D.getIdentifierLoc(),
-      PDiag(diag::err_explicit_instantiation_not_known) << Name,
-      PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
-      PDiag(diag::note_explicit_instantiation_candidate));
+  FunctionDecl *Specialization = NonTemplateMatch;
+  if (!Specialization) {
+    // Find the most specialized function template specialization.
+    UnresolvedSetIterator Result = getMostSpecialized(
+        TemplateMatches.begin(), TemplateMatches.end(), FailedCandidates,
+        D.getIdentifierLoc(),
+        PDiag(diag::err_explicit_instantiation_not_known) << Name,
+        PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+        PDiag(diag::note_explicit_instantiation_candidate));
 
-  if (Result == Matches.end())
-    return true;
+    if (Result == TemplateMatches.end())
+      return true;
 
-  // Ignore access control bits, we don't need them for redeclaration checking.
-  FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+    // Ignore access control bits, we don't need them for redeclaration checking.
+    Specialization = cast<FunctionDecl>(*Result);
+  }
 
   // C++11 [except.spec]p4
   // In an explicit instantiation an exception-specification may be specified,

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp?rev=304951&r1=304950&r2=304951&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p5.cpp Wed Jun  7 18:00:05 2017
@@ -77,3 +77,16 @@ void test_X0(X0 x0, const X0 &x0c) {
   x0.operator float *();
   x0c.operator const char*();
 }
+
+namespace PR14211 {
+template <class U> struct X {
+  void foo(U){}
+  template <class T> void foo(T){}
+
+  template <class T> void bar(T){}
+  void bar(U){}
+};
+
+template void X<int>::foo(int);
+template void X<int>::bar(int);
+}




More information about the cfe-commits mailing list