Author: Timm Bäder Date: 2024-07-14T17:47:11+02:00 New Revision: 33af112f99fe956fb93fb2b797a141ee93956283
URL: https://github.com/llvm/llvm-project/commit/33af112f99fe956fb93fb2b797a141ee93956283 DIFF: https://github.com/llvm/llvm-project/commit/33af112f99fe956fb93fb2b797a141ee93956283.diff LOG: [clang][Interp] Fix modifying const objects in functions calls in ctors The current frame might not be a constructor for the object we're initializing, but a parent frame might. Added: Modified: clang/lib/AST/Interp/Interp.cpp clang/test/AST/Interp/records.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 0411fcad88ad0..70a470021e7f2 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -405,10 +405,16 @@ bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr) { // The This pointer is writable in constructors and destructors, // even if isConst() returns true. - if (const Function *Func = S.Current->getFunction(); - Func && (Func->isConstructor() || Func->isDestructor()) && - Ptr.block() == S.Current->getThis().block()) { - return true; + // TODO(perf): We could be hitting this code path quite a lot in complex + // constructors. Is there a better way to do this? + if (S.Current->getFunction()) { + for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) { + if (const Function *Func = Frame->getFunction(); + Func && (Func->isConstructor() || Func->isDestructor()) && + Ptr.block() == Frame->getThis().block()) { + return true; + } + } } if (!Ptr.isBlockPointer()) diff --git a/clang/test/AST/Interp/records.cpp b/clang/test/AST/Interp/records.cpp index 4b06fc7522d45..2fc88a0b1df6a 100644 --- a/clang/test/AST/Interp/records.cpp +++ b/clang/test/AST/Interp/records.cpp @@ -1512,3 +1512,28 @@ namespace OnePastEndAndBack { constexpr const Base *d = c - 1; static_assert(d == &a, ""); } + +namespace BitSet { + class Bitset { + unsigned Bit = 0; + + public: + constexpr Bitset() { + int Init[2] = {1,2}; + for (auto I : Init) + set(I); + } + constexpr void set(unsigned I) { + this->Bit++; + this->Bit = 1u << 1; + } + }; + + struct ArchInfo { + Bitset DefaultExts; + }; + + constexpr ArchInfo ARMV8A = { + Bitset() + }; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits