diff options
Diffstat (limited to 'clang/test/AST/ByteCode')
| -rw-r--r-- | clang/test/AST/ByteCode/arrays.cpp | 4 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/builtin-functions.cpp | 40 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/c.c | 18 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/cxx11.cpp | 42 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/cxx14.cpp | 21 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/cxx20.cpp | 24 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/cxx23.cpp | 47 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/intap.cpp | 40 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/invalid.cpp | 61 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/literals.cpp | 11 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/new-delete.cpp | 22 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/records.cpp | 11 | ||||
| -rw-r--r-- | clang/test/AST/ByteCode/switch.cpp | 103 |
13 files changed, 441 insertions, 3 deletions
diff --git a/clang/test/AST/ByteCode/arrays.cpp b/clang/test/AST/ByteCode/arrays.cpp index eaf9559..d83ae97 100644 --- a/clang/test/AST/ByteCode/arrays.cpp +++ b/clang/test/AST/ByteCode/arrays.cpp @@ -731,6 +731,10 @@ namespace ZeroSizeTypes { // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \ // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}} + constexpr int k2 = p1 - p1; // both-error {{constexpr variable 'k2' must be initialized by a constant expression}} \ + // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \ + // both-warning {{subtraction of pointers to type 'int[0]' of zero size has undefined behavior}} + int arr[5][0]; constexpr int f() { // both-error {{never produces a constant expression}} return &arr[3] - &arr[0]; // both-note {{subtraction of pointers to type 'int[0]' of zero size}} \ diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index a90f636..3076b52 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -837,6 +837,39 @@ namespace bswap { int h3 = __builtin_bswap16(0x1234) == 0x3412 ? 1 : f(); int h4 = __builtin_bswap32(0x1234) == 0x34120000 ? 1 : f(); int h5 = __builtin_bswap64(0x1234) == 0x3412000000000000 ? 1 : f(); + int h6 = __builtin_bswapg(0x12) == 0x12 ? 1 : f(); + int h7 = __builtin_bswapg(0x1234) == 0x3412 ? 1 : f(); + int h8 = __builtin_bswapg(0x00001234) == 0x34120000 ? 1 : f(); + int h9 = __builtin_bswapg(0x0000000000001234) == 0x3412000000000000 ? 1 : f(); +#ifndef __AVR__ + int h10 = __builtin_bswapg((_BitInt(8))0x12) == (_BitInt(8))0x12 ? 1 : f(); + int h11 = __builtin_bswapg((_BitInt(16))0x1234) == (_BitInt(16))0x3412 ? 1 : f(); + int h12 = __builtin_bswapg((_BitInt(32))0x00001234) == (_BitInt(32))0x34120000 ? 1 : f(); + int h13 = __builtin_bswapg((_BitInt(64))0x0000000000001234) == (_BitInt(64))0x3412000000000000 ? 1 : f(); + int h14 = __builtin_bswapg(~(_BitInt(128))0) == (~(_BitInt(128))0) ? 1 : f(); + int h15 = __builtin_bswapg((_BitInt(24))0x1234) == (_BitInt(24))0x3412 ? 1 : f(); + // expected-error@-1 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}} + // ref-error@-2 {{_BitInt type '_BitInt(24)' (24 bits) must be a multiple of 16 bits for byte swapping}} +#endif + + constexpr const int const_expr = 0x1234; + + void test_constexpr_reference() { + const int expr = 0x1234; + const int& ref = expr; // #declare + + constexpr const int& const_ref = const_expr; + + constexpr auto result2 = __builtin_bswapg(ref); + //expected-error@-1 {{constexpr variable 'result2' must be initialized by a constant expression}} + //expected-note@-2 {{initializer of 'ref' is not a constant expression}} + //expected-note@#declare {{declared here}} + //ref-error@-4 {{constexpr variable 'result2' must be initialized by a constant expression}} + //ref-note@-5 {{initializer of 'ref' is not a constant expression}} + //ref-note@#declare {{declared here}} + + constexpr auto result3 = __builtin_bswapg(const_ref); + } } #define CFSTR __builtin___CFStringMakeConstantString @@ -1512,6 +1545,13 @@ namespace Memcmp { int unknown; void foo(void) { unknown *= __builtin_memcmp(0, 0, 2); } + + constexpr int onepasttheend(char a) { + __builtin_memcmp(&a, &a + 1, 1); // both-note {{read of dereferenced one-past-the-end pointer}} + return 1; + } + static_assert(onepasttheend(10)); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} } namespace Memchr { diff --git a/clang/test/AST/ByteCode/c.c b/clang/test/AST/ByteCode/c.c index 3360d4f..0d3d97b 100644 --- a/clang/test/AST/ByteCode/c.c +++ b/clang/test/AST/ByteCode/c.c @@ -387,3 +387,21 @@ void bar2(void) { int a[2][3][4][5]; // all-note {{array 'a' declared here}} foo2(&a[0][4]); // all-warning {{array index 4 is past the end of the array}} } + +void plainComplex(void) { + _Complex cd; // all-warning {{_Complex double}} + cd = *(_Complex *)&(struct { double r, i; }){0.0, 0.0}; // all-warning {{_Complex double}} +} + +/// This test results in an ImplicitValueInitExpr with DiscardResult set. +struct M{ + char c; +}; +typedef struct S64 { + struct M m; + char a[64]; +} I64; + +_Static_assert((((I64){}, 1)), ""); // all-warning {{left operand of comma operator has no effect}} \ + // pedantic-warning {{use of an empty initializer is a C23 extension}} \ + // pedantic-warning {{expression is not an integer constant expression; folding it to a constant is a GNU extension}} diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp index 427d3a1..9a61321 100644 --- a/clang/test/AST/ByteCode/cxx11.cpp +++ b/clang/test/AST/ByteCode/cxx11.cpp @@ -374,8 +374,48 @@ namespace GH150709 { namespace DiscardedAddrLabel { void foo(void) { L: - *&&L; // both-error {{indirection not permitted}} \ + *&&L; // both-error {{indirection not permitted on operand of type 'void *'}} \ // both-warning {{expression result unused}} } } +struct Counter { + int copies; + constexpr Counter(int copies) : copies(copies) {} + constexpr Counter(const Counter& other) : copies(other.copies + 1) {} +}; +// Passing an lvalue by value makes a non-elidable copy. +constexpr int PassByValue(Counter c) { return c.copies; } +static_assert(PassByValue(Counter(0)) == 0, "expect no copies"); + +namespace PointerCast { + /// The two interpreters disagree here. + struct S { int x, y; } s; + constexpr S* sptr = &s; + struct U {}; + struct Str { + int e : (Str*)(sptr) == (Str*)(sptr); // expected-error {{not an integral constant expression}} \ + // expected-note {{cast that performs the conversions of a reinterpret_cast}} + }; +} + +namespace DummyToGlobalBlockMove { + struct Baz { + unsigned int n; + }; + + struct AP { + const AP *p; + const Baz *lp; + }; + + class Bar { + public: + static Baz _m[]; + static const AP m; + }; + + const AP Bar::m = {0, &Bar::_m[0]}; + Baz Bar::_m[] = {{0}}; + const AP m = {&Bar ::m}; +} diff --git a/clang/test/AST/ByteCode/cxx14.cpp b/clang/test/AST/ByteCode/cxx14.cpp index 9622311..57cb42e 100644 --- a/clang/test/AST/ByteCode/cxx14.cpp +++ b/clang/test/AST/ByteCode/cxx14.cpp @@ -7,3 +7,24 @@ constexpr int(*null_ptr)() = nullptr; constexpr int test4 = (*null_ptr)(); // both-error {{must be initialized by a constant expression}} \ // both-note {{evaluates to a null function pointer}} +struct E { + int n = 0; + struct { + void *x = this; + }; + void *y = this; +}; +constexpr E e1 = E(); +static_assert(e1.x != e1.y, ""); +constexpr E e2 = E{0}; +static_assert(e2.x != e2.y, ""); + +struct S { + int &&a = 2; + int b[1]{a}; +}; +constexpr int foo() { + S s{12}; + return s.b[0]; +} +static_assert(foo() == 12, ""); diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp index cb788fa..227f34c 100644 --- a/clang/test/AST/ByteCode/cxx20.cpp +++ b/clang/test/AST/ByteCode/cxx20.cpp @@ -1201,3 +1201,27 @@ namespace NonPureVirtualCall { int main() { check(); } } + +namespace DyamicCast { + struct X { + virtual constexpr ~X() {} + }; + struct Y : X {}; + constexpr Y y; + constexpr const X *p = &y; + constexpr const Y *q = dynamic_cast<const Y*>(p); +} + +namespace ConditionalTemporaries { + class F { + public: + constexpr F(int a ) {this->a = a;} + constexpr ~F() {} + int a; + }; + constexpr int foo(bool b) { + return b ? F{12}.a : F{13}.a; + } + static_assert(foo(false)== 13); + static_assert(foo(true)== 12); +} diff --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp index ce0a4777..8194606 100644 --- a/clang/test/AST/ByteCode/cxx23.cpp +++ b/clang/test/AST/ByteCode/cxx23.cpp @@ -449,3 +449,50 @@ namespace VolatileWrites { static_assert(test7(12)); // all-error {{not an integral constant expression}} \ // all-note {{in call to}} } + +namespace AIEWithIndex0Narrows { + template <class _Tp> struct greater { + constexpr void operator()(_Tp, _Tp) {} + }; + struct S { + constexpr S() : i_() {} + int i_; + }; + + constexpr void sort(S *__first) { + for (int __start = 0; __start >= 0; --__start) { + greater<S>{}(__first[0], __first[0]); + } + } + constexpr bool test() { + S *ia = new S[2]; + + sort(ia + 1); + delete[] ia; + return true; + } + static_assert(test()); +} + +#if __cplusplus >= 202302L +namespace InactiveLocalsInConditionalOp { + struct A { constexpr A(){}; ~A(); constexpr int get() { return 10; } }; // all-note 2{{declared here}} + constexpr int get(bool b) { + return b ? A().get() : 1; // all-note {{non-constexpr function '~A' cannot be used in a constant expression}} + } + static_assert(get(false) == 1, ""); + static_assert(get(true) == 10, ""); // all-error {{not an integral constant expression}} \ + // all-note {{in call to}} + + static_assert( (false ? A().get() : 1) == 1); + static_assert( (true ? A().get() : 1) == 1); // all-error {{not an integral constant expression}} \ + // all-note {{non-constexpr function '~A' cannot be used in a constant expression}} + + constexpr bool test2(bool b) { + unsigned long __ms = b ? (const unsigned long &)0 : __ms; + return true; + } + static_assert(test2(true)); + +} +#endif diff --git a/clang/test/AST/ByteCode/intap.cpp b/clang/test/AST/ByteCode/intap.cpp index 05ab319b..efb60cb 100644 --- a/clang/test/AST/ByteCode/intap.cpp +++ b/clang/test/AST/ByteCode/intap.cpp @@ -305,6 +305,46 @@ namespace UnderlyingInt128 { static_assert(foo() == 0, ""); // both-error {{not an integral constant expression}} \ // both-note {{in call to}} } + +namespace CompoundAssignOperators { + constexpr unsigned __int128 foo() { + long b = 10; + + b += (__int128)1; + b -= (__int128)1; + b *= (__int128)1; + b /= (__int128)1; + + b += (unsigned __int128)1; + b -= (unsigned __int128)1; + b *= (unsigned __int128)1; + b /= (unsigned __int128)1; + + __int128 i = 10; + i += (__int128)1; + i -= (__int128)1; + i *= (__int128)1; + i /= (__int128)1; + i += (unsigned __int128)1; + i -= (unsigned __int128)1; + i *= (unsigned __int128)1; + i /= (unsigned __int128)1; + + unsigned __int128 i2 = 10; + i2 += (__int128)1; + i2 -= (__int128)1; + i2 *= (__int128)1; + i2 /= (__int128)1; + i2 += (unsigned __int128)1; + i2 -= (unsigned __int128)1; + i2 *= (unsigned __int128)1; + i2 /= (unsigned __int128)1; + + return (int)b; + } + static_assert(foo() == 10); +} + #endif #endif diff --git a/clang/test/AST/ByteCode/invalid.cpp b/clang/test/AST/ByteCode/invalid.cpp index 00db274..541aa63 100644 --- a/clang/test/AST/ByteCode/invalid.cpp +++ b/clang/test/AST/ByteCode/invalid.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s -// RUN: %clang_cc1 -fcxx-exceptions -std=c++20 -verify=ref,both %s +// RUN: %clang_cc1 -triple x86_64 -fcxx-exceptions -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -triple x86_64 -fcxx-exceptions -std=c++20 -verify=ref,both %s namespace Throw { @@ -66,3 +66,60 @@ struct S { S s; S *sp[2] = {&s, &s}; S *&spp = sp[1]; + +namespace InvalidBitCast { + void foo() { + const long long int i = 1; // both-note {{declared const here}} + if (*(double *)&i == 2) { + i = 0; // both-error {{cannot assign to variable}} + } + } + + struct S2 { + void *p; + }; + struct T { + S2 s; + }; + constexpr T t = {{nullptr}}; + constexpr void *foo2() { return ((void **)&t)[0]; } // both-error {{never produces a constant expression}} \ + // both-note 2{{cast that performs the conversions of a reinterpret_cast}} + constexpr auto x = foo2(); // both-error {{must be initialized by a constant expression}} \ + // both-note {{in call to}} + + + struct sockaddr + { + char sa_data[8]; + }; + struct in_addr + { + unsigned int s_addr; + }; + struct sockaddr_in + { + unsigned short int sin_port; + struct in_addr sin_addr; + }; + /// Bitcast from sockaddr to sockaddr_in. Used to crash. + unsigned int get_addr(sockaddr addr) { + return ((sockaddr_in *)&addr)->sin_addr.s_addr; + } + + + struct s { int a; int b[1]; }; + struct s myx; + int *myy = ((struct s *)&myx.a)->b; +} + +namespace InvalidIntPtrRecord { + typedef __SIZE_TYPE__ Size_t; + +#define bufsize ((1LL << (8 * sizeof(Size_t) - 2)) - 256) + + struct S { + short buf[bufsize]; // both-error {{array is too large}} + int a; + }; + Size_t foo() { return (Size_t)(&((struct S *)0)->a); } +} diff --git a/clang/test/AST/ByteCode/literals.cpp b/clang/test/AST/ByteCode/literals.cpp index 5028ebf..c6d79f9 100644 --- a/clang/test/AST/ByteCode/literals.cpp +++ b/clang/test/AST/ByteCode/literals.cpp @@ -1270,6 +1270,17 @@ namespace StmtExprs { namespace CrossFuncLabelDiff { constexpr long a(bool x) { return x ? 0 : (intptr_t)&&lbl + (0 && ({lbl: 0;})); } } + + /// GCC agrees with the bytecode interpreter here. + void switchInSE() { + static_assert(({ // ref-error {{not an integral constant expression}} + int i = 20; + switch(10) { + case 10: i = 300; // ref-note {{a constant expression cannot modify an object that is visible outside that expression}} + } + i; + }) == 300); + } } #endif diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index f548540..43e1f6b 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -1104,6 +1104,28 @@ namespace HugeAllocation { } #endif +namespace ZeroSizeArray { + constexpr int foo() { + int *A = new int[0]; + int diff = A - (&A[0]); + delete[] A; + return diff; + } + static_assert(foo() == 0); +} + +namespace NonLiteralType { + /// This used to crash. + constexpr void foo() { + struct O {}; + + struct S { + O *s; + constexpr S() : s{std::allocator<O>{}.allocate(1)} {} + }; + } +} + #else /// Make sure we reject this prior to C++20 constexpr int a() { // both-error {{never produces a constant expression}} diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index 83f32c9..4799ebe 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -1882,3 +1882,14 @@ namespace MethodWillHaveBody { } int n = f(0); // both-note {{instantiation of}} } + +namespace StaticRedecl { + struct T { + static T tt; + constexpr T() : p(&tt) {} + T *p; + }; + T T::tt; + constexpr T t; + static_assert(t.p == &T::tt, ""); +} diff --git a/clang/test/AST/ByteCode/switch.cpp b/clang/test/AST/ByteCode/switch.cpp index 8136f92..151b4a5 100644 --- a/clang/test/AST/ByteCode/switch.cpp +++ b/clang/test/AST/ByteCode/switch.cpp @@ -86,3 +86,106 @@ constexpr int another_test(int val) { // both-note {{declared here}} } static_assert(another_test(1) == 100, ""); // both-error {{static assertion failed}} \ // both-note {{evaluates to}} + +namespace gnurange { + constexpr int l(int n) { + return n + 1; + } + constexpr int h(int n) { + return 2 * n + 1; + } + constexpr int f(int x) { + const int n = 2; + constexpr struct { + char lo {'a'}; + char hi {'z'}; + } s; + + switch (x) { + case l(n) ... h(n): + return 1; + case -1 ... 1: + return 2; + case 9 ... 14: + return 3; + case 15: + return 4; + case 16 ... 20: + return 5; + case s.lo ... s.hi: + return 6; + default: + return -1; + } + } + static_assert(f(0) == 2); + static_assert(f(2) == -1); + static_assert(f(3) == 1); + static_assert(f(4) == 1); + static_assert(f(5) == 1); + static_assert(f(6) == -1); + static_assert(f(14) == 3); + static_assert(f(15) == 4); + static_assert(f(16) == 5); + static_assert(f(20) == 5); + static_assert(f('d') == 6); + + template <int Lo, int Hi> + constexpr bool g(int x) { + switch (x) { + case Lo ... Hi: + break; + default: + return false; + } + return true; + } + static_assert(g<100, 200>(132)); + + constexpr bool m(int x) { + switch (x) { + case 10 ... 1: // both-warning {{empty case range specified}} + return true; + default: + return false; + } + } + static_assert(m(3)); // both-error {{static assertion failed due to requirement 'm(3)'}} + static_assert(!m(3)); + + constexpr bool j(int x) { // both-note {{declared here}} + switch (x) { + case bad(x) ... 100: // both-error {{case value is not a constant expression}} \ + // both-note {{cannot be used in a constant expression}} + return true; + default: + break; + } + return false; + } + static_assert(j(1)); // both-error {{static assertion failed}} + + constexpr bool d(int x) { // both-note {{declared here}} + switch (x) { + case -100 ... bad(x): // both-error {{case value is not a constant expression}} \ + // both-note {{cannot be used in a constant expression}} + return true; + default: + break; + } + return false; + } + static_assert(d(1)); // both-error {{static assertion failed}} + + constexpr bool s(int x) { // both-note {{declared here}} + switch (x) { + case bad(x) - 100 ... bad(x) + 100: // both-error {{case value is not a constant expression}} \ + // both-note {{cannot be used in a constant expression}} + return true; + default: + break; + } + return false; + } + static_assert(s(1)); // both-error {{static assertion failed}} +} |
