https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/128409
>From 83248eb164ff53442ad6d0c9d1be20027519bac1 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Tue, 18 Feb 2025 01:26:26 +0800 Subject: [PATCH 1/6] [Clang][CodeGen] Bail out on constexpr unknown values in ConstantEmitter --- clang/lib/CodeGen/CGExprConstant.cpp | 6 ++++-- clang/test/CodeGenCXX/cxx23-p2280r4.cpp | 13 +++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGenCXX/cxx23-p2280r4.cpp diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index ee5874b26f534..075f3f435ad74 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1883,8 +1883,10 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { // Try to emit the initializer. Note that this can allow some things that // are not allowed by tryEmitPrivateForMemory alone. - if (APValue *value = D.evaluateValue()) - return tryEmitPrivateForMemory(*value, destType); + if (APValue *value = D.evaluateValue()) { + if (!value->allowConstexprUnknown()) + return tryEmitPrivateForMemory(*value, destType); + } return nullptr; } diff --git a/clang/test/CodeGenCXX/cxx23-p2280r4.cpp b/clang/test/CodeGenCXX/cxx23-p2280r4.cpp new file mode 100644 index 0000000000000..bb9a90ba18ece --- /dev/null +++ b/clang/test/CodeGenCXX/cxx23-p2280r4.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -emit-llvm -o - | FileCheck %s + +extern int& s; + +// CHECK: @_Z4testv() +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I:%.*]] = alloca ptr, align {{.*}} +// CHECK-NEXT: [[X:%.*]] = load ptr, ptr @s, align {{.*}} +// CHECK-NEXT: store ptr [[X]], ptr [[I]], align {{.*}} +int& test() { + auto &i = s; + return i; +} >From ac2bd210ffed3d882be2569a415d7c4bbcbba3e9 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Tue, 18 Feb 2025 19:20:39 +0800 Subject: [PATCH 2/6] Address review comments. NFC. --- clang/test/CodeGenCXX/cxx23-p2280r4.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/test/CodeGenCXX/cxx23-p2280r4.cpp b/clang/test/CodeGenCXX/cxx23-p2280r4.cpp index bb9a90ba18ece..d5409be451df0 100644 --- a/clang/test/CodeGenCXX/cxx23-p2280r4.cpp +++ b/clang/test/CodeGenCXX/cxx23-p2280r4.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++23 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++17 %s -emit-llvm -o - | FileCheck %s extern int& s; >From 1cea7d422c31b5065c76d9fb4a251955b2bea8e6 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Fri, 21 Feb 2025 12:15:29 +0800 Subject: [PATCH 3/6] [Clang][CodeGen] Address review comments. NFC. --- clang/lib/CodeGen/CGExprConstant.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 075f3f435ad74..7d44a9f583eca 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1883,10 +1883,10 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { // Try to emit the initializer. Note that this can allow some things that // are not allowed by tryEmitPrivateForMemory alone. - if (APValue *value = D.evaluateValue()) { - if (!value->allowConstexprUnknown()) - return tryEmitPrivateForMemory(*value, destType); - } + // Bail out on constexpr-unknown values since they are invalid in CodeGen. + if (APValue *value = D.evaluateValue(); + value && !value->allowConstexprUnknown()) + return tryEmitPrivateForMemory(*value, destType); return nullptr; } >From bc24bde52b664ca4b3bcbbbdd48a5a14be37a278 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Sun, 23 Feb 2025 17:04:03 +0800 Subject: [PATCH 4/6] [Clang] Treat constexpr-unknown value as invalid in `evaluateValue` --- clang/lib/AST/Decl.cpp | 3 +++ clang/lib/AST/ExprConstant.cpp | 2 -- clang/lib/CodeGen/CGExprConstant.cpp | 6 ++++-- clang/test/SemaCXX/constant-expression-cxx11.cpp | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5a3be1690f335..f6cf75ed96aca 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2587,6 +2587,9 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes, !Notes.empty()) Result = false; + if (Eval->Evaluated.allowConstexprUnknown()) + Result = false; + // Ensure the computed APValue is cleaned up later if evaluation succeeded, // or that it's empty (so that there's nothing to clean up) if evaluation // failed. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 6ccb6e23f8d2f..5e69b44c20e9c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3628,8 +3628,6 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E, if (AllowConstexprUnknown) { if (!Result) Result = &Info.CurrentCall->createConstexprUnknownAPValues(VD, Base); - else - Result->setConstexprUnknown(); } return true; } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 7d44a9f583eca..0295f703b9061 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1884,9 +1884,11 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { // Try to emit the initializer. Note that this can allow some things that // are not allowed by tryEmitPrivateForMemory alone. // Bail out on constexpr-unknown values since they are invalid in CodeGen. - if (APValue *value = D.evaluateValue(); - value && !value->allowConstexprUnknown()) + if (APValue *value = D.evaluateValue()) { + assert(!value->allowConstexprUnknown() && + "Constexpr unknown values are not allowed in CodeGen"); return tryEmitPrivateForMemory(*value, destType); + } return nullptr; } diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 76e2f81947051..0702673144bd5 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -122,9 +122,9 @@ namespace CaseStatements { } extern int &Recurse1; -int &Recurse2 = Recurse1; // expected-note {{declared here}} +int &Recurse2 = Recurse1; // pre-cxx23-note {{declared here}} int &Recurse1 = Recurse2; -constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'Recurse2' is not a constant expression}} +constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} pre-cxx23-note {{initializer of 'Recurse2' is not a constant expression}} extern const int RecurseA; const int RecurseB = RecurseA; // expected-note {{declared here}} >From 52c81598da38532c119db9c06fcc3d7f9c332a8e Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Thu, 27 Feb 2025 00:07:22 +0800 Subject: [PATCH 5/6] [Clang][AST] Fix diag regression --- clang/lib/AST/Decl.cpp | 3 --- clang/lib/AST/ExprConstant.cpp | 12 ++++++++++++ clang/test/SemaCXX/constant-expression-cxx11.cpp | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index f6cf75ed96aca..5a3be1690f335 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2587,9 +2587,6 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes, !Notes.empty()) Result = false; - if (Eval->Evaluated.allowConstexprUnknown()) - Result = false; - // Ensure the computed APValue is cleaned up later if evaluation succeeded, // or that it's empty (so that there's nothing to clean up) if evaluation // failed. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5e69b44c20e9c..42801dc4e18fa 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -16998,6 +16998,18 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx, if (!Info.discardCleanups()) llvm_unreachable("Unhandled cleanup; missing full expression marker?"); + + if (Value.allowConstexprUnknown()) { + assert(Value.isLValue() && "Expected an lvalue"); + auto Base = Value.getLValueBase(); + const auto *NewVD = Base.dyn_cast<const ValueDecl *>(); + if (!NewVD) + NewVD = VD; + Info.FFDiag(getExprLoc(), diag::note_constexpr_var_init_non_constant, 1) + << NewVD; + NoteLValueLocation(Info, Base); + return false; + } } return CheckConstantExpression(Info, DeclLoc, DeclTy, Value, diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 0702673144bd5..76e2f81947051 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -122,9 +122,9 @@ namespace CaseStatements { } extern int &Recurse1; -int &Recurse2 = Recurse1; // pre-cxx23-note {{declared here}} +int &Recurse2 = Recurse1; // expected-note {{declared here}} int &Recurse1 = Recurse2; -constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} pre-cxx23-note {{initializer of 'Recurse2' is not a constant expression}} +constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}} expected-note {{initializer of 'Recurse2' is not a constant expression}} extern const int RecurseA; const int RecurseB = RecurseA; // expected-note {{declared here}} >From 1f4618cbee227288c7b059236ed09705cafbf5f3 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Thu, 27 Feb 2025 13:09:36 +0800 Subject: [PATCH 6/6] Remove comments. NFC. --- clang/lib/CodeGen/CGExprConstant.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 0295f703b9061..08e42a9e1dcf3 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1883,7 +1883,6 @@ llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { // Try to emit the initializer. Note that this can allow some things that // are not allowed by tryEmitPrivateForMemory alone. - // Bail out on constexpr-unknown values since they are invalid in CodeGen. if (APValue *value = D.evaluateValue()) { assert(!value->allowConstexprUnknown() && "Constexpr unknown values are not allowed in CodeGen"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits