[clang] 797fee6 - [clang][Interp] Start supporting complex types

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 14 02:57:47 PST 2023


Author: Timm Bäder
Date: 2023-12-14T11:57:38+01:00
New Revision: 797fee68d1cb6a4122d89880d44f8c99559c5cac

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

LOG: [clang][Interp] Start supporting complex types

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

Added: 
    clang/test/AST/Interp/complex.cpp

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/Context.cpp
    clang/lib/AST/Interp/EvalEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index f7f8e6c73d84e2..efa98c6517a2ef 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -671,6 +671,22 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
     return true;
   }
 
+  if (T->isAnyComplexType()) {
+    unsigned InitIndex = 0;
+    for (const Expr *Init : E->inits()) {
+      PrimType InitT = classifyPrim(Init->getType());
+
+      if (!this->visit(Init))
+        return false;
+
+      if (!this->emitInitElem(InitT, InitIndex, E))
+        return false;
+      ++InitIndex;
+    }
+    assert(InitIndex == 2);
+    return true;
+  }
+
   return false;
 }
 
@@ -2550,8 +2566,22 @@ 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_Imag:   // __imag x
+  case UO_Real: { // __real x
+    assert(!T);
+    if (!this->visit(SubExpr))
+      return false;
+    if (!this->emitConstUint8(0, E))
+      return false;
+    return this->emitArrayElemPtrPopUint8(E);
+  }
+  case UO_Imag: { // __imag x
+    assert(!T);
+    if (!this->visit(SubExpr))
+      return false;
+    if (!this->emitConstUint8(1, E))
+      return false;
+    return this->emitArrayElemPtrPopUint8(E);
+  }
   case UO_Extension:
     return this->delegate(SubExpr);
   case UO_Coawait:

diff  --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 4fe6d1173f427e..17abb71635839c 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -92,6 +92,9 @@ std::optional<PrimType> Context::classify(QualType T) const {
   if (T->isBooleanType())
     return PT_Bool;
 
+  if (T->isAnyComplexType())
+    return std::nullopt;
+
   if (T->isSignedIntegerOrEnumerationType()) {
     switch (Ctx.getIntWidth(T)) {
     case 64:

diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp
index 9bc42057c5f578..0ff0bde8fd17e8 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -208,6 +208,27 @@ bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
       }
       return Ok;
     }
+
+    // Complex types.
+    if (const auto *CT = Ty->getAs<ComplexType>()) {
+      QualType ElemTy = CT->getElementType();
+      std::optional<PrimType> ElemT = Ctx.classify(ElemTy);
+      assert(ElemT);
+
+      if (ElemTy->isIntegerType()) {
+        INT_TYPE_SWITCH(*ElemT, {
+          auto V1 = Ptr.atIndex(0).deref<T>();
+          auto V2 = Ptr.atIndex(1).deref<T>();
+          Result = APValue(V1.toAPSInt(), V2.toAPSInt());
+          return true;
+        });
+      } else if (ElemTy->isFloatingType()) {
+        Result = APValue(Ptr.atIndex(0).deref<Floating>().getAPFloat(),
+                         Ptr.atIndex(1).deref<Floating>().getAPFloat());
+        return true;
+      }
+      return false;
+    }
     llvm_unreachable("invalid value to return");
   };
 

diff  --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp
new file mode 100644
index 00000000000000..4fd2b5cfd73640
--- /dev/null
+++ b/clang/test/AST/Interp/complex.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
+// RUN: %clang_cc1 -verify=ref %s
+
+// expected-no-diagnostics
+// ref-no-diagnostics
+
+constexpr _Complex double z1 = {1.0, 2.0};
+static_assert(__real(z1) == 1.0, "");
+static_assert(__imag(z1) == 2.0, "");
+
+constexpr double setter() {
+  _Complex float d = {1.0, 2.0};
+
+  __imag(d) = 4.0;
+  return __imag(d);
+}
+static_assert(setter() == 4, "");
+
+constexpr _Complex double getter() {
+  return {1.0, 3.0};
+}
+constexpr _Complex double D = getter();
+static_assert(__real(D) == 1.0, "");
+static_assert(__imag(D) == 3.0, "");
+
+
+constexpr _Complex int I1 = {1, 2};
+static_assert(__real(I1) == 1, "");
+static_assert(__imag(I1) == 2, "");
+
+
+/// FIXME: This should work in the new interpreter as well.
+// constexpr _Complex _BitInt(8) A = 0;// = {4};


        


More information about the cfe-commits mailing list