1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s -fexceptions -fcxx-exceptions -Wno-unevaluated-expression 2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s -fexceptions -fcxx-exceptions -Wno-unevaluated-expression -fexperimental-new-constant-interpreter 3 4 namespace std { 5 struct type_info; 6 } 7 8 void f(); // expected-note {{possible target for call}} 9 void f(int); // expected-note {{possible target for call}} 10 11 void g() { 12 bool b = noexcept(f); // expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} 13 bool b2 = noexcept(f(0)); 14 } 15 16 struct S { 17 void g(); // expected-note {{possible target for call}} 18 void g(int); // expected-note {{possible target for call}} 19 20 void h() { 21 bool b = noexcept(this->g); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}} 22 bool b2 = noexcept(this->g(0)); 23 } 24 }; 25 26 void stmt_expr() { 27 static_assert(noexcept(({ 0; }))); 28 29 static_assert(!noexcept(({ throw 0; }))); 30 31 static_assert(noexcept(({ 32 try { 33 throw 0; 34 } catch (...) { 35 } 36 0; 37 }))); 38 39 static_assert(!noexcept(({ 40 try { 41 throw 0; 42 } catch (...) { 43 throw; 44 } 45 0; 46 }))); 47 48 static_assert(!noexcept(({ 49 try { 50 throw 0; 51 } catch (int) { 52 } 53 0; 54 }))); 55 56 static_assert(!noexcept(({ 57 if (false) throw 0; 58 }))); 59 60 static_assert(noexcept(({ 61 if constexpr (false) throw 0; 62 }))); 63 64 static_assert(!noexcept(({ 65 if constexpr (false) throw 0; else throw 1; 66 }))); 67 68 static_assert(noexcept(({ 69 if constexpr (true) 0; else throw 1; 70 }))); 71 } 72 73 void vla(bool b) { // expected-note 5{{declared here}} 74 static_assert(noexcept(static_cast<int(*)[true ? 41 : 42]>(0)), ""); 75 // FIXME: This can't actually throw, but we conservatively assume any VLA 76 // type can throw for now. 77 static_assert(!noexcept(static_cast<int(*)[b ? 41 : 42]>(0)), ""); // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 78 expected-note {{function parameter 'b' with unknown value cannot be used in a constant expression}} 79 static_assert(!noexcept(static_cast<int(*)[b ? throw : 42]>(0)), ""); // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 80 expected-note {{function parameter 'b' with unknown value cannot be used in a constant expression}} 81 static_assert(!noexcept(reinterpret_cast<int(*)[b ? throw : 42]>(0)), ""); // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 82 expected-note {{function parameter 'b' with unknown value cannot be used in a constant expression}} 83 static_assert(!noexcept((int(*)[b ? throw : 42])0), ""); // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 84 expected-note {{function parameter 'b' with unknown value cannot be used in a constant expression}} 85 static_assert(!noexcept((int(*)[b ? throw : 42]){0}), ""); // expected-warning {{variable length arrays in C++ are a Clang extension}} \ 86 expected-note {{function parameter 'b' with unknown value cannot be used in a constant expression}} 87 } 88 89 struct pr_44514 { 90 // expected-error@+1{{value of type 'void' is not implicitly convertible to 'bool'}} 91 void foo(void) const &noexcept(f()); 92 }; 93 94 namespace P1401 { 95 const int *ptr = nullptr; 96 void f() noexcept(sizeof(char[2])); // expected-error {{noexcept specifier argument evaluates to 2, which cannot be narrowed to type 'bool'}} 97 void g() noexcept(sizeof(char)); 98 void h() noexcept(ptr); // expected-error {{conversion from 'const int *' to 'bool' is not allowed in a converted constant expression}} 99 void i() noexcept(nullptr); // expected-error {{conversion from 'std::nullptr_t' to 'bool' is not allowed in a converted constant expression}} 100 void j() noexcept(0); 101 void k() noexcept(1); 102 void l() noexcept(2); // expected-error {{noexcept specifier argument evaluates to 2, which cannot be narrowed to type 'bool'}} 103 } // namespace P1401 104 105 namespace typeid_ { 106 template<bool NoexceptConstructor, bool NoexceptDestructor> 107 struct Polymorphic { 108 Polymorphic() noexcept(NoexceptConstructor) {} 109 virtual ~Polymorphic() noexcept(NoexceptDestructor) {} 110 }; 111 112 static_assert(noexcept(typeid(Polymorphic<false, false>{}))); // Not evaluated (not glvalue) 113 static_assert(noexcept(typeid((Polymorphic<true, true>&&) Polymorphic<true, true>{}))); 114 static_assert(!noexcept(typeid((Polymorphic<false, true>&&) Polymorphic<false, true>{}))); 115 static_assert(!noexcept(typeid((Polymorphic<true, false>&&) Polymorphic<true, false>{}))); 116 static_assert(!noexcept(typeid(*&(const Polymorphic<true, true>&) Polymorphic<true, true>{}))); 117 static_assert(!noexcept(typeid(*&(const Polymorphic<false, true>&) Polymorphic<false, true>{}))); 118 static_assert(!noexcept(typeid(*&(const Polymorphic<true, false>&) Polymorphic<true, false>{}))); 119 120 template<bool B> 121 struct X { 122 template<typename T> void f(); 123 }; 124 template<typename T> 125 void f1() { 126 X<noexcept(typeid(*T{}))> dependent; 127 // `dependent` should be type-dependent because the noexcept-expression should be value-dependent 128 // (it is true if T is int*, false if T is Polymorphic<false, false>* for example) 129 dependent.f<void>(); // This should need to be `.template f` to parse as a template 130 // expected-error@-1 {{use 'template' keyword to treat 'f' as a dependent template name}} 131 } 132 template<typename... T> 133 void f2() { 134 X<noexcept(typeid(*((static_cast<Polymorphic<false, false>*>(nullptr) && ... && T{}))))> dependent; 135 // X<true> when T...[0] is a type with some operator&& which returns int* 136 // X<false> when sizeof...(T) == 0 137 dependent.f<void>(); 138 // expected-error@-1 {{use 'template' keyword to treat 'f' as a dependent template name}} 139 } 140 template<typename T> 141 void f3() { 142 X<noexcept(typeid(*static_cast<T*>(nullptr)))> dependent; 143 // X<true> when T is int, X<false> when T is Polymorphic<false, false> 144 dependent.f<void>(); 145 // expected-error@-1 {{use 'template' keyword to treat 'f' as a dependent template name}} 146 } 147 template<typename T> 148 void f4() { 149 X<noexcept(typeid(T))> not_dependent; 150 not_dependent.non_existent(); 151 // expected-error@-1 {{no member named 'non_existent' in 'typeid_::X<true>'}} 152 } 153 template<typename T> 154 void f5() { 155 X<noexcept(typeid(sizeof(sizeof(T))))> not_dependent; 156 not_dependent.non_existent(); 157 // expected-error@-1 {{no member named 'non_existent' in 'typeid_::X<true>'}} 158 } 159 } // namespace typeid_ 160 161 namespace GH97453 { 162 163 struct UnconstrainedCtor { 164 int value_; 165 166 template <typename T> 167 constexpr UnconstrainedCtor(T value) noexcept(noexcept(value_ = value)) 168 : value_(static_cast<int>(value)) {} 169 }; 170 171 UnconstrainedCtor U(42); 172 173 struct X { 174 void ICE(int that) noexcept(noexcept([that]() {})); 175 }; 176 177 } // namespace GH97453 178