// RUN: %clang_cc1 %s -fcxx-exceptions -fdeclspec -fsyntax-only -Wexceptions -verify -std=c++14 // RUN: %clang_cc1 %s -fcxx-exceptions -fdeclspec -fsyntax-only -Wexceptions -verify -std=c++17 -DCPP17 __attribute__((nothrow)) void f1(); static_assert(noexcept(f1()), ""); void f1() noexcept; // expected-error@+2 {{exception specification in declaration does not match previous declaration}} // expected-note@-2 {{previous declaration is here}} void f1() noexcept(false); __attribute__((nothrow)) void f2(); static_assert(noexcept(f2()), ""); // expected-error@+2 {{exception specification in declaration does not match previous declaration}} // expected-note@-3 {{previous declaration is here}} void f2() noexcept(false); void f3() __attribute__((nothrow)); static_assert(noexcept(f3()), ""); void f3() noexcept; // expected-error@+2 {{exception specification in declaration does not match previous declaration}} // expected-note@-2 {{previous declaration is here}} void f3() noexcept(false); // Still noexcept due to throw() __attribute__((nothrow)) void f4() throw(); static_assert(noexcept(f4()), ""); // Still noexcept due to noexcept __attribute__((nothrow)) void f5() noexcept; static_assert(noexcept(f5()), ""); // Still noexcept due to noexcept(true) __attribute__((nothrow)) void f6() noexcept(true); static_assert(noexcept(f6()), ""); #ifndef CPP17 // Doesn't override C++ implementation. // expected-warning@+1{{'nothrow' attribute conflicts with exception specification; attribute ignored}} __attribute__((nothrow)) void f7() throw(int); static_assert(!noexcept(f7()), ""); #endif // Doesn't override C++ implementation. // expected-warning@+1{{'nothrow' attribute conflicts with exception specification; attribute ignored}} __attribute__((nothrow)) void f8() noexcept(false); static_assert(!noexcept(f8()), ""); __declspec(nothrow) void foo1() noexcept; __declspec(nothrow) void foo2() noexcept(true); // expected-warning@+1{{'nothrow' attribute conflicts with exception specification; attribute ignored}} __declspec(nothrow) void foo3() noexcept(false); __declspec(nothrow) void foo4() noexcept(noexcept(foo1())); __declspec(nothrow) void foo5() noexcept(noexcept(foo2())); // expected-warning@+1{{'nothrow' attribute conflicts with exception specification; attribute ignored}} __declspec(nothrow) void foo6() noexcept(noexcept(foo3())); template __declspec(nothrow) void foo7() noexcept(noexcept(F())); // FIXME: It would be nice to be able to warn on these, however at the time we // evaluate the nothrow, these have yet to be parsed, so the data is not yet // there. struct S { __declspec(nothrow) void f1(); #ifndef CPP17 __declspec(nothrow) void f2() throw(); __declspec(nothrow) void f3() throw(int); #endif __declspec(nothrow) void f4() noexcept(true); __declspec(nothrow) void f5() noexcept(false); }; namespace PR42100 { class Base { public: // expected-note@+1{{overridden virtual function is here}} virtual __declspec(nothrow) void foo() = 0; // expected-note@+1{{previous declaration is here}} __declspec(nothrow) void bar(); }; // expected-warning@+1{{'bar' is missing exception specification '__attribute__((nothrow))'}} void Base::bar() {} class Sub : public Base { public: // expected-warning@+1{{exception specification of overriding function is more lax than base version}} void foo() {} }; } namespace FuncPointerReferenceConverts { void FuncToBeRefed(); #ifndef CPP17 // expected-error@+6{{target exception specification is not superset of source}} // expected-error@+6{{target exception specification is not superset of source}} #else // expected-error@+3{{non-const lvalue reference to type 'void () __attribute__((nothrow))' cannot bind to a value of unrelated type 'void ()'}} // expected-error@+3{{cannot initialize a variable of type 'void (*)() __attribute__((nothrow))' with an lvalue of type 'void ()': different exception specifications}} #endif __declspec(nothrow) void (&FuncRef)() = FuncToBeRefed; __declspec(nothrow) void (*FuncPtr)() = FuncToBeRefed; }