https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/208990
... if we're in the bottom frame. >From 51b228649819fb88f1c0164fac300b77884d061b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]> Date: Sun, 12 Jul 2026 08:22:49 +0200 Subject: [PATCH] diagnose reads from non-const locals --- clang/lib/AST/ByteCode/Interp.cpp | 12 +++++++++++- clang/test/AST/ByteCode/literals.cpp | 20 ++++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp index 0adcdfe6e78c9..169aab5ed9f3d 100644 --- a/clang/lib/AST/ByteCode/Interp.cpp +++ b/clang/lib/AST/ByteCode/Interp.cpp @@ -857,11 +857,12 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B) { bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) { assert(!B->isExtern()); const auto &Desc = *reinterpret_cast<const InlineDescriptor *>(B->rawData()); + const Descriptor *BlockDesc = B->getDescriptor(); if (!CheckLifetime(S, OpPC, Desc.LifeState, B, AK_Read)) return false; if (!Desc.IsInitialized) return DiagnoseUninitialized(S, OpPC, /*Extern=*/false, B, AK_Read); - if (B->getDescriptor()->IsVolatile) { + if (BlockDesc->IsVolatile) { if (!S.getLangOpts().CPlusPlus) return Invalid(S, OpPC); @@ -872,6 +873,15 @@ bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B) { S.Note(D->getLocation(), diag::note_constexpr_volatile_here) << 1; return false; } + + // A non-const local variable while we don't have a parent frame. This must be + // a local variable in a statement expression. + if (S.Current->isBottomFrame() && !BlockDesc->IsConst && + !BlockDesc->IsTemporary && !S.checkingPotentialConstantExpression()) { + if (const ValueDecl *VD = BlockDesc->asValueDecl()) + diagnoseNonConstVariable(S, OpPC, VD); + return false; + } return true; } diff --git a/clang/test/AST/ByteCode/literals.cpp b/clang/test/AST/ByteCode/literals.cpp index eafab2e1ab64d..3b24b166e39a7 100644 --- a/clang/test/AST/ByteCode/literals.cpp +++ b/clang/test/AST/ByteCode/literals.cpp @@ -1326,17 +1326,29 @@ namespace StmtExprs { constexpr long a(bool x) { return x ? 0 : (intptr_t)&&lbl + (0 && ({lbl: 0;})); } } - /// GCC agrees with the bytecode interpreter here. + /// FIXME: This should be accepted. + /// BUT accepting this breaks test/OpenMP/for_codegen.cpp void switchInSE() { - static_assert(({ // ref-error {{not an integral constant expression}} - int i = 20; + static_assert(({ // both-error {{not an integral constant expression}} + int i = 20; // expected-note {{declared here}} switch(10) { - case 10: i = 300; // ref-note {{a constant expression cannot modify an object that is visible outside that expression}} + case 10: i = 300; // ref-note {{a constant expression cannot modify an object that is visible outside that expression}} \ + // expected-note {{read of non-const variable 'i'}} } i; }) == 300); } + /// We reject the test above because of the read from i, not because of the modification. + /// FIXME: The sourcelocation for the broken read is incorrect. + void switchInSE2() { + static_assert(({ // both-error {{not an integral constant expression}} + int i = 20; // expected-note {{read of non-const variable}} \ + // both-note {{declared here}} + i; // ref-note {{read of non-const variable}} + }) == 300); + } + constexpr int f(int k) { switch (k) { case 0: _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
