[clang] [clang][bytecode] Don't check instance pointers for mutability (PR #205820)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 25 06:58:47 PDT 2026
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/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`.
>From 64b49b225f33298caa1dbb9070c3713da8077f87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 25 Jun 2026 13:59:40 +0200
Subject: [PATCH] asdf
---
clang/lib/AST/ByteCode/Interp.cpp | 20 +++++++-------------
clang/test/AST/ByteCode/cxx11.cpp | 1 +
clang/test/AST/ByteCode/mutable.cpp | 23 +++++++++++++++++++++++
3 files changed, 31 insertions(+), 13 deletions(-)
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