r337497 - [Sema] Diagnose an invalid dependent function template specialization

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 19 13:40:20 PDT 2018


Author: epilk
Date: Thu Jul 19 13:40:20 2018
New Revision: 337497

URL: http://llvm.org/viewvc/llvm-project?rev=337497&view=rev
Log:
[Sema] Diagnose an invalid dependent function template specialization

Previously, clang marked the specialization as invalid without emitting a
diagnostic. This lead to an assert in CodeGen.

rdar://41806724

Differential revision: https://reviews.llvm.org/D49085

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=337497&r1=337496&r2=337497&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul 19 13:40:20 2018
@@ -4106,6 +4106,13 @@ def ext_explicit_specialization_storage_
 def err_explicit_specialization_inconsistent_storage_class : Error<
   "explicit specialization has extraneous, inconsistent storage class "
   "'%select{none|extern|static|__private_extern__|auto|register}0'">;
+def err_dependent_function_template_spec_no_match : Error<
+  "no candidate function template was found for dependent"
+  " friend function template specialization">;
+def note_dependent_function_template_spec_discard_reason : Note<
+  "candidate ignored: %select{not a function template"
+  "|not a member of the enclosing namespace;"
+  " did you mean to explicitly qualify the specialization?}0">;
 
 // C++ class template specializations and out-of-line definitions
 def err_template_spec_needs_header : Error<

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=337497&r1=337496&r2=337497&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Jul 19 13:40:20 2018
@@ -8003,17 +8003,34 @@ Sema::CheckDependentFunctionTemplateSpec
   // the correct context.
   DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
   LookupResult::Filter F = Previous.makeFilter();
+  enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing };
+  SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates;
   while (F.hasNext()) {
     NamedDecl *D = F.next()->getUnderlyingDecl();
-    if (!isa<FunctionTemplateDecl>(D) ||
-        !FDLookupContext->InEnclosingNamespaceSetOf(
-                              D->getDeclContext()->getRedeclContext()))
+    if (!isa<FunctionTemplateDecl>(D)) {
       F.erase();
+      DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D));
+      continue;
+    }
+
+    if (!FDLookupContext->InEnclosingNamespaceSetOf(
+            D->getDeclContext()->getRedeclContext())) {
+      F.erase();
+      DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D));
+      continue;
+    }
   }
   F.done();
 
-  // Should this be diagnosed here?
-  if (Previous.empty()) return true;
+  if (Previous.empty()) {
+    Diag(FD->getLocation(),
+         diag::err_dependent_function_template_spec_no_match);
+    for (auto &P : DiscardedCandidates)
+      Diag(P.second->getLocation(),
+           diag::note_dependent_function_template_spec_discard_reason)
+          << P.first;
+    return true;
+  }
 
   FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
                                          ExplicitTemplateArgs);

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp?rev=337497&r1=337496&r2=337497&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp Thu Jul 19 13:40:20 2018
@@ -359,3 +359,31 @@ namespace PR10913 {
   template void f2<int>(X<int> *);
   template void f2<float>(X<int> *); // expected-note{{in instantiation of function template specialization 'PR10913::f2<float, int>' requested here}}
 }
+
+namespace test16 {
+template <class T> struct foo {}; // expected-note{{candidate ignored: not a function template}}
+template <class T> class A {
+  friend void foo<T>(); // expected-error{{no candidate function template was found for dependent friend function template specialization}}
+};
+}
+
+namespace test17 {
+namespace ns {
+template <class T> void foo() {} // expected-note{{candidate ignored: not a member of the enclosing namespace; did you mean to explicitly qualify the specialization?}}
+}
+using ns::foo;
+template <class T> struct A {
+  friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}}
+};
+}
+
+namespace test18 {
+namespace ns1 { template <class T> struct foo {}; } // expected-note{{candidate ignored: not a function template}}
+namespace ns2 { void foo() {} } // expected-note{{candidate ignored: not a function template}}
+using ns1::foo;
+using ns2::foo;
+
+template <class T> class A {
+  friend void foo<T>() {} // expected-error{{no candidate function template was found for dependent friend function template specialization}}
+};
+}




More information about the cfe-commits mailing list