Richard Smith a91de375f2 Promote a warning on ill-formed code (redeclaration missing an exception
specification) to an error. No compiler other than Clang seems to allow this,
and it doesn't seem like a useful thing to accept as an extension in general.

The current behavior was added for PR5957, where the problem was specifically
related to mismatches of the exception specification on the implicitly-declared
global operator new and delete. To retain that workaround, we downgrade the
error to an ExtWarn when the declaration is of a replaceable global allocation
function.

Now that this is an error, stop trying (and failing) to recover from a missing
computed noexcept specification. That recovery didn't work, and led to crashes
in code like the added testcase.

llvm-svn: 248867
2015-09-30 00:48:50 +00:00

107 lines
3.7 KiB
C++

// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -fsyntax-only -verify %s
// Exception specification compatibility.
// We test function pointers, because functions have an extra rule in p4.
// Same type is compatible
extern void (*r1)() throw(int);
extern void (*r1)() throw(int);
// Typedefs don't matter.
typedef int INT;
extern void (*r2)() throw(int);
extern void (*r2)() throw(INT);
// Order doesn't matter.
extern void (*r3)() throw(int, float);
extern void (*r3)() throw(float, int);
// MS throw-any spec and no spec at all are compatible
extern void (*r4)();
extern void (*r4)() throw(...);
// throw(X) and no spec are not compatible
extern void (*r5)() throw(int); // expected-note {{previous declaration}}
extern void (*r5)(); // expected-error {{exception specification in declaration does not match}}
// throw(int) and no spec are not compatible
extern void f5() throw(int); // expected-note {{previous declaration}}
extern void f5(); // expected-error {{missing exception specification}}
// Different types are not compatible.
extern void (*r7)() throw(int); // expected-note {{previous declaration}}
extern void (*r7)() throw(float); // expected-error {{exception specification in declaration does not match}}
// Top-level const doesn't matter.
extern void (*r8)() throw(int);
extern void (*r8)() throw(const int);
// Multiple appearances don't matter.
extern void (*r9)() throw(int, int);
extern void (*r9)() throw(int, int);
// noexcept is compatible with itself
extern void (*r10)() noexcept;
extern void (*r10)() noexcept;
// noexcept(true) is compatible with noexcept
extern void (*r11)() noexcept;
extern void (*r11)() noexcept(true);
// noexcept(false) isn't
extern void (*r12)() noexcept; // expected-note {{previous declaration}}
extern void (*r12)() noexcept(false); // expected-error {{does not match}}
// The form of the boolean expression doesn't matter.
extern void (*r13)() noexcept(1 < 2);
extern void (*r13)() noexcept(2 > 1);
// noexcept(false) is incompatible with noexcept(true)
extern void (*r14)() noexcept(true); // expected-note {{previous declaration}}
extern void (*r14)() noexcept(false); // expected-error {{does not match}}
// noexcept(false) is compatible with itself
extern void (*r15)() noexcept(false);
extern void (*r15)() noexcept(false);
// noexcept(false) is compatible with MS throw(...)
extern void (*r16)() noexcept(false);
extern void (*r16)() throw(...);
// noexcept(false) is *not* compatible with no spec
extern void (*r17)(); // expected-note {{previous declaration}}
extern void (*r17)() noexcept(false); // expected-error {{does not match}}
// except for functions
void f17();
void f17() noexcept(false);
// noexcept(false) is compatible with dynamic specs that throw unless
// CWG 1073 resolution is accepted. Clang implements it.
//extern void (*r18)() throw(int);
//extern void (*r18)() noexcept(false);
// noexcept(true) is compatible with dynamic specs that don't throw
extern void (*r19)() throw();
extern void (*r19)() noexcept(true);
// The other way round doesn't work.
extern void (*r20)() throw(); // expected-note {{previous declaration}}
extern void (*r20)() noexcept(false); // expected-error {{does not match}}
extern void (*r21)() throw(int); // expected-note {{previous declaration}}
extern void (*r21)() noexcept(true); // expected-error {{does not match}}
// As a very special workaround, we allow operator new to match no spec
// with a throw(bad_alloc) spec, because C++0x makes an incompatible change
// here.
extern "C++" { namespace std { class bad_alloc {}; } }
typedef decltype(sizeof(int)) mysize_t;
void* operator new(mysize_t) throw(std::bad_alloc);
void* operator new(mysize_t);
void* operator new[](mysize_t);
void* operator new[](mysize_t) throw(std::bad_alloc);