[clang] eac9044 - [clang][bytecode] Don't check instance pointers for mutability (#205820)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 25 23:01:50 PDT 2026
Author: Timm Baeder
Date: 2026-06-26T08:01:45+02:00
New Revision: eac90446207dedf6bd243c9033fb3f1c7dec8dee
URL: https://github.com/llvm/llvm-project/commit/eac90446207dedf6bd243c9033fb3f1c7dec8dee
DIFF: https://github.com/llvm/llvm-project/commit/eac90446207dedf6bd243c9033fb3f1c7dec8dee.diff
LOG: [clang][bytecode] Don't check instance pointers for mutability (#205820)
The instance pointer being mutable is perfectly fine, we just can't read
anything from it.
This regresses a test case in `cxx11.cpp` where we now diagnose an extra
frame for `U(g1.u)`, but this seems correct since the read is happening
in the copy constructor of `U`.
Added:
Modified:
clang/lib/AST/ByteCode/Interp.cpp
clang/test/AST/ByteCode/cxx11.cpp
clang/test/AST/ByteCode/mutable.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 71021815baeef..2f09c19178f09 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -660,16 +660,7 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK) {
if (S.checkingConstantDestruction()) {
// Never allowed when checking for constant destruction.
- // Find the reason this pointer is mutable.
- PtrView MutablePtr = Ptr;
- while (!MutablePtr.isRoot() && MutablePtr.getBase().isMutable())
- MutablePtr = MutablePtr.getBase();
-
- const FieldDecl *Field = MutablePtr.getField();
- S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_mutable, 1)
- << AK << Field;
- S.Note(Field->getLocation(), diag::note_declared_at);
- return false;
+ // Diagnose below.
} else if (S.getLangOpts().CPlusPlus14 &&
S.lifetimeStartedInEvaluation(Ptr.block())) {
// In C++14 onwards, it is permitted to read a mutable member whose
@@ -677,8 +668,13 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, PtrView Ptr, AccessKinds AK) {
return true;
}
+ // Find the reason this pointer is mutable.
+ PtrView MutablePtr = Ptr;
+ while (!MutablePtr.isRoot() && MutablePtr.getBase().isMutable())
+ MutablePtr = MutablePtr.getBase();
+
const SourceInfo &Loc = S.Current->getSource(OpPC);
- const FieldDecl *Field = Ptr.getField();
+ const FieldDecl *Field = MutablePtr.getField();
S.FFDiag(Loc, diag::note_constexpr_access_mutable, 1) << AK << Field;
S.Note(Field->getLocation(), diag::note_declared_at);
return false;
@@ -1025,8 +1021,6 @@ static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
return false;
if (!(IsCtor || IsDtor) && !CheckLifetime(S, OpPC, Ptr, AK_MemberCall))
return false;
- if (!IsDtor && !CheckMutable(S, OpPC, Ptr))
- return false;
}
return true;
}
diff --git a/clang/test/AST/ByteCode/cxx11.cpp b/clang/test/AST/ByteCode/cxx11.cpp
index ffe2f3c67c511..3553ab3ba68ad 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -343,6 +343,7 @@ namespace ReadMutableInCopyCtor {
constexpr G g1 = {};
constexpr G g2 = g1; // both-error {{must be initialized by a constant expression}} \
// both-note {{read of mutable member 'u'}} \
+ // expected-note {{in call to 'U(g1.u)'}} \
// both-note {{in call to 'G(g1)'}}
}
diff --git a/clang/test/AST/ByteCode/mutable.cpp b/clang/test/AST/ByteCode/mutable.cpp
index 16c8ce9125d5e..5dbaa66ab4c86 100644
--- a/clang/test/AST/ByteCode/mutable.cpp
+++ b/clang/test/AST/ByteCode/mutable.cpp
@@ -73,4 +73,27 @@ constexpr D d2 = d1; // both-error {{must be initialized by a constant expressio
// both-note {{read of mutable member 'y}} \
// both-note {{in call to}}
+namespace MutablenessFromBasePtr {
+ struct Foo {
+ constexpr int five() const { return 5; }
+ int k = 12;
+ };
+ struct M {
+ mutable Foo F; // both-note {{declared here}}
+ };
+ constexpr M m{};
+ static_assert(m.F.k == 12, ""); // both-error {{not an integral constant expression}} \
+ // both-note {{read of mutable member 'F' is not allowed in a constant expression}}
+}
+namespace MemberCall {
+ struct Foo {
+ constexpr int five() const { return 5; }
+ };
+ struct M {
+ mutable Foo F;
+ constexpr int zomg() const { return F.five(); }
+ };
+ constexpr M m{};
+ static_assert(m.zomg() == 5, "");
+}
More information about the cfe-commits
mailing list