Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -6353,13 +6353,10 @@ "cannot use '%0' with Objective-C exceptions disabled">; def warn_throw_in_noexcept_func : Warning<"%0 has a non-throwing exception specification but can still " - "throw, resulting in unexpected program termination">, - InGroup; + "throw">, InGroup; def note_throw_in_dtor - : Note<"destructor or deallocator has a (possibly implicit) non-throwing " - "excepton specification">; -def note_throw_in_function - : Note<"non-throwing function declare here">; + : Note<"destructor or deallocator has a '%0' exception specification">; +def note_throw_in_function : Note<"function declared non-throwing here">; def err_seh_try_outside_functions : Error< "cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">; def err_mixing_cxx_try_seh_try : Error< Index: lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- lib/Sema/AnalysisBasedWarnings.cpp +++ lib/Sema/AnalysisBasedWarnings.cpp @@ -396,9 +396,20 @@ (isa(FD) || FD->getDeclName().getCXXOverloadedOperator() == OO_Delete || FD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete)) - S.Diag(FD->getLocation(), diag::note_throw_in_dtor); + if (FD->getTypeSourceInfo() && isa(FD)) { + const auto *Ty = + FD->getTypeSourceInfo()->getType()->getAs(); + S.Diag(FD->getLocation(), diag::note_throw_in_dtor) + << (Ty->hasExceptionSpec() ? "non-throwing" + : "implicit non-throwing") + << (Ty->hasExceptionSpec() ? FD->getExceptionSpecSourceRange() + : FD->getSourceRange()); + } else + S.Diag(FD->getLocation(), diag::note_throw_in_dtor) + << "non-throwing" << FD->getExceptionSpecSourceRange(); else - S.Diag(FD->getLocation(), diag::note_throw_in_function); + S.Diag(FD->getLocation(), diag::note_throw_in_function) + << FD->getExceptionSpecSourceRange(); } } @@ -416,8 +427,7 @@ static bool isNoexcept(const FunctionDecl *FD) { const auto *FPT = FD->getType()->castAs(); - if (FPT->getExceptionSpecType() != EST_None && - FPT->isNothrow(FD->getASTContext())) + if (FPT->isNothrow(FD->getASTContext())) return true; return false; } Index: test/CXX/except/except.spec/p11.cpp =================================================================== --- test/CXX/except/except.spec/p11.cpp +++ test/CXX/except/except.spec/p11.cpp @@ -1,10 +1,10 @@ // RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s // This is the "let the user shoot themselves in the foot" clause. -void f() noexcept { // expected-note {{non-throwing function declare here}} +void f() noexcept { // expected-note {{function declared non-throwing here}} throw 0; // expected-warning {{has a non-throwing exception specification but}} } -void g() throw() { // expected-note {{non-throwing function declare here}} +void g() throw() { // expected-note {{function declared non-throwing here}} throw 0; // expected-warning {{has a non-throwing exception specification but}} } void h() throw(int) { Index: test/SemaCXX/warn-throw-out-noexcept-func.cpp =================================================================== --- test/SemaCXX/warn-throw-out-noexcept-func.cpp +++ test/SemaCXX/warn-throw-out-noexcept-func.cpp @@ -2,8 +2,8 @@ struct A_ShouldDiag { ~A_ShouldDiag(); // implicitly noexcept(true) }; -A_ShouldDiag::~A_ShouldDiag() { // expected-note {{destructor or deallocator has a (possibly implicit) non-throwing excepton specification}} - throw 1; // expected-warning {{has a non-throwing exception specification but can still throw, resulting in unexpected program termination}} +A_ShouldDiag::~A_ShouldDiag() { // expected-note {{destructor or deallocator has a 'implicit non-throwing' exception specification}} + throw 1; // expected-warning {{has a non-throwing exception specification but can still throw}} } struct B_ShouldDiag { int i; @@ -119,7 +119,7 @@ throw 1; // expected-warning {{has a non-throwing exception specification but}} } }; -void foo() noexcept { //expected-note {{non-throwing function declare here}} +void foo() noexcept { //expected-note {{function declared non-throwing here}} throw 1; // expected-warning {{has a non-throwing exception specification but}} } struct Throws { @@ -158,21 +158,21 @@ } } -void h_ShouldDiag() noexcept { //expected-note {{non-throwing function declare here}} +void h_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}} try { throw 12; // expected-warning {{has a non-throwing exception specification but}} } catch (const char *) { } } -void i_ShouldDiag() noexcept { //expected-note {{non-throwing function declare here}} +void i_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}} try { throw 12; } catch (int) { throw; // expected-warning {{has a non-throwing exception specification but}} } } -void j_ShouldDiag() noexcept { //expected-note {{non-throwing function declare here}} +void j_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}} try { throw 12; } catch (int) { @@ -180,7 +180,7 @@ } } -void k_ShouldDiag() noexcept { //expected-note {{non-throwing function declare here}} +void k_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}} try { throw 12; } catch (...) { @@ -188,7 +188,7 @@ } } -void loo_ShouldDiag(int i) noexcept { //expected-note {{non-throwing function declare here}} +void loo_ShouldDiag(int i) noexcept { //expected-note {{function declared non-throwing here}} if (i) try { throw 12; @@ -203,13 +203,13 @@ throw 12; } -void loo2_ShouldDiag() noexcept { //expected-note {{non-throwing function declare here}} +void loo2_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}} if (1) throw 12; // expected-warning {{has a non-throwing exception specification but}} } struct S {}; -void l_ShouldDiag() noexcept { //expected-note {{non-throwing function declare here}} +void l_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}} try { throw S{}; //expected-warning {{has a non-throwing exception specification but}} } catch (S *s) { @@ -231,7 +231,7 @@ } catch (const S &s) { } } -void o_ShouldDiag() noexcept { //expected-note {{non-throwing function declare here}} +void o_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}} try { throw; //expected-warning {{has a non-throwing exception specification but}} } catch (...) { @@ -239,7 +239,7 @@ } #define NOEXCEPT noexcept -void with_macro() NOEXCEPT { //expected-note {{non-throwing function declare here}} +void with_macro() NOEXCEPT { //expected-note {{function declared non-throwing here}} throw 1; // expected-warning {{has a non-throwing exception specification but}} } @@ -248,7 +248,7 @@ } catch (...) { } -void with_try_block1() noexcept try { //expected-note {{non-throwing function declare here}} +void with_try_block1() noexcept try { //expected-note {{function declared non-throwing here}} throw 2; // expected-warning {{has a non-throwing exception specification but}} } catch (char *) { }