Timm =?utf-8?q?Bäder?= <tbae...@redhat.com> Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/79...@github.com>
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/79452 >From a0727e28e16a051bce8b1b2dd8f5ace6b2b54394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Tue, 6 Feb 2024 10:03:15 +0100 Subject: [PATCH 1/2] [clang][Interp][NFC] Simplify test case By checking using verify={ref,expected},both. --- clang/test/AST/Interp/literals.cpp | 382 ++++++++++------------------- 1 file changed, 129 insertions(+), 253 deletions(-) diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp index 0031e577580aa..c2bc5338ea925 100644 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -Wno-vla -fms-extensions -std=c++11 -verify %s -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -Wno-vla -fms-extensions -std=c++20 -verify %s -// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-vla -verify=ref %s -// RUN: %clang_cc1 -std=c++20 -fms-extensions -Wno-vla -verify=ref %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -Wno-vla -fms-extensions -std=c++11 -verify=expected,both %s +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -Wno-vla -fms-extensions -std=c++20 -verify=expected,both %s +// RUN: %clang_cc1 -std=c++11 -fms-extensions -Wno-vla -verify=ref,both %s +// RUN: %clang_cc1 -std=c++20 -fms-extensions -Wno-vla -verify=ref,both %s #define INT_MIN (~__INT_MAX__) #define INT_MAX __INT_MAX__ @@ -11,21 +11,19 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t; static_assert(true, ""); -static_assert(false, ""); // expected-error{{failed}} ref-error{{failed}} +static_assert(false, ""); // both-error{{failed}} static_assert(nullptr == nullptr, ""); static_assert(__null == __null, ""); static_assert(1 == 1, ""); -static_assert(1 == 3, ""); // expected-error{{failed}} ref-error{{failed}} +static_assert(1 == 3, ""); // both-error{{failed}} constexpr void* v = nullptr; static_assert(__null == v, ""); constexpr int number = 10; static_assert(number == 10, ""); -static_assert(number != 10, ""); // expected-error{{failed}} \ - // ref-error{{failed}} \ - // expected-note{{evaluates to}} \ - // ref-note{{evaluates to}} +static_assert(number != 10, ""); // both-error{{failed}} \ + // both-note{{evaluates to}} static_assert(__objc_yes, ""); static_assert(!__objc_no, ""); @@ -38,22 +36,14 @@ static_assert(one == 1, ""); constexpr bool b2 = bool(); static_assert(!b2, ""); -constexpr int Failed1 = 1 / 0; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{division by zero}} \ - // expected-note {{declared here}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{division by zero}} \ - // ref-note {{declared here}} -constexpr int Failed2 = Failed1 + 1; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{declared here}} \ - // expected-note {{initializer of 'Failed1' is not a constant expression}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{declared here}} \ - // ref-note {{initializer of 'Failed1' is not a constant expression}} -static_assert(Failed2 == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{initializer of 'Failed2' is not a constant expression}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{initializer of 'Failed2' is not a constant expression}} +constexpr int Failed1 = 1 / 0; // both-error {{must be initialized by a constant expression}} \ + // both-note {{division by zero}} \ + // both-note {{declared here}} +constexpr int Failed2 = Failed1 + 1; // both-error {{must be initialized by a constant expression}} \ + // both-note {{declared here}} \ + // both-note {{initializer of 'Failed1' is not a constant expression}} +static_assert(Failed2 == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{initializer of 'Failed2' is not a constant expression}} namespace ScalarTypes { constexpr int ScalarInitInt = int(); @@ -112,10 +102,8 @@ namespace IntegralCasts { static_assert(!nu, ""); }; -constexpr int UninitI; // expected-error {{must be initialized by a constant expression}} \ - // ref-error {{must be initialized by a constant expression}} -constexpr int *UninitPtr; // expected-error {{must be initialized by a constant expression}} \ - // ref-error {{must be initialized by a constant expression}} +constexpr int UninitI; // both-error {{must be initialized by a constant expression}} +constexpr int *UninitPtr; // both-error {{must be initialized by a constant expression}} constexpr bool getTrue() { return true; } constexpr bool getFalse() { return false; } @@ -134,7 +122,7 @@ static_assert(false == 0, ""); static_assert(!5 == false, ""); static_assert(!0, ""); static_assert(-true, ""); -static_assert(-false, ""); //expected-error{{failed}} ref-error{{failed}} +static_assert(-false, ""); //both-error{{failed}} static_assert(~0 == -1, ""); static_assert(~1 == -2, ""); @@ -143,10 +131,8 @@ static_assert(~255 == -256, ""); static_assert(~INT_MIN == INT_MAX, ""); static_assert(~INT_MAX == INT_MIN, ""); -static_assert(-(1 << 31), ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{outside the range of representable values}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{outside the range of representable values}} \ +static_assert(-(1 << 31), ""); // both-error {{not an integral constant expression}} \ + // both-note {{outside the range of representable values}} namespace PrimitiveEmptyInitList { constexpr int a = {}; @@ -199,10 +185,8 @@ namespace PointerComparison { constexpr void *pv = (void*)&s.a; constexpr void *qv = (void*)&s.b; constexpr bool v1 = null < (int*)0; - constexpr bool v2 = null < pv; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{comparison between 'nullptr' and '&s.a' has unspecified value}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{comparison between 'nullptr' and '&s.a' has unspecified value}} \ + constexpr bool v2 = null < pv; // both-error {{must be initialized by a constant expression}} \ + // both-note {{comparison between 'nullptr' and '&s.a' has unspecified value}} constexpr bool v3 = null == pv; // ok constexpr bool v4 = qv == pv; // ok @@ -213,10 +197,8 @@ namespace PointerComparison { // ref-note {{unequal pointers to void}} constexpr bool v8 = qv > (void*)&s.a; // ref-error {{constant expression}} \ // ref-note {{unequal pointers to void}} - constexpr bool v6 = qv > null; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{comparison between '&s.b' and 'nullptr' has unspecified value}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{comparison between '&s.b' and 'nullptr' has unspecified value}} + constexpr bool v6 = qv > null; // both-error {{must be initialized by a constant expression}} \ + // both-note {{comparison between '&s.b' and 'nullptr' has unspecified value}} constexpr bool v7 = qv <= (void*)&s.b; // ok @@ -229,10 +211,8 @@ namespace PointerComparison { constexpr long m3 = (&m3 + 1) - (&m3); static_assert(m3 == 1, ""); - constexpr long m4 = &m4 + 2 - &m4; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cannot refer to element 2 of non-array object}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cannot refer to element 2 of non-array object}} + constexpr long m4 = &m4 + 2 - &m4; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cannot refer to element 2 of non-array object}} } namespace SizeOf { @@ -257,11 +237,9 @@ namespace SizeOf { static_assert(sizeof(bool) == 1, ""); static_assert(sizeof(char) == 1, ""); - constexpr int F = sizeof(void); // expected-error{{incomplete type 'void'}} \ - // ref-error{{incomplete type 'void'}} + constexpr int F = sizeof(void); // both-error{{incomplete type 'void'}} - constexpr int F2 = sizeof(gimme); // expected-error{{to a function type}} \ - // ref-error{{to a function type}} + constexpr int F2 = sizeof(gimme); // both-error{{to a function type}} struct S { @@ -273,22 +251,19 @@ namespace SizeOf { void func() { int n = 12; - constexpr int oofda = sizeof(int[n++]); // expected-error {{must be initialized by a constant expression}} \ - // ref-error {{must be initialized by a constant expression}} + constexpr int oofda = sizeof(int[n++]); // both-error {{must be initialized by a constant expression}} } #if __cplusplus >= 201402L constexpr int IgnoredRejected() { // ref-error {{never produces a constant expression}} int n = 0; - sizeof(int[n++]); // expected-warning {{expression result unused}} \ - // ref-warning {{expression result unused}} \ + sizeof(int[n++]); // both-warning {{expression result unused}} \ // ref-note 2{{subexpression not valid in a constant expression}} return n; } /// FIXME: This is rejected because the parameter so sizeof() is not constant. /// produce a proper diagnostic. - static_assert(IgnoredRejected() == 0, ""); // expected-error {{not an integral constant expression}} \ - // ref-error {{not an integral constant expression}} \ + static_assert(IgnoredRejected() == 0, ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'IgnoredRejected()'}} #endif @@ -317,32 +292,22 @@ namespace rem { static_assert(-3 % -4 == -3, ""); constexpr int zero() { return 0; } - static_assert(10 % zero() == 20, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{division by zero}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{division by zero}} - + static_assert(10 % zero() == 20, ""); // both-error {{not an integral constant expression}} \ + // both-note {{division by zero}} static_assert(true % true == 0, ""); static_assert(false % true == 0, ""); - static_assert(true % false == 10, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{division by zero}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{division by zero}} - constexpr int x = INT_MIN % - 1; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{value 2147483648 is outside the range}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{value 2147483648 is outside the range}} \ - + static_assert(true % false == 10, ""); // both-error {{not an integral constant expression}} \ + // both-note {{division by zero}} + constexpr int x = INT_MIN % - 1; // both-error {{must be initialized by a constant expression}} \ + // both-note {{value 2147483648 is outside the range}} }; namespace div { constexpr int zero() { return 0; } static_assert(12 / 3 == 4, ""); - static_assert(12 / zero() == 12, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{division by zero}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{division by zero}} + static_assert(12 / zero() == 12, ""); // both-error {{not an integral constant expression}} \ + // both-note {{division by zero}} static_assert(12 / -3 == -4, ""); static_assert(-12 / 3 == -4, ""); @@ -351,11 +316,8 @@ namespace div { constexpr long unsigned RHS = 3; static_assert(LHS / RHS == 4, ""); - constexpr int x = INT_MIN / - 1; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{value 2147483648 is outside the range}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{value 2147483648 is outside the range}} \ - + constexpr int x = INT_MIN / - 1; // both-error {{must be initialized by a constant expression}} \ + // both-note {{value 2147483648 is outside the range}} }; namespace cond { @@ -446,8 +408,7 @@ namespace bitXor { #if __cplusplus >= 201402L constexpr bool IgnoredUnary() { bool bo = true; - !bo; // expected-warning {{expression result unused}} \ - // ref-warning {{expression result unused}} + !bo; // both-warning {{expression result unused}} return bo; } static_assert(IgnoredUnary(), ""); @@ -482,15 +443,11 @@ namespace strings { #pragma clang diagnostic ignored "-Wmultichar" constexpr int mc = 'abc'; static_assert(mc == 'abc', ""); - __WCHAR_TYPE__ wm = L'abc'; // ref-error{{wide character literals may not contain multiple characters}} \ - // expected-error{{wide character literals may not contain multiple characters}} - __WCHAR_TYPE__ wu = u'abc'; // ref-error{{Unicode character literals may not contain multiple characters}} \ - // expected-error{{Unicode character literals may not contain multiple characters}} - __WCHAR_TYPE__ wU = U'abc'; // ref-error{{Unicode character literals may not contain multiple characters}} \ - // expected-error{{Unicode character literals may not contain multiple characters}} + __WCHAR_TYPE__ wm = L'abc'; // both-error{{wide character literals may not contain multiple characters}} + __WCHAR_TYPE__ wu = u'abc'; // both-error{{Unicode character literals may not contain multiple characters}} + __WCHAR_TYPE__ wU = U'abc'; // both-error{{Unicode character literals may not contain multiple characters}} #if __cplusplus > 201103L - __WCHAR_TYPE__ wu8 = u8'abc'; // ref-error{{Unicode character literals may not contain multiple characters}} \ - // expected-error{{Unicode character literals may not contain multiple characters}} + __WCHAR_TYPE__ wu8 = u8'abc'; // both-error{{Unicode character literals may not contain multiple characters}} #endif #pragma clang diagnostic pop @@ -507,26 +464,19 @@ namespace strings { static_assert(foo2[3] == '\0', ""); static_assert(foo2[6] == 'f', ""); static_assert(foo2[7] == '\0', ""); - static_assert(foo2[8] == '\0', ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{read of dereferenced one-past-the-end pointer}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{read of dereferenced one-past-the-end pointer}} + static_assert(foo2[8] == '\0', ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of dereferenced one-past-the-end pointer}} constexpr char foo3[4] = "abc"; static_assert(foo3[3] == '\0', ""); - static_assert(foo3[4] == '\0', ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{read of dereferenced one-past-the-end pointer}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{read of dereferenced one-past-the-end pointer}} + static_assert(foo3[4] == '\0', ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of dereferenced one-past-the-end pointer}} - constexpr char foo4[2] = "abcd"; // expected-error {{initializer-string for char array is too long}} \ - // ref-error {{initializer-string for char array is too long}} + constexpr char foo4[2] = "abcd"; // both-error {{initializer-string for char array is too long}} static_assert(foo4[0] == 'a', ""); static_assert(foo4[1] == 'b', ""); - static_assert(foo4[2] == '\0', ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{read of dereferenced one-past-the-end pointer}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{read of dereferenced one-past-the-end pointer}} + static_assert(foo4[2] == '\0', ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of dereferenced one-past-the-end pointer}} constexpr char foo5[12] = "abc\xff"; #if defined(__CHAR_UNSIGNED__) || __CHAR_BIT__ > 8 @@ -574,16 +524,13 @@ namespace IncDec { constexpr int three() { int a = 0; - return ++a + ++a; // expected-warning {{multiple unsequenced modifications to 'a'}} \ - // ref-warning {{multiple unsequenced modifications to 'a'}} \ - + return ++a + ++a; // both-warning {{multiple unsequenced modifications to 'a'}} } static_assert(three() == 3, ""); constexpr bool incBool() { bool b = false; - return ++b; // expected-error {{ISO C++17 does not allow incrementing expression of type bool}} \ - // ref-error {{ISO C++17 does not allow incrementing expression of type bool}} + return ++b; // both-error {{ISO C++17 does not allow incrementing expression of type bool}} } static_assert(incBool(), ""); @@ -611,73 +558,54 @@ namespace IncDec { } return 1; } - static_assert(uninit<int, true, true>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<int, true, true>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<int, true, true>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<int, false, true>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<int, false, true>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<int, false, true>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<float, true, true>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<float, true, true>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<float, true, true>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<float, false, true>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<float, false, true>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<float, false, true>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<float, true, false>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<float, true, false>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<float, true, false>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<float, false, false>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<float, false, false>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<float, false, false>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<int*, true, true>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<int*, true, true>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<int *, true, true>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<int*, false, true>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<int*, false, true>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<int *, false, true>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<int*, true, false>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<int*, true, false>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<int *, true, false>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - static_assert(uninit<int*, false, false>(), ""); // ref-error {{not an integral constant expression}} \ + static_assert(uninit<int*, false, false>(), ""); // both-error {{not an integral constant expression}} \ // ref-note {{in call to 'uninit<int *, false, false>()'}} \ - // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'uninit()'}} - constexpr int OverFlow() { // ref-error {{never produces a constant expression}} \ - // expected-error {{never produces a constant expression}} + constexpr int OverFlow() { // both-error {{never produces a constant expression}} int a = INT_MAX; - ++a; // ref-note 2{{is outside the range}} \ - // expected-note 2{{is outside the range}} + ++a; // both-note 2{{is outside the range}} return -1; } - static_assert(OverFlow() == -1, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'OverFlow()'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'OverFlow()'}} - + static_assert(OverFlow() == -1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'OverFlow()'}} - constexpr int UnderFlow() { // ref-error {{never produces a constant expression}} \ - // expected-error {{never produces a constant expression}} + constexpr int UnderFlow() { // both-error {{never produces a constant expression}} int a = INT_MIN; - --a; // ref-note 2{{is outside the range}} \ - // expected-note 2{{is outside the range}} + --a; // both-note 2{{is outside the range}} return -1; } - static_assert(UnderFlow() == -1, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'UnderFlow()'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'UnderFlow()'}} + static_assert(UnderFlow() == -1, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'UnderFlow()'}} constexpr int getTwo() { int i = 1; @@ -691,26 +619,20 @@ namespace IncDec { static_assert(sub(7) == 5, ""); constexpr int add(int a, int b) { - a += b; // expected-note {{is outside the range of representable values}} \ - // ref-note {{is outside the range of representable values}} + a += b; // both-note {{is outside the range of representable values}} return a; } static_assert(add(1, 2) == 3, ""); - static_assert(add(INT_MAX, 1) == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'add}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'add}} + static_assert(add(INT_MAX, 1) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'add}} constexpr int sub(int a, int b) { - a -= b; // expected-note {{is outside the range of representable values}} \ - // ref-note {{is outside the range of representable values}} + a -= b; // both-note {{is outside the range of representable values}} return a; } static_assert(sub(10, 20) == -10, ""); - static_assert(sub(INT_MIN, 1) == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'sub}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'sub}} + static_assert(sub(INT_MIN, 1) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'sub}} constexpr int subAll(int a) { return (a -= a); @@ -792,26 +714,18 @@ namespace IncDec { constexpr int IntRem(int a, int b) { int r; r = a; - r %= b; // expected-note {{division by zero}} \ - // ref-note {{division by zero}} \ - // expected-note {{outside the range of representable values}} \ - // ref-note {{outside the range of representable values}} + r %= b; // both-note {{division by zero}} \ + // both-note {{outside the range of representable values}} return r; } static_assert(IntRem(2, 2) == 0, ""); static_assert(IntRem(2, 1) == 0, ""); static_assert(IntRem(9, 7) == 2, ""); - static_assert(IntRem(5, 0) == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'IntRem(5, 0)'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'IntRem(5, 0)'}} - - static_assert(IntRem(INT_MIN, -1) == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'IntRem}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'IntRem}} - + static_assert(IntRem(5, 0) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'IntRem(5, 0)'}} + static_assert(IntRem(INT_MIN, -1) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'IntRem}} constexpr bool BoolDiv(bool b1, bool b2) { bool a; @@ -825,25 +739,19 @@ namespace IncDec { constexpr int IntDiv(int a, int b) { int r; r = a; - r /= b; // expected-note {{division by zero}} \ - // ref-note {{division by zero}} \ - // expected-note {{outside the range of representable values}} \ - // ref-note {{outside the range of representable values}} + r /= b; // both-note {{division by zero}} \ + // both-note {{outside the range of representable values}} return r; } static_assert(IntDiv(2, 2) == 1, ""); static_assert(IntDiv(12, 20) == 0, ""); static_assert(IntDiv(2, 1) == 2, ""); static_assert(IntDiv(9, 7) == 1, ""); - static_assert(IntDiv(5, 0) == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'IntDiv(5, 0)'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'IntDiv(5, 0)'}} + static_assert(IntDiv(5, 0) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'IntDiv(5, 0)'}} - static_assert(IntDiv(INT_MIN, -1) == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'IntDiv}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'IntDiv}} + static_assert(IntDiv(INT_MIN, -1) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'IntDiv}} constexpr bool BoolMul(bool b1, bool b2) { bool a; @@ -859,18 +767,15 @@ namespace IncDec { constexpr int IntMul(int a, int b) { int r; r = a; - r *= b; // expected-note {{is outside the range of representable values of type 'int'}} \ - // ref-note {{is outside the range of representable values of type 'int'}} + r *= b; // both-note {{is outside the range of representable values of type 'int'}} return r; } static_assert(IntMul(2, 2) == 4, ""); static_assert(IntMul(12, 20) == 240, ""); static_assert(IntMul(2, 1) == 2, ""); static_assert(IntMul(9, 7) == 63, ""); - static_assert(IntMul(INT_MAX, 2) == 0, ""); // expected-error {{not an integral constant expression}} \ - // expected-note {{in call to 'IntMul}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'IntMul}} + static_assert(IntMul(INT_MAX, 2) == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to 'IntMul}} constexpr int arr[] = {1,2,3}; constexpr int ptrInc1() { const int *p = arr; @@ -885,11 +790,9 @@ namespace IncDec { } static_assert(ptrInc2() == 2, ""); - constexpr int ptrInc3() { // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} + constexpr int ptrInc3() { // both-error {{never produces a constant expression}} const int *p = arr; - p += 12; // expected-note {{cannot refer to element 12 of array of 3 elements}} \ - // ref-note {{cannot refer to element 12 of array of 3 elements}} + p += 12; // both-note {{cannot refer to element 12 of array of 3 elements}} return *p; } @@ -901,11 +804,9 @@ namespace IncDec { } static_assert(ptrIncDec1() == 2, ""); - constexpr int ptrDec1() { // expected-error {{never produces a constant expression}} \ - // ref-error {{never produces a constant expression}} + constexpr int ptrDec1() { // both-error {{never produces a constant expression}} const int *p = arr; - p -= 1; // expected-note {{cannot refer to element -1 of array of 3 elements}} \ - // ref-note {{cannot refer to element -1 of array of 3 elements}} + p -= 1; // both-note {{cannot refer to element -1 of array of 3 elements}} return *p; } @@ -1133,10 +1034,8 @@ namespace PredefinedExprs { } constexpr char heh(unsigned index) { - __FUNCTION__; // ref-warning {{result unused}} \ - // expected-warning {{result unused}} - __extension__ __FUNCTION__; // ref-warning {{result unused}} \ - // expected-warning {{result unused}} + __FUNCTION__; // both-warning {{result unused}} + __extension__ __FUNCTION__; // both-warning {{result unused}} return __FUNCTION__[index]; } static_assert(heh(0) == 'h', ""); @@ -1158,8 +1057,7 @@ namespace NE { #if __cplusplus > 201402L constexpr int a() { int b = 0; - (void)noexcept(++b); // expected-warning {{expression with side effects has no effect in an unevaluated context}} \ - // ref-warning {{expression with side effects has no effect in an unevaluated context}} + (void)noexcept(++b); // both-warning {{expression with side effects has no effect in an unevaluated context}} return b; } @@ -1170,60 +1068,38 @@ namespace NE { namespace PointerCasts { constexpr int M = 10; constexpr const int *P = &M; - constexpr intptr_t A = (intptr_t)P; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{cast that performs the conversions of a reinterpret_cast}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{cast that performs the conversions of a reinterpret_cast}} + constexpr intptr_t A = (intptr_t)P; // both-error {{must be initialized by a constant expression}} \ + // both-note {{cast that performs the conversions of a reinterpret_cast}} - int array[(intptr_t)(char*)0]; // ref-warning {{variable length array folded to constant array}} \ - // expected-warning {{variable length array folded to constant array}} + int array[(intptr_t)(char*)0]; // both-warning {{variable length array folded to constant array}} } namespace InvalidDeclRefs { - bool b00; // ref-note {{declared here}} \ - // expected-note {{declared here}} - static_assert(b00, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{read of non-const variable}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{read of non-const variable}} - - float b01; // ref-note {{declared here}} \ - // expected-note {{declared here}} - static_assert(b01, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{read of non-constexpr variable}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{read of non-constexpr variable}} - - extern const int b02; // ref-note {{declared here}} \ - // expected-note {{declared here}} - static_assert(b02, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{initializer of 'b02' is unknown}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{initializer of 'b02' is unknown}} - - int b03 = 3; // ref-note {{declared here}} \ - // expected-note {{declared here}} - static_assert(b03, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{read of non-const variable}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{read of non-const variable}} + bool b00; // both-note {{declared here}} + static_assert(b00, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of non-const variable}} + + float b01; // both-note {{declared here}} + static_assert(b01, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of non-constexpr variable}} + + extern const int b02; // both-note {{declared here}} + static_assert(b02, ""); // both-error {{not an integral constant expression}} \ + // both-note {{initializer of 'b02' is unknown}} + + int b03 = 3; // both-note {{declared here}} + static_assert(b03, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of non-const variable}} } namespace NonConstReads { - void *p = nullptr; // ref-note {{declared here}} \ - // expected-note {{declared here}} - static_assert(!p, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{read of non-constexpr variable 'p'}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{read of non-constexpr variable 'p'}} - - int arr[!p]; // ref-error {{variable length array}} \ - // expected-error {{variable length array}} - - int z; // ref-note {{declared here}} \ - // expected-note {{declared here}} - static_assert(z == 0, ""); // ref-error {{not an integral constant expression}} \ - // ref-note {{read of non-const variable 'z'}} \ - // expected-error {{not an integral constant expression}} \ - // expected-note {{read of non-const variable 'z'}} + void *p = nullptr; // both-note {{declared here}} + static_assert(!p, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of non-constexpr variable 'p'}} + + int arr[!p]; // both-error {{variable length array}} + + int z; // both-note {{declared here}} + static_assert(z == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{read of non-const variable 'z'}} } >From bb4ec70f3c28a627c2cfed9dc8779a5237f037c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Thu, 25 Jan 2024 15:20:52 +0100 Subject: [PATCH 2/2] [clang][Interp] Handle complex values in visitBool() In C++, we get a ComplexToBool cast, but we might not in C. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 115 +++++++++++++---------- clang/lib/AST/Interp/ByteCodeExprGen.h | 1 + clang/test/AST/Interp/c.c | 4 + clang/test/AST/Interp/complex.cpp | 2 + 4 files changed, 72 insertions(+), 50 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 10e32d9b7bcf3..e6775d5a59ee5 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -239,57 +239,11 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { case CK_IntegralComplexToBoolean: case CK_FloatingComplexToBoolean: { - PrimType ElemT = classifyComplexElementType(SubExpr->getType()); - // We emit the expression (__real(E) != 0 || __imag(E) != 0) - // for us, that means (bool)E[0] || (bool)E[1] + if (DiscardResult) + return this->discard(SubExpr); if (!this->visit(SubExpr)) return false; - if (!this->emitConstUint8(0, CE)) - return false; - if (!this->emitArrayElemPtrUint8(CE)) - return false; - if (!this->emitLoadPop(ElemT, CE)) - return false; - if (ElemT == PT_Float) { - if (!this->emitCastFloatingIntegral(PT_Bool, CE)) - return false; - } else { - if (!this->emitCast(ElemT, PT_Bool, CE)) - return false; - } - - // We now have the bool value of E[0] on the stack. - LabelTy LabelTrue = this->getLabel(); - if (!this->jumpTrue(LabelTrue)) - return false; - - if (!this->emitConstUint8(1, CE)) - return false; - if (!this->emitArrayElemPtrPopUint8(CE)) - return false; - if (!this->emitLoadPop(ElemT, CE)) - return false; - if (ElemT == PT_Float) { - if (!this->emitCastFloatingIntegral(PT_Bool, CE)) - return false; - } else { - if (!this->emitCast(ElemT, PT_Bool, CE)) - return false; - } - // Leave the boolean value of E[1] on the stack. - LabelTy EndLabel = this->getLabel(); - this->jump(EndLabel); - - this->emitLabel(LabelTrue); - if (!this->emitPopPtr(CE)) - return false; - if (!this->emitConstBool(true, CE)) - return false; - - this->fallthrough(EndLabel); - this->emitLabel(EndLabel); - - return true; + return this->emitComplexBoolCast(SubExpr); } case CK_IntegralComplexToReal: @@ -2055,8 +2009,15 @@ bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) { template <class Emitter> bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) { std::optional<PrimType> T = classify(E->getType()); - if (!T) + if (!T) { + // Convert complex values to bool. + if (E->getType()->isAnyComplexType()) { + if (!this->visit(E)) + return false; + return this->emitComplexBoolCast(E); + } return false; + } if (!this->visit(E)) return false; @@ -3150,6 +3111,60 @@ bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) { return true; } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::emitComplexBoolCast(const Expr *E) { + assert(!DiscardResult); + PrimType ElemT = classifyComplexElementType(E->getType()); + // We emit the expression (__real(E) != 0 || __imag(E) != 0) + // for us, that means (bool)E[0] || (bool)E[1] + if (!this->emitConstUint8(0, E)) + return false; + if (!this->emitArrayElemPtrUint8(E)) + return false; + if (!this->emitLoadPop(ElemT, E)) + return false; + if (ElemT == PT_Float) { + if (!this->emitCastFloatingIntegral(PT_Bool, E)) + return false; + } else { + if (!this->emitCast(ElemT, PT_Bool, E)) + return false; + } + + // We now have the bool value of E[0] on the stack. + LabelTy LabelTrue = this->getLabel(); + if (!this->jumpTrue(LabelTrue)) + return false; + + if (!this->emitConstUint8(1, E)) + return false; + if (!this->emitArrayElemPtrPopUint8(E)) + return false; + if (!this->emitLoadPop(ElemT, E)) + return false; + if (ElemT == PT_Float) { + if (!this->emitCastFloatingIntegral(PT_Bool, E)) + return false; + } else { + if (!this->emitCast(ElemT, PT_Bool, E)) + return false; + } + // Leave the boolean value of E[1] on the stack. + LabelTy EndLabel = this->getLabel(); + this->jump(EndLabel); + + this->emitLabel(LabelTrue); + if (!this->emitPopPtr(E)) + return false; + if (!this->emitConstBool(true, E)) + return false; + + this->fallthrough(EndLabel); + this->emitLabel(EndLabel); + + return true; +} + /// When calling this, we have a pointer of the local-to-destroy /// on the stack. /// Emit destruction of record types (or arrays of record types). diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 2c9cca5082b12..cb3aed35b5823 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -283,6 +283,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, } bool emitComplexReal(const Expr *SubExpr); + bool emitComplexBoolCast(const Expr *E); bool emitRecordDestruction(const Descriptor *Desc); unsigned collectBaseOffset(const RecordType *BaseType, diff --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c index 9ab271a82aeef..cc074d800eed0 100644 --- a/clang/test/AST/Interp/c.c +++ b/clang/test/AST/Interp/c.c @@ -129,3 +129,7 @@ _Static_assert(sizeof(name2) == 0, ""); // expected-error {{failed}} \ // expected-note {{evaluates to}} \ // pedantic-expected-error {{failed}} \ // pedantic-expected-note {{evaluates to}} + +const int A = ((_Complex double)1.0 ? 21 : 1); +_Static_assert(A == 21, ""); // pedantic-ref-warning {{GNU extension}} \ + // pedantic-expected-warning {{GNU extension}} diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp index 7f02bfa18bbdb..875c9f23d5a38 100644 --- a/clang/test/AST/Interp/complex.cpp +++ b/clang/test/AST/Interp/complex.cpp @@ -77,6 +77,8 @@ constexpr int ignored() { (int)D1; (double)D1; (_Complex float)I2; + (bool)D1; + (bool)I2; return 0; } static_assert(ignored() == 0, ""); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits