llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Akash Manna (akash-manna-sky) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/226386.diff 3 Files Affected: - (modified) clang/lib/AST/ByteCode/InterpBlock.cpp (+10) - (modified) clang/lib/AST/ByteCode/InterpBlock.h (+1-1) - (added) clang/test/AST/ByteCode/weak-internal-linkage.cpp (+12) ``````````diff diff --git a/clang/lib/AST/ByteCode/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp index 888a660719590..6bd6d520e0037 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 4d6a2ecf81321..469601eef9e28 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 0000000000000..359f96d01788d --- /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]; `````````` </details> https://github.com/llvm/llvm-project/pull/226386 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
