xref: /llvm-project/clang/test/CXX/except/except.spec/p3.cpp (revision b64764a30bcec0cc13fff3eb23aa3664b71ac377)
19ca5c425SRichard Smith // RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s
2fa453cfdSSebastian Redl 
3fa453cfdSSebastian Redl // Exception specification compatibility.
4fa453cfdSSebastian Redl // We test function pointers, because functions have an extra rule in p4.
5fa453cfdSSebastian Redl 
6fa453cfdSSebastian Redl // Same type is compatible
7fa453cfdSSebastian Redl extern void (*r1)() throw(int);
8fa453cfdSSebastian Redl extern void (*r1)() throw(int);
9fa453cfdSSebastian Redl 
10fa453cfdSSebastian Redl // Typedefs don't matter.
11fa453cfdSSebastian Redl typedef int INT;
12fa453cfdSSebastian Redl extern void (*r2)() throw(int);
13fa453cfdSSebastian Redl extern void (*r2)() throw(INT);
14fa453cfdSSebastian Redl 
15fa453cfdSSebastian Redl // Order doesn't matter.
16fa453cfdSSebastian Redl extern void (*r3)() throw(int, float);
17fa453cfdSSebastian Redl extern void (*r3)() throw(float, int);
18fa453cfdSSebastian Redl 
19fa453cfdSSebastian Redl // MS throw-any spec and no spec at all are compatible
20fa453cfdSSebastian Redl extern void (*r4)();
21fa453cfdSSebastian Redl extern void (*r4)() throw(...);
22fa453cfdSSebastian Redl 
23fa453cfdSSebastian Redl // throw(X) and no spec are not compatible
24fa453cfdSSebastian Redl extern void (*r5)() throw(int); // expected-note {{previous declaration}}
25fa453cfdSSebastian Redl extern void (*r5)(); // expected-error {{exception specification in declaration does not match}}
26fa453cfdSSebastian Redl 
27a91de375SRichard Smith // throw(int) and no spec are not compatible
28fa453cfdSSebastian Redl extern void f5() throw(int); // expected-note {{previous declaration}}
29a91de375SRichard Smith extern void f5(); // expected-error {{missing exception specification}}
30fa453cfdSSebastian Redl 
31fa453cfdSSebastian Redl // Different types are not compatible.
32fa453cfdSSebastian Redl extern void (*r7)() throw(int); // expected-note {{previous declaration}}
33fa453cfdSSebastian Redl extern void (*r7)() throw(float); // expected-error {{exception specification in declaration does not match}}
34fa453cfdSSebastian Redl 
35fa453cfdSSebastian Redl // Top-level const doesn't matter.
36fa453cfdSSebastian Redl extern void (*r8)() throw(int);
37fa453cfdSSebastian Redl extern void (*r8)() throw(const int);
38fa453cfdSSebastian Redl 
39fa453cfdSSebastian Redl // Multiple appearances don't matter.
40fa453cfdSSebastian Redl extern void (*r9)() throw(int, int);
41fa453cfdSSebastian Redl extern void (*r9)() throw(int, int);
42fa453cfdSSebastian Redl 
43fa453cfdSSebastian Redl 
44fa453cfdSSebastian Redl // noexcept is compatible with itself
45fa453cfdSSebastian Redl extern void (*r10)() noexcept;
46fa453cfdSSebastian Redl extern void (*r10)() noexcept;
47fa453cfdSSebastian Redl 
48fa453cfdSSebastian Redl // noexcept(true) is compatible with noexcept
49fa453cfdSSebastian Redl extern void (*r11)() noexcept;
50fa453cfdSSebastian Redl extern void (*r11)() noexcept(true);
51fa453cfdSSebastian Redl 
52fa453cfdSSebastian Redl // noexcept(false) isn't
53fa453cfdSSebastian Redl extern void (*r12)() noexcept; // expected-note {{previous declaration}}
54fa453cfdSSebastian Redl extern void (*r12)() noexcept(false); // expected-error {{does not match}}
55fa453cfdSSebastian Redl 
56fa453cfdSSebastian Redl // The form of the boolean expression doesn't matter.
57fa453cfdSSebastian Redl extern void (*r13)() noexcept(1 < 2);
58fa453cfdSSebastian Redl extern void (*r13)() noexcept(2 > 1);
59fa453cfdSSebastian Redl 
60fa453cfdSSebastian Redl // noexcept(false) is incompatible with noexcept(true)
61fa453cfdSSebastian Redl extern void (*r14)() noexcept(true); // expected-note {{previous declaration}}
62fa453cfdSSebastian Redl extern void (*r14)() noexcept(false); // expected-error {{does not match}}
63fa453cfdSSebastian Redl 
64fa453cfdSSebastian Redl // noexcept(false) is compatible with itself
65fa453cfdSSebastian Redl extern void (*r15)() noexcept(false);
66fa453cfdSSebastian Redl extern void (*r15)() noexcept(false);
67fa453cfdSSebastian Redl 
68fa453cfdSSebastian Redl // noexcept(false) is compatible with MS throw(...)
69fa453cfdSSebastian Redl extern void (*r16)() noexcept(false);
70fa453cfdSSebastian Redl extern void (*r16)() throw(...);
71fa453cfdSSebastian Redl 
72fa453cfdSSebastian Redl // noexcept(false) is *not* compatible with no spec
73fa453cfdSSebastian Redl extern void (*r17)(); // expected-note {{previous declaration}}
74fa453cfdSSebastian Redl extern void (*r17)() noexcept(false); // expected-error {{does not match}}
75fa453cfdSSebastian Redl 
76fa453cfdSSebastian Redl // except for functions
77fa453cfdSSebastian Redl void f17();
78fa453cfdSSebastian Redl void f17() noexcept(false);
79fa453cfdSSebastian Redl 
80fa453cfdSSebastian Redl // noexcept(false) is compatible with dynamic specs that throw unless
81fa453cfdSSebastian Redl // CWG 1073 resolution is accepted. Clang implements it.
82fa453cfdSSebastian Redl //extern void (*r18)() throw(int);
83fa453cfdSSebastian Redl //extern void (*r18)() noexcept(false);
84fa453cfdSSebastian Redl 
85fa453cfdSSebastian Redl // noexcept(true) is compatible with dynamic specs that don't throw
86fa453cfdSSebastian Redl extern void (*r19)() throw();
87fa453cfdSSebastian Redl extern void (*r19)() noexcept(true);
88fa453cfdSSebastian Redl 
89fa453cfdSSebastian Redl // The other way round doesn't work.
90fa453cfdSSebastian Redl extern void (*r20)() throw(); // expected-note {{previous declaration}}
91fa453cfdSSebastian Redl extern void (*r20)() noexcept(false); // expected-error {{does not match}}
92fa453cfdSSebastian Redl 
93fa453cfdSSebastian Redl extern void (*r21)() throw(int); // expected-note {{previous declaration}}
94fa453cfdSSebastian Redl extern void (*r21)() noexcept(true); // expected-error {{does not match}}
95cb5dd007SSebastian Redl 
96cb5dd007SSebastian Redl 
97cb5dd007SSebastian Redl // As a very special workaround, we allow operator new to match no spec
98cb5dd007SSebastian Redl // with a throw(bad_alloc) spec, because C++0x makes an incompatible change
99cb5dd007SSebastian Redl // here.
100c34c29f6SSebastian Redl extern "C++" { namespace std { class bad_alloc {}; } }
101e8008381SSebastian Redl typedef decltype(sizeof(int)) mysize_t;
102e8008381SSebastian Redl void* operator new(mysize_t) throw(std::bad_alloc);
103e8008381SSebastian Redl void* operator new(mysize_t);
104e8008381SSebastian Redl void* operator new[](mysize_t);
105e8008381SSebastian Redl void* operator new[](mysize_t) throw(std::bad_alloc);
106cb5dd007SSebastian Redl 
107*b64764a3SRichard Smith template<bool X> void equivalent() noexcept (X);
108*b64764a3SRichard Smith template<bool X> void equivalent() noexcept (X);
109*b64764a3SRichard Smith 
110*b64764a3SRichard Smith template<bool X, bool Y> void not_equivalent() noexcept (X); // expected-note {{previous}}
111*b64764a3SRichard Smith template<bool X, bool Y> void not_equivalent() noexcept (Y); // expected-error {{does not match}}
112*b64764a3SRichard Smith 
113*b64764a3SRichard Smith template<bool X> void missing() noexcept (X); // expected-note {{previous}}
114*b64764a3SRichard Smith // FIXME: The missing exception specification that we report here doesn't make
115*b64764a3SRichard Smith // sense in the context of this declaration.
116*b64764a3SRichard Smith template<bool P> void missing(); // expected-error {{missing exception specification 'noexcept(X)'}}
117