summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2024-02-01 07:13:10 +0100
committerGitHub <noreply@github.com>2024-02-01 07:13:10 +0100
commit6ff431b01e29e99c7dbfcda96bdefdff91dcdf7f (patch)
treee9befca72327abe4dab731def19d9c823c3f1859
parent5d9ffcd7f8e47ab1e15e8f7f23784b639544a7e9 (diff)
[clang][Interp] Handle imaginary literals (#79130)
Initialize the first element to 0 and the second element to the value of the subexpression.
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.cpp26
-rw-r--r--clang/lib/AST/Interp/ByteCodeExprGen.h1
-rw-r--r--clang/lib/AST/Interp/Context.cpp8
-rw-r--r--clang/test/AST/Interp/complex.cpp8
4 files changed, 40 insertions, 3 deletions
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d307739c301e..c0721b0daf9a 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -394,6 +394,31 @@ bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
}
template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitImaginaryLiteral(
+ const ImaginaryLiteral *E) {
+ assert(E->getType()->isAnyComplexType());
+ if (DiscardResult)
+ return true;
+
+ if (!Initializing) {
+ std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/false);
+ if (!LocalIndex)
+ return false;
+ if (!this->emitGetPtrLocal(*LocalIndex, E))
+ return false;
+ }
+
+ const Expr *SubExpr = E->getSubExpr();
+ PrimType SubExprT = classifyPrim(SubExpr->getType());
+
+ if (!this->visitZeroInitializer(SubExprT, SubExpr->getType(), SubExpr))
+ return false;
+ if (!this->emitInitElem(SubExprT, 0, SubExpr))
+ return false;
+ return this->visitArrayElemInit(1, SubExpr);
+}
+
+template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *E) {
return this->delegate(E->getSubExpr());
}
@@ -2883,6 +2908,7 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return false;
return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
}
+
if (!this->visit(SubExpr))
return false;
if (!this->emitConstUint8(1, E))
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 315169d487cd..971fd09bdfac 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -61,6 +61,7 @@ public:
bool VisitCastExpr(const CastExpr *E);
bool VisitIntegerLiteral(const IntegerLiteral *E);
bool VisitFloatingLiteral(const FloatingLiteral *E);
+ bool VisitImaginaryLiteral(const ImaginaryLiteral *E);
bool VisitParenExpr(const ParenExpr *E);
bool VisitBinaryOperator(const BinaryOperator *E);
bool VisitLogicalBinOp(const BinaryOperator *E);
diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index ba80a015965b..5f5a6622f10f 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -111,11 +111,13 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
#endif
// Ensure global variables are fully initialized.
- if (shouldBeGloballyIndexed(VD) && !Res.isInvalid() &&
- (VD->getType()->isRecordType() || VD->getType()->isArrayType())) {
+ if (shouldBeGloballyIndexed(VD) &&
+ (VD->getType()->isRecordType() || VD->getType()->isArrayType() ||
+ VD->getType()->isAnyComplexType())) {
assert(Res.isLValue());
- if (!Res.checkFullyInitialized(C.getState()))
+ if (!VD->getType()->isAnyComplexType() &&
+ !Res.checkFullyInitialized(C.getState()))
return false;
// lvalue-to-rvalue conversion.
diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp
index bb230c2ebe64..fdd1d738de82 100644
--- a/clang/test/AST/Interp/complex.cpp
+++ b/clang/test/AST/Interp/complex.cpp
@@ -61,6 +61,14 @@ static_assert(__real(D3) == 1.0, "");
static_assert(__imag(D3) == 3.0, "");
+constexpr _Complex int a = 2i;
+static_assert(__real(a) == 0, "");
+static_assert(__imag(a) == 2, "");
+
+constexpr _Complex double b = 4.0i;
+static_assert(__real(b) == 0, "");
+static_assert(__imag(b) == 4, "");
+
constexpr int ignored() {
I2;
(int)I2;