|
1 | 1 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s -fexceptions -fcxx-exceptions -Wno-unevaluated-expression
|
2 | 2 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++2a %s -fexceptions -fcxx-exceptions -Wno-unevaluated-expression -fexperimental-new-constant-interpreter
|
3 | 3 |
|
| 4 | +namespace std { |
| 5 | +struct type_info; |
| 6 | +} |
| 7 | + |
4 | 8 | void f(); // expected-note {{possible target for call}}
|
5 | 9 | void f(int); // expected-note {{possible target for call}}
|
6 | 10 |
|
@@ -97,3 +101,59 @@ void j() noexcept(0);
|
97 | 101 | void k() noexcept(1);
|
98 | 102 | void l() noexcept(2); // expected-error {{noexcept specifier argument evaluates to 2, which cannot be narrowed to type 'bool'}}
|
99 | 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_ |
0 commit comments