Nico Weber | 7288943 | 2014-09-06 01:25:55 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall -Wno-unused-local-typedefs %s |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 2 | |
| 3 | template<bool b> struct ExceptionIf { static int f(); }; |
| 4 | template<> struct ExceptionIf<false> { typedef int f; }; |
| 5 | |
| 6 | // The exception specification of a defaulted default constructor depends on |
| 7 | // the contents of in-class member initializers. However, the in-class member |
| 8 | // initializers can depend on the exception specification of the constructor, |
| 9 | // since the class is considered complete within them. We reject any such cases. |
| 10 | namespace InClassInitializers { |
| 11 | // Noexcept::Noexcept() is implicitly declared as noexcept(false), because it |
| 12 | // directly invokes ThrowSomething(). However... |
| 13 | // |
| 14 | // If noexcept(Noexcept()) is false, then Noexcept() is a constant expression, |
| 15 | // so noexcept(Noexcept()) is true. But if noexcept(Noexcept()) is true, then |
| 16 | // Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept()) |
| 17 | // is false. |
| 18 | bool ThrowSomething() noexcept(false); |
| 19 | struct ConstExpr { |
Reid Kleckner | d60b82f | 2014-11-17 23:36:45 +0000 | [diff] [blame] | 20 | bool b = noexcept(ConstExpr()) && ThrowSomething(); // expected-error {{cannot use defaulted default constructor of 'ConstExpr' within the class outside of member functions}} |
| 21 | // expected-note@-1 {{implicit default constructor for 'InClassInitializers::ConstExpr' first required here}} |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 22 | }; |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 23 | |
| 24 | // Much more obviously broken: we can't parse the initializer without already |
| 25 | // knowing whether it produces a noexcept expression. |
| 26 | struct TemplateArg { |
Reid Kleckner | d60b82f | 2014-11-17 23:36:45 +0000 | [diff] [blame] | 27 | int n = ExceptionIf<noexcept(TemplateArg())>::f(); // expected-error {{cannot use defaulted default constructor of 'TemplateArg' within the class outside of member functions}} |
| 28 | // expected-note@-1 {{implicit default constructor for 'InClassInitializers::TemplateArg' first required here}} |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 29 | }; |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 30 | |
| 31 | // And within a nested class. |
Reid Kleckner | d60b82f | 2014-11-17 23:36:45 +0000 | [diff] [blame] | 32 | struct Nested { // expected-note {{implicit default constructor for 'InClassInitializers::Nested::Inner' first required here}} |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 33 | struct Inner { |
Reid Kleckner | d60b82f | 2014-11-17 23:36:45 +0000 | [diff] [blame] | 34 | // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested' outside of member functions}} |
Richard Smith | e10d304 | 2012-11-07 01:14:25 +0000 | [diff] [blame] | 35 | int n = ExceptionIf<noexcept(Nested())>::f(); // expected-note {{implicit default constructor for 'InClassInitializers::Nested' first required here}} |
| 36 | } inner; |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 37 | }; |
Richard Smith | d3b5c908 | 2012-07-27 04:22:15 +0000 | [diff] [blame] | 38 | |
Reid Kleckner | d60b82f | 2014-11-17 23:36:45 +0000 | [diff] [blame] | 39 | struct Nested2 { // expected-error {{implicit default constructor for 'InClassInitializers::Nested2' must explicitly initialize the member 'inner' which does not have a default constructor}} |
Richard Smith | d3b5c908 | 2012-07-27 04:22:15 +0000 | [diff] [blame] | 40 | struct Inner; |
Reid Kleckner | d60b82f | 2014-11-17 23:36:45 +0000 | [diff] [blame] | 41 | int n = Inner().n; // expected-note {{implicit default constructor for 'InClassInitializers::Nested2::Inner' first required here}} |
| 42 | struct Inner { // expected-note {{declared here}} |
| 43 | // expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested2' outside of member functions}} |
Richard Smith | e10d304 | 2012-11-07 01:14:25 +0000 | [diff] [blame] | 44 | int n = ExceptionIf<noexcept(Nested2())>::f(); |
Reid Kleckner | d60b82f | 2014-11-17 23:36:45 +0000 | [diff] [blame] | 45 | // expected-note@-1 {{implicit default constructor for 'InClassInitializers::Nested2' first required here}} |
| 46 | } inner; // expected-note {{member is declared here}} |
Richard Smith | d3b5c908 | 2012-07-27 04:22:15 +0000 | [diff] [blame] | 47 | }; |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 48 | } |
| 49 | |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 50 | namespace ExceptionSpecification { |
Richard Smith | 0b3a462 | 2014-11-13 20:01:57 +0000 | [diff] [blame] | 51 | // FIXME: This diagnostic is quite useless; we should indicate whose |
| 52 | // exception specification we were looking for and why. |
| 53 | struct Nested { |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 54 | struct T { |
Richard Smith | 0b3a462 | 2014-11-13 20:01:57 +0000 | [diff] [blame] | 55 | T() noexcept(!noexcept(Nested())); |
| 56 | } t; // expected-error{{exception specification is not available until end of class definition}} |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 57 | }; |
| 58 | } |
| 59 | |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 60 | namespace DefaultArgument { |
Richard Smith | 852265f | 2012-03-30 20:53:28 +0000 | [diff] [blame] | 61 | struct Default { |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 62 | struct T { |
Douglas Gregor | 74f7d50 | 2012-02-15 19:33:52 +0000 | [diff] [blame] | 63 | T(int = ExceptionIf<noexcept(Default())::f()); // expected-error {{call to implicitly-deleted default constructor}} |
Richard Smith | 852265f | 2012-03-30 20:53:28 +0000 | [diff] [blame] | 64 | } t; // expected-note {{has no default constructor}} |
Richard Smith | 938f40b | 2011-06-11 17:19:42 +0000 | [diff] [blame] | 65 | }; |
| 66 | } |
Richard Smith | 84973e5 | 2012-04-21 18:42:51 +0000 | [diff] [blame] | 67 | |
| 68 | namespace ImplicitDtorExceptionSpec { |
| 69 | struct A { |
| 70 | virtual ~A(); |
| 71 | |
| 72 | struct Inner { |
| 73 | ~Inner() throw(); |
| 74 | }; |
| 75 | Inner inner; |
| 76 | }; |
| 77 | |
| 78 | struct B { |
| 79 | virtual ~B() {} // expected-note {{here}} |
| 80 | }; |
| 81 | |
| 82 | struct C : B { |
| 83 | virtual ~C() {} |
| 84 | A a; |
| 85 | }; |
| 86 | |
| 87 | struct D : B { |
| 88 | ~D(); // expected-error {{more lax than base}} |
| 89 | struct E { |
| 90 | ~E(); |
| 91 | struct F { |
| 92 | ~F() throw(A); |
| 93 | } f; |
| 94 | } e; |
| 95 | }; |
| 96 | } |