[clang] 18d0a7e - [clang][Interp] Implement ComplexToReal casts (#77294)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 18 04:55:09 PST 2024


Author: Timm Baeder
Date: 2024-01-18T13:55:04+01:00
New Revision: 18d0a7e4c0d085de4e652e359bdd6778c43ec9bf

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

LOG: [clang][Interp] Implement ComplexToReal casts (#77294)

Add a new emitComplexReal() helper function and use that for the new
casts as well as the old __real implementation.

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/ByteCodeExprGen.h
    clang/test/AST/Interp/complex.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 5839123a5b95f23..138ffed392fcac3 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -287,6 +287,10 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
     return true;
   }
 
+  case CK_IntegralComplexToReal:
+  case CK_FloatingComplexToReal:
+    return this->emitComplexReal(SubExpr);
+
   case CK_ToVoid:
     return discard(SubExpr);
 
@@ -2030,7 +2034,7 @@ bool ByteCodeExprGen<Emitter>::dereference(
   }
 
   if (LV->getType()->isAnyComplexType())
-    return visit(LV);
+    return this->delegate(LV);
 
   return false;
 }
@@ -2767,22 +2771,10 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
     if (!this->visit(SubExpr))
       return false;
     return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
-  case UO_Real: { // __real x
+  case UO_Real: // __real x
     if (T)
       return this->delegate(SubExpr);
-    if (!this->visit(SubExpr))
-      return false;
-    if (!this->emitConstUint8(0, E))
-      return false;
-    if (!this->emitArrayElemPtrPopUint8(E))
-      return false;
-
-    // Since our _Complex implementation does not map to a primitive type,
-    // we sometimes have to do the lvalue-to-rvalue conversion here manually.
-    if (!SubExpr->isLValue())
-      return this->emitLoadPop(classifyPrim(E->getType()), E);
-    return true;
-  }
+    return this->emitComplexReal(SubExpr);
   case UO_Imag: { // __imag x
     if (T) {
       if (!this->discard(SubExpr))
@@ -2953,6 +2945,29 @@ bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
   return false;
 }
 
+/// Emits __real(SubExpr)
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::emitComplexReal(const Expr *SubExpr) {
+  assert(SubExpr->getType()->isAnyComplexType());
+
+  if (DiscardResult)
+    return this->discard(SubExpr);
+
+  if (!this->visit(SubExpr))
+    return false;
+  if (!this->emitConstUint8(0, SubExpr))
+    return false;
+  if (!this->emitArrayElemPtrPopUint8(SubExpr))
+    return false;
+
+  // Since our _Complex implementation does not map to a primitive type,
+  // we sometimes have to do the lvalue-to-rvalue conversion here manually.
+  if (!SubExpr->isLValue())
+    return this->emitLoadPop(*classifyComplexElementType(SubExpr->getType()),
+                             SubExpr);
+  return true;
+}
+
 /// When calling this, we have a pointer of the local-to-destroy
 /// on the stack.
 /// Emit destruction of record types (or arrays of record types).

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index bbb13e97e725692..48005ce05724b54 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -294,6 +294,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
     return this->classify(ElemType);
   }
 
+  bool emitComplexReal(const Expr *SubExpr);
+
   bool emitRecordDestruction(const Descriptor *Desc);
   unsigned collectBaseOffset(const RecordType *BaseType,
                              const RecordType *DerivedType);

diff  --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp
index 1e97cc618495244..e63693a0cfaa140 100644
--- a/clang/test/AST/Interp/complex.cpp
+++ b/clang/test/AST/Interp/complex.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
-// RUN: %clang_cc1 -verify=ref %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify -Wno-unused-value %s
+// RUN: %clang_cc1 -verify=ref -Wno-unused-value %s
 
 // expected-no-diagnostics
 // ref-no-diagnostics
@@ -42,6 +42,18 @@ static_assert(__real(12u) == 12u, "");
 static_assert(__imag(4.0) == 0.0, "");
 static_assert(__imag(13) == 0, "");
 
+constexpr int ignoredCast() {
+  I2;
+  (int)I2;
+  (float)I2;
+  D1;
+  (int)D1;
+  (double)D1;
+  return 0;
+}
+static_assert(ignoredCast() == 0, "");
+static_assert((int)I1 == 1, "");
+static_assert((float)D == 1.0f, "");
 
 
 /// Standalone complex expressions.


        


More information about the cfe-commits mailing list