aboutsummaryrefslogtreecommitdiff
path: root/clang/test/AST/ByteCode
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/AST/ByteCode')
-rw-r--r--clang/test/AST/ByteCode/arrays.cpp4
-rw-r--r--clang/test/AST/ByteCode/builtin-functions.cpp40
-rw-r--r--clang/test/AST/ByteCode/c.c18
-rw-r--r--clang/test/AST/ByteCode/cxx11.cpp42
-rw-r--r--clang/test/AST/ByteCode/cxx14.cpp21
-rw-r--r--clang/test/AST/ByteCode/cxx20.cpp24
-rw-r--r--clang/test/AST/ByteCode/cxx23.cpp47
-rw-r--r--clang/test/AST/ByteCode/intap.cpp40
-rw-r--r--clang/test/AST/ByteCode/invalid.cpp61
-rw-r--r--clang/test/AST/ByteCode/literals.cpp11
-rw-r--r--clang/test/AST/ByteCode/new-delete.cpp22
-rw-r--r--clang/test/AST/ByteCode/records.cpp11
-rw-r--r--clang/test/AST/ByteCode/switch.cpp103
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}}
+}