aboutsummaryrefslogtreecommitdiff
path: root/clang/test/AST
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/AST')
-rw-r--r--clang/test/AST/ByteCode/builtin-bit-cast.cpp4
-rw-r--r--clang/test/AST/ByteCode/functions.cpp24
-rw-r--r--clang/test/AST/ByteCode/intap.cpp14
-rw-r--r--clang/test/AST/ByteCode/unions.cpp72
-rw-r--r--clang/test/AST/ast-dump-APValue-lvalue.cpp8
5 files changed, 111 insertions, 11 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/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/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 {
diff --git a/clang/test/AST/ast-dump-APValue-lvalue.cpp b/clang/test/AST/ast-dump-APValue-lvalue.cpp
index 51d22a5..f4cf2f5 100644
--- a/clang/test/AST/ast-dump-APValue-lvalue.cpp
+++ b/clang/test/AST/ast-dump-APValue-lvalue.cpp
@@ -67,6 +67,10 @@ void Test(int (&arr)[10]) {
// CHECK-NEXT: | |-value: LValue Base=TypeInfoLValue typeid(int), Null=0, Offset=0, HasPath=1, PathLength=0, Path=()
constexpr int(MP::*pmi) = (int MP::*)&P::x;
- // CHECK: `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pmi 'int (MP::*const)' constexpr cinit
- // CHECK-NEXT: |-value: MemberPointer MP::x
+ // CHECK: | `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pmi 'int (MP::*const)' constexpr cinit
+ // CHECK-NEXT: | |-value: MemberPointer MP::x
+
+ constexpr int(MP::*pmn) = (int MP::*)nullptr;
+ // CHECK: `-VarDecl {{.*}} <col:{{.*}}, col:{{.*}}> col:{{.*}} pmn 'int (MP::*const)' constexpr cinit
+ // CHECK-NEXT: |-value: MemberPointer null
}