llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

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`.

---
Full diff: https://github.com/llvm/llvm-project/pull/205820.diff


3 Files Affected:

- (modified) clang/lib/AST/ByteCode/Interp.cpp (+7-13) 
- (modified) clang/test/AST/ByteCode/cxx11.cpp (+1) 
- (modified) clang/test/AST/ByteCode/mutable.cpp (+23) 


``````````diff
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, "");
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/205820
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to