From fcdd2cb2fdf35f806dd800b369fe0772a1c8c26c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 10 Oct 2011 18:15:57 +0000 Subject: [PATCH] Don't suggest 'noreturn' for function template instantiations, because it might be wrong for other instantiations of the same function template. Fixes PR10801. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141559 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/AnalysisBasedWarnings.cpp | 18 ++++++++++++++- test/SemaCXX/warn-missing-noreturn.cpp | 32 +++++++++++++++++++++----- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index e42370d1a3..f461772ba7 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -239,7 +239,23 @@ struct CheckFallThroughDiagnostics { if (const CXXMethodDecl *Method = dyn_cast(Func)) isVirtualMethod = Method->isVirtual(); - if (!isVirtualMethod) + // Don't suggest that template instantiations be marked "noreturn" + bool isTemplateInstantiation = false; + if (const FunctionDecl *Function = dyn_cast(Func)) { + switch (Function->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + break; + + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + isTemplateInstantiation = true; + break; + } + } + + if (!isVirtualMethod && !isTemplateInstantiation) D.diag_NeverFallThroughOrReturn = diag::warn_suggest_noreturn_function; else diff --git a/test/SemaCXX/warn-missing-noreturn.cpp b/test/SemaCXX/warn-missing-noreturn.cpp index ac568a5d81..8072ac6b82 100644 --- a/test/SemaCXX/warn-missing-noreturn.cpp +++ b/test/SemaCXX/warn-missing-noreturn.cpp @@ -1,27 +1,27 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -Wmissing-noreturn -Wreturn-type void f() __attribute__((noreturn)); -template void g(T) { // expected-warning {{function 'g' could be declared with attribute 'noreturn'}} +template void g(T) { f(); } -template void g(int); // expected-note {{in instantiation of function template specialization 'g' requested here}} +template void g(int); template struct A { - void g() { // expected-warning {{function 'g' could be declared with attribute 'noreturn'}} + void g() { f(); } }; -template struct A; // expected-note {{in instantiation of member function 'A::g' requested here}} +template struct A; struct B { - template void g(T) { // expected-warning {{function 'g' could be declared with attribute 'noreturn'}} + template void g(T) { f(); } }; -template void B::g(int); // expected-note {{in instantiation of function template specialization 'B::g' requested here}} +template void B::g(int); // We don't want a warning here. struct X { @@ -103,3 +103,23 @@ rdar8875247_B test_rdar8875247_B() { return f; } // no-warning +namespace PR10801 { + struct Foo { + void wibble() __attribute((__noreturn__)); + }; + + struct Bar { + void wibble(); + }; + + template void thingy(T thing) { + thing.wibble(); + } + + void test() { + Foo f; + Bar b; + thingy(f); + thingy(b); + } +} -- 2.50.1