[clang] 88abd53 - [clang][Interp] Allow evaluating standalone complex expressions

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 14 06:24:03 PST 2023


Author: Timm Bäder
Date: 2023-12-14T15:07:42+01:00
New Revision: 88abd530ef8e66ba4275146ffba028aa8923bf7f

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

LOG: [clang][Interp] Allow evaluating standalone complex expressions

We reach visitExpr() when evaluating standalone expressions. However,
the RetValue() code path was unused before, because we never reach it,
even with structs or arrays.

RetValue expects a pointer on the stack it can take apart to return an
APValue, so provide it with one.

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index fdc84d0a0da005..080b7e896a8201 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2180,15 +2180,33 @@ const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) {
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
   ExprScope<Emitter> RootScope(this);
-  if (!visit(E))
-    return false;
-
-  if (E->getType()->isVoidType())
+  // Void expressions.
+  if (E->getType()->isVoidType()) {
+    if (!visit(E))
+      return false;
     return this->emitRetVoid(E);
+  }
 
-  if (std::optional<PrimType> T = classify(E))
+  // Expressions with a primitive return type.
+  if (std::optional<PrimType> T = classify(E)) {
+    if (!visit(E))
+      return false;
     return this->emitRet(*T, E);
-  return this->emitRetValue(E);
+  }
+
+  // Expressions with a composite return type.
+  // For us, that means everything we don't
+  // have a PrimType for.
+  if (std::optional<unsigned> LocalOffset = this->allocateLocal(E)) {
+    if (!this->visitLocalInitializer(E, *LocalOffset))
+      return false;
+
+    if (!this->emitGetPtrLocal(*LocalOffset, E))
+      return false;
+    return this->emitRetValue(E);
+  }
+
+  return false;
 }
 
 /// Toplevel visitDecl().
@@ -2644,7 +2662,14 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
       return false;
     if (!this->emitConstUint8(0, E))
       return false;
-    return this->emitArrayElemPtrPopUint8(E);
+    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;
   }
   case UO_Imag: { // __imag x
     assert(!T);
@@ -2652,7 +2677,14 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
       return false;
     if (!this->emitConstUint8(1, E))
       return false;
-    return this->emitArrayElemPtrPopUint8(E);
+    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;
   }
   case UO_Extension:
     return this->delegate(SubExpr);

diff  --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp
index 084a63d4701c23..1eb70a1b9ce3b4 100644
--- a/clang/test/AST/Interp/complex.cpp
+++ b/clang/test/AST/Interp/complex.cpp
@@ -38,6 +38,10 @@ static_assert(__real(I2) == 0, "");
 static_assert(__imag(I2) == 0, "");
 
 
+/// Standalone complex expressions.
+static_assert(__real((_Complex float){1.0, 3.0}) == 1.0, "");
+
+
 #if 0
 /// FIXME: This should work in the new interpreter.
 constexpr _Complex double D2 = {12};


        


More information about the cfe-commits mailing list