llvm-project/clang/test/AST/ByteCode/codegen-constexpr-unknown.cpp
Timm Baeder 8edbf23098
[clang][bytecode] Revisit reference variables as constexpr-unknown in C++26 (#187918)
When revisiting `const T& range = f(T());`, we do mark the variable for
`range` as constexpr-unknown, but not the temporary variable we create
for `T()`. Change that.

Then we also need to ignore constexpr-unknown pointers in
`CheckInvoke()`.

Fixes https://github.com/llvm/llvm-project/issues/187775
2026-04-01 09:49:55 +02:00

95 lines
2.1 KiB
C++

// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -fcxx-exceptions -o - %s | FileCheck %s --check-prefix=CHECK
// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -fcxx-exceptions -o - %s -fexperimental-new-constant-interpreter -DINTERP | FileCheck %s --check-prefix=CHECK
/// CodeGenFunction::ConstantFoldsToSimpleInteger() for the if condition
/// needs to succeed and return true.
/// When re-visiting p during that evaluation, we need to attach the local
/// variable to the topmost scope, otherwise we will pick the call scope
/// of to_address and de-allocate the local variable at the end of the
/// to_address call.
extern void abort2();
constexpr const int* to_address(const int *a) {
return a;
}
void rightscope() {
const int p = 0;
if (to_address(&p) == &p)
return;
abort2();
}
// CHECK: define dso_local void @_Z10rightscopev()
// CHECK-NEXT: entry:
// CHECK-NEXT: %p = alloca i32
// CHECK-NEXT: store i32 0, ptr %p
/// In the if expression below, the read from s.i should fail.
/// If it doesn't, and we actually read the value 0, the call to
/// func() will always occur, resuliting in a runtime failure.
struct S {
mutable int i = 0;
};
void func() {
__builtin_abort();
};
void setI(const S &s) {
s.i = 12;
}
int main() {
const S s;
setI(s);
if (s.i == 0)
func();
return 0;
}
// CHECK: define dso_local noundef i32 @main()
// CHECK: br
// CHECK: if.then
// CHECK: if.end
// CHECK: ret i32 0
/// Similarly, here we revisit the BindingDecl.
struct F { int x; };
int main2() {
const F s{99};
const auto& [r1] = s;
if (&r1 != &s.x)
__builtin_abort();
return 0;
}
// CHECK: define dso_local noundef i32 @_Z5main2v()
// CHECK: br
// CHECK: if.then
// CHECK: if.end
// CHECK: ret i32 0
/// The comparison here should work and return 0.
class X {
public:
X();
X(const X&);
X(const volatile X &);
~X();
};
extern X OuterX;
X test24() {
X x;
if (&x == &OuterX)
throw 0;
return x;
}
// CHECK: define dso_local void @_Z6test24v
// CHECK-NOT: lpad
// CHECK-NOT: eh.resume