diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-10-10 18:15:57 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-10-10 18:15:57 +0000 |
commit | fcdd2cb2fdf35f806dd800b369fe0772a1c8c26c (patch) | |
tree | 2a9f66fa71d0039b02f8cda663c1f3289a43ca6b | |
parent | 72a81d239d6e72fab285c3a8a022c733c5e6beb4 (diff) |
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
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 18 | ||||
-rw-r--r-- | 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<CXXMethodDecl>(Func)) isVirtualMethod = Method->isVirtual(); - if (!isVirtualMethod) + // Don't suggest that template instantiations be marked "noreturn" + bool isTemplateInstantiation = false; + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(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<typename T> void g(T) { // expected-warning {{function 'g<int>' could be declared with attribute 'noreturn'}} +template<typename T> void g(T) { f(); } -template void g<int>(int); // expected-note {{in instantiation of function template specialization 'g<int>' requested here}} +template void g<int>(int); template<typename T> struct A { - void g() { // expected-warning {{function 'g' could be declared with attribute 'noreturn'}} + void g() { f(); } }; -template struct A<int>; // expected-note {{in instantiation of member function 'A<int>::g' requested here}} +template struct A<int>; struct B { - template<typename T> void g(T) { // expected-warning {{function 'g<int>' could be declared with attribute 'noreturn'}} + template<typename T> void g(T) { f(); } }; -template void B::g<int>(int); // expected-note {{in instantiation of function template specialization 'B::g<int>' requested here}} +template void B::g<int>(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 <typename T> void thingy(T thing) { + thing.wibble(); + } + + void test() { + Foo f; + Bar b; + thingy(f); + thingy(b); + } +} |