256 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both %s2// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter3 4 5namespace std {6 struct type_info;7 struct destroying_delete_t {8 explicit destroying_delete_t() = default;9 } inline constexpr destroying_delete{};10 struct nothrow_t {11 explicit nothrow_t() = default;12 } inline constexpr nothrow{};13 using size_t = decltype(sizeof(0));14 enum class align_val_t : size_t {};15};16 17constexpr void *operator new(std::size_t, void *p) { return p; }18namespace std {19 template<typename T> constexpr T *construct(T *p) { return new (p) T; }20 template<typename T> constexpr void destroy(T *p) { p->~T(); }21}22 23template <unsigned N>24struct S {25 S() requires (N==1) = default;26 S() requires (N==2) {} // both-note {{declared here}}27 consteval S() requires (N==3) = default;28};29 30consteval int aConstevalFunction() { // both-error {{consteval function never produces a constant expression}}31 S<2> s4; // both-note {{non-constexpr constructor 'S' cannot be used in a constant expression}}32 return 0;33}34/// We're NOT calling the above function. The diagnostics should appear anyway.35 36namespace Covariant {37 struct A {38 virtual constexpr char f() const { return 'Z'; }39 char a = f();40 };41 42 struct D : A {};43 struct Covariant1 {44 D d;45 virtual const A *f() const;46 };47 48 struct Covariant3 : Covariant1 {49 constexpr virtual const D *f() const { return &this->d; }50 };51 52 constexpr Covariant3 cb;53 constexpr const Covariant1 *cb1 = &cb;54 static_assert(cb1->f()->a == 'Z');55}56 57namespace DtorOrder {58 struct Buf {59 char buf[64];60 int n = 0;61 constexpr void operator+=(char c) { buf[n++] = c; }62 constexpr bool operator==(const char *str) const {63 if (str[n] != 0)64 return false;65 66 for (int i = 0; i < n; ++i) {67 if (buf[n] != str[n])68 return false;69 }70 return true;71 72 return __builtin_memcmp(str, buf, n) == 0;73 }74 constexpr bool operator!=(const char *str) const { return !operator==(str); }75 };76 77 struct A {78 constexpr A(Buf &buf, char c) : buf(buf), c(c) { buf += c; }79 constexpr ~A() { buf += (c - 32);}80 constexpr operator bool() const { return true; }81 Buf &buf;82 char c;83 };84 85 constexpr void abnormal_termination(Buf &buf) {86 struct Indestructible {87 constexpr ~Indestructible(); // not defined88 };89 A a(buf, 'a');90 A(buf, 'b');91 int n = 0;92 93 for (A &&c = A(buf, 'c'); A d = A(buf, 'd'); A(buf, 'e')) {94 switch (A f(buf, 'f'); A g = A(buf, 'g')) { // both-warning {{boolean}}95 case false: {96 A x(buf, 'x');97 }98 99 case true: {100 A h(buf, 'h');101 switch (n++) {102 case 0:103 break;104 case 1:105 continue;106 case 2:107 return;108 }109 break;110 }111 112 default:113 Indestructible indest;114 }115 116 A j = (A(buf, 'i'), A(buf, 'j'));117 }118 }119 120 constexpr bool check_abnormal_termination() {121 Buf buf = {};122 abnormal_termination(buf);123 return buf ==124 "abBc"125 "dfgh" /*break*/ "HGFijIJeED"126 "dfgh" /*continue*/ "HGFeED"127 "dfgh" /*return*/ "HGFD"128 "CA";129 }130 static_assert(check_abnormal_termination());131}132 133namespace std {134 struct type_info;135}136 137namespace TypeId {138 struct A {139 const std::type_info &ti = typeid(*this);140 };141 struct A2 : A {};142 static_assert(&A().ti == &typeid(A));143 static_assert(&typeid((A2())) == &typeid(A2));144 extern A2 extern_a2;145 static_assert(&typeid(extern_a2) == &typeid(A2));146 147 constexpr A2 a2;148 constexpr const A &a1 = a2;149 static_assert(&typeid(a1) == &typeid(A));150 151 struct B {152 virtual void f();153 const std::type_info &ti1 = typeid(*this);154 };155 struct B2 : B {156 const std::type_info &ti2 = typeid(*this);157 };158 static_assert(&B2().ti1 == &typeid(B));159 static_assert(&B2().ti2 == &typeid(B2));160 extern B2 extern_b2;161 static_assert(&typeid(extern_b2) == &typeid(B2));162 163 constexpr B2 b2;164 constexpr const B &b1 = b2;165 static_assert(&typeid(b1) == &typeid(B2));166 167 constexpr bool side_effects() {168 // Not polymorphic nor a glvalue.169 bool OK = true;170 (void)typeid(OK = false, A2()); // both-warning {{has no effect}}171 if (!OK) return false;172 173 // Not polymorphic.174 A2 a2;175 (void)typeid(OK = false, a2); // both-warning {{has no effect}}176 if (!OK) return false;177 178 // Not a glvalue.179 (void)typeid(OK = false, B2()); // both-warning {{has no effect}}180 if (!OK) return false;181 182 // Polymorphic glvalue: operand evaluated.183 OK = false;184 B2 b2;185 (void)typeid(OK = true, b2); // both-warning {{will be evaluated}}186 return OK;187 }188 static_assert(side_effects());189}190 191consteval int f(int i);192constexpr bool test(auto i) {193 return f(0) == 0;194}195consteval int f(int i) {196 return 2 * i;197}198static_assert(test(42));199 200namespace PureVirtual {201 struct Abstract {202 constexpr virtual void f() = 0; // both-note {{declared here}}203 constexpr Abstract() { do_it(); } // both-note {{in call to}}204 constexpr void do_it() { f(); } // both-note {{pure virtual function 'PureVirtual::Abstract::f' called}}205 };206 struct PureVirtualCall : Abstract { void f(); }; // both-note {{in call to 'Abstract}}207 constexpr PureVirtualCall pure_virtual_call; // both-error {{constant expression}} both-note {{in call to 'PureVirtualCall}}208}209 210namespace Dtor {211 constexpr bool pseudo(bool read, bool recreate) {212 using T = bool;213 bool b = false; // both-note {{lifetime has already ended}}214 // This evaluates the store to 'b'...215 (b = true).~T();216 // ... and ends the lifetime of the object.217 return (read218 ? b // both-note {{read of object outside its lifetime}}219 : true) +220 (recreate221 ? (std::construct(&b), true)222 : true);223 }224 static_assert(pseudo(false, false)); // both-error {{constant expression}} both-note {{in call}}225 static_assert(pseudo(true, false)); // both-error {{constant expression}} both-note {{in call}}226 static_assert(pseudo(false, true));227}228 229namespace GH150705 {230 struct A { };231 struct B : A { };232 struct C : A {233 constexpr virtual int foo() const { return 0; }234 };235 236 constexpr auto p = &C::foo;237 constexpr auto q = static_cast<int (A::*)() const>(p);238 constexpr B b;239 constexpr const A& a = b;240 constexpr auto x = (a.*q)(); // both-error {{constant expression}}241}242 243namespace DependentRequiresExpr {244 template <class T,245 bool = []() -> bool { // both-error {{not a constant expression}}246 if (requires { T::type; })247 return true;248 return false;249 }()>250 struct p {251 using type = void;252 };253 254 template <class T> using P = p<T>::type; // both-note {{while checking a default template argument}}255}256