Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1906,7 +1906,7 @@ return false; } - if (!this->emitCallBI(Func, E)) + if (!this->emitCallBI(Func, E, E)) return false; QualType ReturnType = E->getCallReturnType(Ctx.getASTContext()); Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -180,7 +180,8 @@ bool Interpret(InterpState &S, APValue &Result); /// Interpret a builtin function. -bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F); +bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, + const CallExpr *Call); /// Perform a bitcast of all fields of P into Buff. This performs the /// actions of a __builtin_bit_cast expression when the target type @@ -1843,13 +1844,14 @@ return Call(S, OpPC, Func); } -inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func) { +inline bool CallBI(InterpState &S, CodePtr &PC, const Function *Func, + const CallExpr *CE) { auto NewFrame = std::make_unique(S, Func, PC); InterpFrame *FrameBefore = S.Current; S.Current = NewFrame.get(); - if (InterpretBuiltin(S, PC, Func)) { + if (InterpretBuiltin(S, PC, Func, CE)) { NewFrame.release(); return true; } Index: clang/lib/AST/Interp/InterpBuiltin.cpp =================================================================== --- clang/lib/AST/Interp/InterpBuiltin.cpp +++ clang/lib/AST/Interp/InterpBuiltin.cpp @@ -73,7 +73,11 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, - bool Signaling) { + bool Signaling, const CallExpr *Call) { + + if (!isa(Call->getArg(0)->IgnoreParenCasts())) + return false; + const Pointer &Arg = getParam(Frame, 0); if (!CheckLoad(S, OpPC, Arg)) @@ -240,10 +244,9 @@ /// second one is an integral value. static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, - const Function *Func) { - const Expr *E = S.Current->getExpr(OpPC); - const CallExpr *CE = cast(E); - PrimType FPClassArgT = *S.getContext().classify(CE->getArgs()[1]->getType()); + const Function *Func, + const CallExpr *Call) { + PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType()); APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT); const Floating &F = S.Stk.peek(align(primSize(FPClassArgT) + primSize(PT_Float))); @@ -304,10 +307,9 @@ /// The return type must be the same. static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, - const Function *Func) { - const Expr *E = S.Current->getExpr(OpPC); - const CallExpr *CE = cast(E); - QualType ReturnType = CE->getType(); + const Function *Func, + const CallExpr *Call) { + QualType ReturnType = Call->getType(); // TODO: Support vector and complex types. if (!ReturnType->isFloatingType()) @@ -319,7 +321,8 @@ return true; } -bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F) { +bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, + const CallExpr *Call) { InterpFrame *Frame = S.Current; APValue Dummy; @@ -338,7 +341,7 @@ case Builtin::BI__builtin_nanl: case Builtin::BI__builtin_nanf16: case Builtin::BI__builtin_nanf128: - if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false)) + if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false, Call)) return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_nans: @@ -346,7 +349,7 @@ case Builtin::BI__builtin_nansl: case Builtin::BI__builtin_nansf16: case Builtin::BI__builtin_nansf128: - if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true)) + if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true, Call)) return Ret(S, OpPC, Dummy); break; @@ -413,7 +416,7 @@ return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_isfpclass: - if (interp__builtin_isfpclass(S, OpPC, Frame, F)) + if (interp__builtin_isfpclass(S, OpPC, Frame, F, Call)) return Ret(S, OpPC, Dummy); break; case Builtin::BI__builtin_fpclassify: @@ -430,7 +433,7 @@ break; case Builtin::BI__arithmetic_fence: - if (interp__builtin_arithmetic_fence(S, OpPC, Frame, F)) + if (interp__builtin_arithmetic_fence(S, OpPC, Frame, F, Call)) return Ret(S, OpPC, Dummy); break; Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -52,6 +52,7 @@ def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; } def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; } def ArgCastKind : ArgType { let Name = "CastKind"; } +def ArgCallExpr : ArgType { let Name = "const CallExpr *"; } //===----------------------------------------------------------------------===// // Classes of types instructions operate on. @@ -188,7 +189,7 @@ } def CallBI : Opcode { - let Args = [ArgFunction]; + let Args = [ArgFunction, ArgCallExpr]; let Types = []; } Index: clang/test/AST/Interp/builtin-functions.cpp =================================================================== --- clang/test/AST/Interp/builtin-functions.cpp +++ clang/test/AST/Interp/builtin-functions.cpp @@ -41,7 +41,9 @@ namespace nan { constexpr double NaN1 = __builtin_nan(""); - constexpr float Nan2 = __builtin_nans([](){return "0xAE98";}()); // ref-error {{must be initialized by a constant expression}} + constexpr float Nan2 = __builtin_nans([](){return "0xAE98";}()); // ref-error {{must be initialized by a constant expression}} \ + // expected-error {{must be initialized by a constant expression}} + } namespace inf {