[clang] [clang][bytecode] Fix diagnostic in final ltor cast (PR #105292)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 20 12:37:45 PDT 2024


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/105292

Don't diagnose volatile reads but diagnose a few other accesses earlier.

>From 8580230aad18c0955e92767e843344579dac1a66 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 20 Aug 2024 18:06:25 +0200
Subject: [PATCH] [clang][bytecode] Fix diagnostic in final ltor cast

Don't diagnose volatile reads but diagnose a few other accesses earlier.
---
 clang/lib/AST/ByteCode/Compiler.cpp           |  2 +-
 clang/lib/AST/ByteCode/EvalEmitter.cpp        | 11 +++++---
 clang/lib/AST/ByteCode/Interp.cpp             | 25 +++++++++++++++++++
 clang/lib/AST/ByteCode/Interp.h               |  1 +
 .../temp/temp.arg/temp.arg.nontype/p1-11.cpp  |  1 +
 5 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 131b83ae8eb397..0129d91a01d52e 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2556,7 +2556,7 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
 
     if (DiscardResult)
       return this->emitPopPtr(E);
-    return true;
+    return this->emitFinishInit(E);
   }
 
   if (T->isArrayType()) {
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index e36d86c814e17f..53ec8f52d4921f 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -165,11 +165,16 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
   if (ConvertResultToRValue) {
     if (!Ptr.isZero() && !Ptr.isDereferencable())
       return false;
+
+    if (S.getLangOpts().CPlusPlus11 && Ptr.isBlockPointer() &&
+        !CheckFinalLoad(S, OpPC, Ptr)) {
+      return false;
+    }
+
     // Never allow reading from a non-const pointer, unless the memory
     // has been created in this evaluation.
-    if (!Ptr.isZero() && Ptr.isBlockPointer() &&
-        Ptr.block()->getEvalID() != Ctx.getEvalID() &&
-        (!CheckLoad(S, OpPC, Ptr, AK_Read) || !Ptr.isConst()))
+    if (!Ptr.isZero() && !Ptr.isConst() && Ptr.isBlockPointer() &&
+        Ptr.block()->getEvalID() != Ctx.getEvalID())
       return false;
 
     if (std::optional<APValue> V =
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index a0571728570d3f..aea303f0e630c9 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -559,6 +559,31 @@ bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
   return true;
 }
 
+/// This is not used by any of the opcodes directly. It's used by
+/// EvalEmitter to do the final lvalue-to-rvalue conversion.
+bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+  if (!CheckLive(S, OpPC, Ptr, AK_Read))
+    return false;
+  if (!CheckConstant(S, OpPC, Ptr))
+    return false;
+
+  if (!CheckDummy(S, OpPC, Ptr, AK_Read))
+    return false;
+  if (!CheckExtern(S, OpPC, Ptr))
+    return false;
+  if (!CheckRange(S, OpPC, Ptr, AK_Read))
+    return false;
+  if (!CheckActive(S, OpPC, Ptr, AK_Read))
+    return false;
+  if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
+    return false;
+  if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
+    return false;
+  if (!CheckMutable(S, OpPC, Ptr))
+    return false;
+  return true;
+}
+
 bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
   if (!CheckLive(S, OpPC, Ptr, AK_Assign))
     return false;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index bad46e98304845..56d7bc7e7a29f3 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -92,6 +92,7 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
 /// Checks if a value can be loaded from a block.
 bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                AccessKinds AK = AK_Read);
+bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
 
 bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                       AccessKinds AK);
diff --git a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp
index e28753c3d668cc..692958ef565cf4 100644
--- a/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp
+++ b/clang/test/CXX/temp/temp.arg/temp.arg.nontype/p1-11.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++11 %s -verify -triple x86_64-linux-gnu
+// RUN: %clang_cc1 -std=c++11 %s -verify -triple x86_64-linux-gnu -fexperimental-new-constant-interpreter
 
 namespace std {
   typedef decltype(nullptr) nullptr_t;



More information about the cfe-commits mailing list