summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2018-07-19 20:40:20 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2018-07-19 20:40:20 +0000
commit0b75dc5fa2e0552e7c9f3250e3487cf73dacd32b (patch)
treedb97575c2f0bd735f9201d0e297b90129ab75327 /clang
parentbc093ea0033d01f86724893d8fecd1b35792ebf4 (diff)
downloadbcm5719-llvm-0b75dc5fa2e0552e7c9f3250e3487cf73dacd32b.tar.gz
bcm5719-llvm-0b75dc5fa2e0552e7c9f3250e3487cf73dacd32b.zip
[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 llvm-svn: 337497
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp27
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp28
3 files changed, 57 insertions, 5 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ee51db2d0a7..f623bd37735 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4106,6 +4106,13 @@ def ext_explicit_specialization_storage_class : ExtWarn<
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<
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 935264cb8cc..dd116326711 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -8003,17 +8003,34 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
// 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);
diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
index f1f3f701624..849728a448b 100644
--- a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp
@@ -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}}
+};
+}
OpenPOWER on IntegriCloud