diff options
Diffstat (limited to 'clang/test/AST/ByteCode')
-rw-r--r-- | clang/test/AST/ByteCode/builtin-bit-cast.cpp | 4 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/codegen.cpp | 4 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/complex.cpp | 5 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/const-eval.c | 5 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/cxx11.cpp | 5 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/functions.cpp | 24 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/intap.cpp | 14 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/records.cpp | 6 | ||||
-rw-r--r-- | clang/test/AST/ByteCode/unions.cpp | 72 |
9 files changed, 118 insertions, 21 deletions
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp index 3c5e89d7..bc356b0 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp @@ -22,6 +22,10 @@ typedef __INTPTR_TYPE__ intptr_t; static_assert(sizeof(int) == 4); static_assert(sizeof(long long) == 8); + +constexpr bool test_bad_bool = __builtin_bit_cast(bool, (char)0xff); // both-error {{must be initialized by a constant expression}} \ + // both-note {{value 255 cannot be represented in type 'bool'}} + template <class To, class From> constexpr To bit_cast(const From &from) { static_assert(sizeof(To) == sizeof(From)); diff --git a/clang/test/AST/ByteCode/codegen.cpp b/clang/test/AST/ByteCode/codegen.cpp index 6f9e75e..1bc756c 100644 --- a/clang/test/AST/ByteCode/codegen.cpp +++ b/clang/test/AST/ByteCode/codegen.cpp @@ -23,6 +23,10 @@ S s; // CHECK: @sp = constant ptr getelementptr (i8, ptr @s, i64 16), align 8 float &sp = s.c[3]; +namespace NearlyZeroInit { + // CHECK: @_ZN14NearlyZeroInit1bE ={{.*}} global{{.*}} { i32, <{ i32, [2147483647 x i32] }> } { i32 1, <{ i32, [2147483647 x i32] }> <{ i32 2, [2147483647 x i32] zeroinitializer }> }{{.*}} + struct B { int n; int arr[1024 * 1024 * 1024 * 2u]; } b = {1, {2}}; +} namespace BaseClassOffsets { struct A { int a; }; diff --git a/clang/test/AST/ByteCode/complex.cpp b/clang/test/AST/ByteCode/complex.cpp index 959d759..be10b3c 100644 --- a/clang/test/AST/ByteCode/complex.cpp +++ b/clang/test/AST/ByteCode/complex.cpp @@ -396,10 +396,9 @@ namespace ComplexConstexpr { // both-note {{cannot refer to element 3 of array of 2 elements}} constexpr _Complex float *p = 0; constexpr float pr = __real *p; // both-error {{constant expr}} \ - // expected-note {{read of dereferenced null pointer}} \ - // ref-note {{dereferencing a null pointer}} + // both-note {{dereferencing a null pointer}} constexpr float pi = __imag *p; // both-error {{constant expr}} \ - // ref-note {{dereferencing a null pointer}} + // both-note {{dereferencing a null pointer}} constexpr const _Complex double *q = &test3 + 1; constexpr double qr = __real *q; // ref-error {{constant expr}} \ // ref-note {{cannot access real component of pointer past the end}} diff --git a/clang/test/AST/ByteCode/const-eval.c b/clang/test/AST/ByteCode/const-eval.c index c8651a7..3e22822 100644 --- a/clang/test/AST/ByteCode/const-eval.c +++ b/clang/test/AST/ByteCode/const-eval.c @@ -51,8 +51,6 @@ struct s { }; EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1)); -// ref-error@-1 {{expression is not an integer constant expression}} \ -// ref-note@-1 {{dereferencing a null pointer}} #ifndef NEW_INTERP EVAL_EXPR(20, __builtin_constant_p(*((int*) 10))); @@ -182,6 +180,9 @@ typedef __INTPTR_TYPE__ intptr_t; const intptr_t A = (intptr_t)(((int*) 0) + 1); const intptr_t B = (intptr_t)(((char*)0) + 3); _Static_assert(A > B, ""); +int * GH149500_p = &(*(int *)0x400); +static const void *GH149500_q = &(*(const struct sysrq_key_op *)0); + #else #error :( #endif diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp index 5555422..378702f 100644 --- a/clang/test/AST/ByteCode/cxx11.cpp +++ b/clang/test/AST/ByteCode/cxx11.cpp @@ -39,9 +39,8 @@ struct S { constexpr S s = { 5 }; constexpr const int *p = &s.m + 1; -constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; -// ref-error@-1 {{constexpr variable 'np2' must be initialized by a constant expression}} \ -// ref-note@-1 {{dereferencing a null pointer is not allowed in a constant expression}} +constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // both-error {{constexpr variable 'np2' must be initialized by a constant expression}} \ + // both-note {{dereferencing a null pointer is not allowed in a constant expression}} constexpr int preDec(int x) { // both-error {{never produces a constant expression}} return --x; // both-note {{subexpression}} diff --git a/clang/test/AST/ByteCode/functions.cpp b/clang/test/AST/ByteCode/functions.cpp index b5e6f5b..363b6a5 100644 --- a/clang/test/AST/ByteCode/functions.cpp +++ b/clang/test/AST/ByteCode/functions.cpp @@ -5,6 +5,8 @@ // RUN: %clang_cc1 -pedantic -std=c++14 -verify=ref,both %s // RUN: %clang_cc1 -pedantic -std=c++20 -verify=ref,both %s +#define fold(x) (__builtin_constant_p(0) ? (x) : (x)) + constexpr void doNothing() {} constexpr int gimme5() { doNothing(); @@ -654,14 +656,26 @@ namespace { } namespace FunctionCast { - // When folding, we allow functions to be cast to different types. Such - // cast functions cannot be called, even if they're constexpr. + // When folding, we allow functions to be cast to different types. We only + // allow calls if the dynamic type of the pointer matches the type of the + // call. constexpr int f() { return 1; } + constexpr void* f2() { return nullptr; } + constexpr int f3(int a) { return a; } typedef double (*DoubleFn)(); typedef int (*IntFn)(); - int a[(int)DoubleFn(f)()]; // both-error {{variable length array}} \ - // both-warning {{are a Clang extension}} - int b[(int)IntFn(f)()]; // ok + typedef int* (*IntPtrFn)(); + constexpr int test1 = (int)DoubleFn(f)(); // both-error {{constant expression}} both-note {{reinterpret_cast}} + // FIXME: We should print a note explaining the error. + constexpr int test2 = (int)fold(DoubleFn(f))(); // both-error {{constant expression}} + constexpr int test3 = (int)IntFn(f)(); // no-op cast + constexpr int test4 = fold(IntFn(DoubleFn(f)))(); + constexpr int test5 = IntFn(fold(DoubleFn(f)))(); // both-error {{constant expression}} \ + // both-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + // FIXME: Interpreter is less strict here. + constexpr int test6 = fold(IntPtrFn(f2))() == nullptr; // ref-error {{constant expression}} + // FIXME: The following crashes interpreter + // constexpr int test6 = fold(IntFn(f3)()); } #if __cplusplus >= 202002L diff --git a/clang/test/AST/ByteCode/intap.cpp b/clang/test/AST/ByteCode/intap.cpp index 6888387..05ab319b 100644 --- a/clang/test/AST/ByteCode/intap.cpp +++ b/clang/test/AST/ByteCode/intap.cpp @@ -292,7 +292,19 @@ constexpr int shifts() { // both-error {{never produces a constant expression}} (void)(2 << b); // ref-warning {{shift count is negative}} return 1; } -#endif +namespace UnderlyingInt128 { + enum F { + a = (__int128)-1 + }; + + constexpr int foo() { // both-error {{never produces a constant expression}} + F f = (F)(__int128)10; // both-note 2{{integer value 10 is outside the valid range of values [-1, 0] for the enumeration type 'F'}} + return (int)f; + } + static_assert(foo() == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} +} +#endif #endif diff --git a/clang/test/AST/ByteCode/records.cpp b/clang/test/AST/ByteCode/records.cpp index 774fed6..5ca3e2d 100644 --- a/clang/test/AST/ByteCode/records.cpp +++ b/clang/test/AST/ByteCode/records.cpp @@ -1660,11 +1660,9 @@ namespace NullptrCast { constexpr A *na = nullptr; constexpr B *nb = nullptr; constexpr A &ra = *nb; // both-error {{constant expression}} \ - // ref-note {{dereferencing a null pointer}} \ - // expected-note {{cannot access base class of null pointer}} + // both-note {{dereferencing a null pointer}} constexpr B &rb = (B&)*na; // both-error {{constant expression}} \ - // ref-note {{dereferencing a null pointer}} \ - // expected-note {{cannot access derived class of null pointer}} + // both-note {{dereferencing a null pointer}} constexpr bool test() { auto a = (A*)(B*)nullptr; diff --git a/clang/test/AST/ByteCode/unions.cpp b/clang/test/AST/ByteCode/unions.cpp index 7cfd0d6..139e318 100644 --- a/clang/test/AST/ByteCode/unions.cpp +++ b/clang/test/AST/ByteCode/unions.cpp @@ -79,10 +79,9 @@ namespace DefaultInit { constexpr U1 u1; /// OK. - constexpr int foo() { // expected-error {{never produces a constant expression}} + constexpr int foo() { U1 u; - return u.a; // both-note {{read of member 'a' of union with active member 'b'}} \ - // expected-note {{read of member 'a' of union with active member 'b'}} + return u.a; // both-note {{read of member 'a' of union with active member 'b'}} } static_assert(foo() == 42); // both-error {{not an integral constant expression}} \ // both-note {{in call to}} @@ -861,6 +860,73 @@ namespace CopyCtorMutable { // both-note {{in call}} } + +namespace NonTrivialCtor { + struct A { int x = 1; constexpr int f() { return 1; } }; + struct B : A { int y = 1; constexpr int g() { return 2; } }; + struct C { + int x; + constexpr virtual int f() = 0; + }; + struct D : C { + int y; + constexpr virtual int f() override { return 3; } + }; + + union U { + int n; + B b; + D d; + }; + + consteval int test(int which) { + if (which == 0) {} + + U u{.n = 5}; + assert_active(u); + assert_active(u.n); + assert_inactive(u.b); + + switch (which) { + case 0: + u.b.x = 10; // both-note {{assignment to member 'b' of union with active member 'n'}} + return u.b.f(); + case 1: + u.b.y = 10; // both-note {{assignment to member 'b' of union with active member 'n'}} + return u.b.g(); + case 2: + u.d.x = 10; // both-note {{assignment to member 'd' of union with active member 'n'}} + return u.d.f(); + case 3: + u.d.y = 10; // both-note {{assignment to member 'd' of union with active member 'n'}} + return u.d.f(); + } + + return 1; + } + static_assert(test(0)); // both-error {{not an integral constant expression}} \ + // both-note {{in call}} + static_assert(test(1)); // both-error {{not an integral constant expression}} \ + // both-note {{in call}} + static_assert(test(2)); // both-error {{not an integral constant expression}} \ + // both-note {{in call}} + static_assert(test(3)); // both-error {{not an integral constant expression}} \ + // both-note {{in call}} + +} + +namespace PrimitiveFieldInitActivates { + /// The initializer of a needs the field to be active _before_ it's visited. + template<int> struct X {}; + union V { + int a, b; + constexpr V(X<0>) : a(a = 1) {} // ok + constexpr V(X<2>) : a() { b = 1; } // ok + }; + constinit V v0 = X<0>(); + constinit V v2 = X<2>(); +} + #endif namespace AddressComparison { |