diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index b4110d5856d51..efe10458f7790 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -2730,6 +2730,18 @@ bool ByteCodeExprGen::VisitBuiltinCallExpr(const CallExpr *E) { if (!Func) return false; + QualType ReturnType = E->getType(); + std::optional ReturnT = classify(E); + + // Non-primitive return type. Prepare storage. + if (!Initializing && !ReturnT && !ReturnType->isVoidType()) { + std::optional LocalIndex = allocateLocal(E, /*IsExtended=*/false); + if (!LocalIndex) + return false; + if (!this->emitGetPtrLocal(*LocalIndex, E)) + return false; + } + if (!Func->isUnevaluatedBuiltin()) { // Put arguments on the stack. for (const auto *Arg : E->arguments()) { @@ -2741,10 +2753,9 @@ bool ByteCodeExprGen::VisitBuiltinCallExpr(const CallExpr *E) { if (!this->emitCallBI(Func, E, E)) return false; - QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); if (DiscardResult && !ReturnType->isVoidType()) { - PrimType T = classifyPrim(ReturnType); - return this->emitPop(T, E); + assert(ReturnT); + return this->emitPop(*ReturnT, E); } return true; diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index cc457ce41af59..5250d02be85a6 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -900,6 +900,25 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, return false; } +/// __builtin_complex(Float A, float B); +static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + const Floating &Arg2 = S.Stk.peek(); + const Floating &Arg1 = S.Stk.peek(align(primSize(PT_Float)) * 2); + Pointer &Result = S.Stk.peek(align(primSize(PT_Float)) * 2 + + align(primSize(PT_Ptr))); + + Result.atIndex(0).deref() = Arg1; + Result.atIndex(0).initialize(); + Result.atIndex(1).deref() = Arg2; + Result.atIndex(1).initialize(); + Result.initialize(); + + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { InterpFrame *Frame = S.Current; @@ -907,9 +926,6 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, std::optional ReturnT = S.getContext().classify(Call); - // If classify failed, we assume void. - assert(ReturnT || Call->getType()->isVoidType()); - switch (F->getBuiltinID()) { case Builtin::BI__builtin_is_constant_evaluated: S.Stk.push(Boolean::from(S.inConstantContext())); @@ -1206,6 +1222,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_complex: + if (!interp__builtin_complex(S, OpPC, Frame, F, Call)) + return false; + break; + default: S.FFDiag(S.Current->getLocation(OpPC), diag::note_invalid_subexpr_in_const_expr) diff --git a/clang/test/AST/Interp/complex.cpp b/clang/test/AST/Interp/complex.cpp index b6091d90867a0..8acce7b734d85 100644 --- a/clang/test/AST/Interp/complex.cpp +++ b/clang/test/AST/Interp/complex.cpp @@ -1,8 +1,5 @@ -// 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 +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected -Wno-unused-value %s +// RUN: %clang_cc1 -verify=both,ref -Wno-unused-value %s constexpr _Complex double z1 = {1.0, 2.0}; static_assert(__real(z1) == 1.0, ""); @@ -256,3 +253,16 @@ namespace DeclRefCopy { } static_assert(localComplexArray() == (24 + 42), ""); } + +namespace Builtin { + constexpr _Complex float A = __builtin_complex(10.0f, 20.0f); + static_assert(__real(A) == 10, ""); + static_assert(__imag(A) == 20, ""); + + constexpr _Complex double B = __builtin_complex(10.0, 20.0); + static_assert(__real(B) == 10, ""); + static_assert(__imag(B) == 20, ""); + + + constexpr _Complex float C = __builtin_complex(10.0f, 20.0); // both-error {{arguments are of different types}} +}