https://github.com/akash-manna-sky created https://github.com/llvm/llvm-project/pull/226386
Fixes #156186 A namespace-scope `const` variable has internal linkage in C++, so `__attribute__((weak))` on it is an error and Sema drops the attribute in `FinalizeDeclaration`. That happens after the initializer has already been evaluated, and with the new interpreter that evaluation creates the global block and copies the weak flag into it. From then on the AST says the variable is not weak, but the block still says it is. In C++03, `CheckICE` sees the up-to-date declaration and accepts the array bound, then `EvaluateKnownConstIntCheckOverflow` asserts because the interpreter refuses the load. In later standards there is no crash, but the interpreter reports bogus VLA diagnostics that the classic evaluator does not. `Block::isWeak()` now treats the cached flag as "may be weak" and confirms with the declaration, so blocks agree with the AST at the time of the read. Blocks that were never flagged keep the zero-cost fast path. Every consumer of the flag goes through this method, so load checks, pointer comparisons, and dead-block copies all pick it up. >From 88b0e46d8779df2666a332d2a17072b44e32e76b Mon Sep 17 00:00:00 2001 From: Akash Manna <[email protected]> Date: Fri, 25 Sep 2026 12:44:02 +0530 Subject: [PATCH] [clang][bytecode] Re-check the declaration before treating a block as weak Sema drops an invalid weak attribute in FinalizeDeclaration, after the initializer has already been evaluated. By then the interpreter has created the global block and copied the weak flag into it, so later reads keep failing even though the declaration is no longer weak. In C++03 the ICE check sees the up-to-date declaration, accepts the expression, and EvaluateKnownConstIntCheckOverflow asserts when the interpreter refuses the load. Make Block::isWeak() confirm with the declaration when the flag is set. Fixes #156186 --- clang/lib/AST/ByteCode/InterpBlock.cpp | 10 ++++++++++ clang/lib/AST/ByteCode/InterpBlock.h | 2 +- clang/test/AST/ByteCode/weak-internal-linkage.cpp | 12 ++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 clang/test/AST/ByteCode/weak-internal-linkage.cpp diff --git a/clang/lib/AST/ByteCode/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp index 888a660719590d..6bd6d520e0037f 100644 --- a/clang/lib/AST/ByteCode/InterpBlock.cpp +++ b/clang/lib/AST/ByteCode/InterpBlock.cpp @@ -55,6 +55,16 @@ void Block::removePointer(Pointer *P) { #endif } +bool Block::isWeak() const { + if (!(AccessFlags & WeakFlag)) + return false; + + // Sema might have dropped the weak attribute after this block was created. + if (const ValueDecl *VD = Desc->asValueDecl()) + return VD->isWeak(); + return true; +} + void Block::cleanup() { if (Pointers == nullptr && !isDynamic() && isDead()) (reinterpret_cast<DeadBlock *>(this + 1) - 1)->free(); diff --git a/clang/lib/AST/ByteCode/InterpBlock.h b/clang/lib/AST/ByteCode/InterpBlock.h index 4d6a2ecf813218..469601eef9e28e 100644 --- a/clang/lib/AST/ByteCode/InterpBlock.h +++ b/clang/lib/AST/ByteCode/InterpBlock.h @@ -79,7 +79,7 @@ class Block final { bool isStatic() const { return IsStatic; } /// Checks if the block is temporary. bool isTemporary() const { return Desc->IsTemporary; } - bool isWeak() const { return AccessFlags & WeakFlag; } + bool isWeak() const; bool isDynamic() const { return (DynAllocId != std::nullopt); } bool isDead() const { return AccessFlags & DeadFlag; } /// Returns the size of the block, including metadata. diff --git a/clang/test/AST/ByteCode/weak-internal-linkage.cpp b/clang/test/AST/ByteCode/weak-internal-linkage.cpp new file mode 100644 index 00000000000000..359f96d01788d1 --- /dev/null +++ b/clang/test/AST/ByteCode/weak-internal-linkage.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++03 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -std=c++03 -verify=ref,both %s +// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify=expected,both %s +// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s + +/// The weak attribute is dropped after the initializer has been evaluated. +__attribute__((weak)) const unsigned int test10_bound = 10; // both-error {{weak declaration cannot have internal linkage}} +char test10_global[test10_bound]; +void test10(void) { + char test10_local[test10_bound] = "help"; +} +int test10_size_check[sizeof(test10_global) == 10 ? 1 : -1]; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
