[clang] ae4849f - [clang][Interp] PointerToIntegral casts

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 26 04:39:59 PDT 2023


Author: Timm Bäder
Date: 2023-07-26T13:39:37+02:00
New Revision: ae4849f96706cde460e6c792a6c8110791a6db32

URL: https://github.com/llvm/llvm-project/commit/ae4849f96706cde460e6c792a6c8110791a6db32
DIFF: https://github.com/llvm/llvm-project/commit/ae4849f96706cde460e6c792a6c8110791a6db32.diff

LOG: [clang][Interp] PointerToIntegral casts

Differential Revision: https://reviews.llvm.org/D150946

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/Interp.cpp
    clang/lib/AST/Interp/Interp.h
    clang/lib/AST/Interp/Opcodes.td
    clang/lib/AST/Interp/Pointer.h
    clang/test/AST/Interp/literals.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 29069ba10bb86d..9f17ba1d7aa05f 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -127,6 +127,15 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
       return true;
     return this->emitNull(classifyPrim(CE->getType()), CE);
 
+  case CK_PointerToIntegral: {
+    // TODO: Discard handling.
+    if (!this->visit(SubExpr))
+      return false;
+
+    PrimType T = classifyPrim(CE->getType());
+    return this->emitCastPointerIntegral(T, CE);
+  }
+
   case CK_ArrayToPointerDecay:
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:

diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 4917f43f9512ec..4d49c75799637b 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -462,6 +462,17 @@ bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) {
   return CheckArrayInitialized(S, OpPC, This, CAT);
 }
 
+bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
+                                   const Pointer &Ptr) {
+  if (!S.inConstantContext())
+    return true;
+
+  const SourceInfo &E = S.Current->getSource(OpPC);
+  S.CCEDiag(E, diag::note_constexpr_invalid_cast)
+      << 2 << S.getLangOpts().CPlusPlus;
+  return false;
+}
+
 bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status) {
   // In a constant context, assume that any dynamic rounding mode or FP
   // exception state matches the default floating-point environment.

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 33ab0cdedeae42..ee3b953bb69cc2 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -104,6 +104,10 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
 /// Checks that all fields are initialized after a constructor call.
 bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This);
 
+/// Checks if reinterpret casts are legal in the current context.
+bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
+                                   const Pointer &Ptr);
+
 /// Checks if the shift operation is legal.
 template <typename LT, typename RT>
 bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
@@ -1493,6 +1497,17 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
   }
 }
 
+template <PrimType Name, class T = typename PrimConv<Name>::T>
+bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
+  const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+  if (!CheckPotentialReinterpretCast(S, OpPC, Ptr))
+    return false;
+
+  S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 // Zero, Nullptr
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 6d12823990cf2c..0f494c530b2568 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -565,6 +565,12 @@ def CastFloatingIntegral : Opcode {
   let HasGroup = 1;
 }
 
+def CastPointerIntegral : Opcode {
+  let Types = [AluTypeClass];
+  let Args = [];
+  let HasGroup = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // Comparison opcodes.
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index f795466f1db4c5..a5e7ad8af81898 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -77,6 +77,13 @@ class Pointer {
   /// Converts the pointer to an APValue.
   APValue toAPValue() const;
 
+  /// Converts the pointer to a string usable in diagnostics.
+  std::string toDiagnosticString(const ASTContext &Ctx) const;
+
+  unsigned getIntegerRepresentation() const {
+    return reinterpret_cast<uintptr_t>(Pointee) + Offset;
+  }
+
   /// Offsets a pointer inside an array.
   Pointer atIndex(unsigned Idx) const {
     if (Base == RootPtrMark)

diff  --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 5a645621e2d756..c6f293886f90dc 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -6,6 +6,8 @@
 #define INT_MIN (~__INT_MAX__)
 #define INT_MAX __INT_MAX__
 
+typedef __INTPTR_TYPE__ intptr_t;
+
 
 static_assert(true, "");
 static_assert(false, ""); // expected-error{{failed}} ref-error{{failed}}
@@ -932,3 +934,15 @@ namespace NE {
   static_assert(a() == 0, "");
 #endif
 }
+
+namespace PointerCasts {
+  constexpr int M = 10;
+  constexpr const int *P = &M;
+  constexpr intptr_t A = (intptr_t)P; // ref-error {{must be initialized by a constant expression}} \
+                                      // ref-note {{cast that performs the conversions of a reinterpret_cast}} \
+                                      // expected-error {{must be initialized by a constant expression}} \
+                                      // expected-note {{cast that performs the conversions of a reinterpret_cast}}
+
+  int array[(long)(char*)0]; // ref-warning {{variable length array folded to constant array}} \
+                             // expected-warning {{variable length array folded to constant array}}
+}


        


More information about the cfe-commits mailing list