llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>



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


4 Files Affected:

- (modified) clang/lib/AST/ByteCode/Interp.cpp (+13-5) 
- (modified) clang/lib/AST/ByteCode/Interp.h (+7) 
- (added) clang/test/AST/ByteCode/codegen-constexpr-unknown.cpp (+72) 
- (removed) clang/test/AST/ByteCode/codegen-mutable-read.cpp (-36) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 187477713bef8..0acfe01a42410 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -302,6 +302,17 @@ void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
     TYPE_SWITCH(Ty, S.Stk.discard<T>());
 }
 
+// FIXME: Instead of using this fairly expensive test, we should
+// just mark constexpr-unknown values when creating them.
+bool isConstexprUnknown(const Pointer &P) {
+  if (!P.isBlockPointer())
+    return false;
+  if (P.isDummy())
+    return false;
+  const VarDecl *VD = P.block()->getDescriptor()->asVarDecl();
+  return VD && VD->hasLocalStorage();
+}
+
 bool CheckBCPResult(InterpState &S, const Pointer &Ptr) {
   if (Ptr.isDummy())
     return false;
@@ -607,11 +618,8 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, const 
Pointer &Ptr) {
     // variables in Compiler.cpp:visitDeclRef. Revisiting a so far
     // unknown variable will get the same EvalID and we end up allowing
     // reads from mutable members of it.
-    if (!S.inConstantContext()) {
-      if (const VarDecl *VD = Ptr.block()->getDescriptor()->asVarDecl();
-          VD && VD->hasLocalStorage())
-        return false;
-    }
+    if (!S.inConstantContext() && isConstexprUnknown(Ptr))
+      return false;
     return true;
   }
 
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index ee4139fbc9530..938077a9f10ae 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -173,6 +173,8 @@ static bool handleOverflow(InterpState &S, CodePtr OpPC, 
const T &SrcValue) {
 bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
                               const FixedPoint &FP);
 
+bool isConstexprUnknown(const Pointer &P);
+
 enum class ShiftDir { Left, Right };
 
 /// Checks if the shift operation is legal.
@@ -1062,6 +1064,11 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr 
OpPC, CompareFn Fn) {
     }
   }
 
+  if (!S.inConstantContext()) {
+    if (isConstexprUnknown(LHS) || isConstexprUnknown(RHS))
+      return false;
+  }
+
   if (Pointer::hasSameBase(LHS, RHS)) {
     unsigned VL = LHS.getByteOffset();
     unsigned VR = RHS.getByteOffset();
diff --git a/clang/test/AST/ByteCode/codegen-constexpr-unknown.cpp 
b/clang/test/AST/ByteCode/codegen-constexpr-unknown.cpp
new file mode 100644
index 0000000000000..f62117d5f7bec
--- /dev/null
+++ b/clang/test/AST/ByteCode/codegen-constexpr-unknown.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -fcxx-exceptions -o - %s    
                                     | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -fcxx-exceptions -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
+
+
+/// In the if expression below, the read from s.i should fail.
+/// If it doesn't, and we actually read the value 0, the call to
+/// func() will always occur, resuliting in a runtime failure.
+
+struct S {
+  mutable int i = 0;
+};
+
+void func() {
+  __builtin_abort();
+};
+
+void setI(const S &s) {
+  s.i = 12;
+}
+
+int main() {
+  const S s;
+
+  setI(s);
+
+  if (s.i == 0)
+    func();
+
+  return 0;
+}
+
+// CHECK: define dso_local noundef i32 @main()
+// CHECK: br
+// CHECK: if.then
+// CHECK: if.end
+// CHECK: ret i32 0
+
+
+/// Similarly, here we revisit the BindingDecl.
+struct F { int x; };
+int main2() {
+  const F const s{99};
+  const auto& [r1] = s;
+  if (&r1 != &s.x)
+    __builtin_abort();
+  return 0;
+}
+// CHECK: define dso_local noundef i32 @_Z5main2v()
+// CHECK: br
+// CHECK: if.then
+// CHECK: if.end
+// CHECK: ret i32 0
+
+/// The comparison here should work and return 0.
+class X {
+public:
+  X();
+  X(const X&);
+  X(const volatile X &);
+  ~X();
+};
+extern X OuterX;
+X test24() {
+  X x;
+  if (&x == &OuterX)
+    throw 0;
+  return x;
+}
+
+// CHECK: define dso_local void @_Z6test24v
+// CHECK-NOT: lpad
+// CHECK-NOT: eh.resume
diff --git a/clang/test/AST/ByteCode/codegen-mutable-read.cpp 
b/clang/test/AST/ByteCode/codegen-mutable-read.cpp
deleted file mode 100644
index afa46d34b0673..0000000000000
--- a/clang/test/AST/ByteCode/codegen-mutable-read.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s                     
                    | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
-
-
-/// In the if expression below, the read from s.i should fail.
-/// If it doesn't, and we actually read the value 0, the call to
-/// func() will always occur, resuliting in a runtime failure.
-
-struct S {
-  mutable int i = 0;
-};
-
-void func() {
-  __builtin_abort();
-};
-
-void setI(const S &s) {
-  s.i = 12;
-}
-
-int main() {
-  const S s;
-
-  setI(s);
-
-  if (s.i == 0)
-    func();
-
-  return 0;
-}
-
-// CHECK: define dso_local noundef i32 @main()
-// CHECK: br
-// CHECK: if.then
-// CHECK: if.end
-// CHECK: ret i32 0

``````````

</details>


https://github.com/llvm/llvm-project/pull/133701
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to