reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
// 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<typename F>
__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;
}