tbaeder updated this revision to Diff 541318. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D155356/new/
https://reviews.llvm.org/D155356 Files: clang/lib/AST/Interp/InterpBuiltin.cpp clang/test/AST/Interp/builtin-functions.cpp
Index: clang/test/AST/Interp/builtin-functions.cpp =================================================================== --- clang/test/AST/Interp/builtin-functions.cpp +++ clang/test/AST/Interp/builtin-functions.cpp @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter %s -verify // RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated +// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter %s -verify +// RUN: %clang_cc1 -std=c++20 -verify=ref %s -Wno-constant-evaluated + namespace strcmp { constexpr char kFoobar[6] = {'f','o','o','b','a','r'}; @@ -34,3 +37,9 @@ // ref-error {{not an integral constant}} \ // ref-note {{dereferenced one-past-the-end}} } + +namespace nan { + constexpr double NaN1 = __builtin_nan(""); + + constexpr float Nan2 = __builtin_nans([](){return "0xAE98";}()); // ref-error {{must be initialized by a constant expression}} +} Index: clang/lib/AST/Interp/InterpBuiltin.cpp =================================================================== --- clang/lib/AST/Interp/InterpBuiltin.cpp +++ clang/lib/AST/Interp/InterpBuiltin.cpp @@ -9,6 +9,7 @@ #include "Interp.h" #include "PrimType.h" #include "clang/Basic/Builtins.h" +#include "clang/Basic/TargetInfo.h" namespace clang { namespace interp { @@ -57,6 +58,64 @@ return true; } +static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, const Function *F, + bool Signaling) { + const Pointer &Arg = getParam<Pointer>(Frame, 0); + + if (!CheckLoad(S, OpPC, Arg)) + return false; + + assert(Arg.getFieldDesc()->isPrimitiveArray()); + + // Convert the given string to an integer using StringRef's API. + llvm::APInt Fill; + std::string Str; + assert(Arg.getNumElems() >= 1); + for (unsigned I = 0, E = Arg.getNumElems() - 1; I != E; ++I) { + const Pointer &Elem = Arg.atIndex(I); + + if (!CheckLoad(S, OpPC, Elem)) + return false; + + Str += Elem.deref<char>(); + } + + // Treat empty strings as if they were zero. + if (Str.empty()) + Fill = llvm::APInt(32, 0); + else if (StringRef(Str).getAsInteger(0, Fill)) + return false; + + const llvm::fltSemantics &TargetSemantics = + S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType()); + + Floating Result; + if (S.getCtx().getTargetInfo().isNan2008()) { + if (Signaling) + Result = Floating( + llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill)); + else + Result = Floating( + llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill)); + } else { + // Prior to IEEE 754-2008, architectures were allowed to choose whether + // the first bit of their significand was set for qNaN or sNaN. MIPS chose + // a different encoding to what became a standard in 2008, and for pre- + // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as + // sNaN. This is now known as "legacy NaN" encoding. + if (Signaling) + Result = Floating( + llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill)); + else + Result = Floating( + llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill)); + } + + S.Stk.push<Floating>(Result); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F) { InterpFrame *Frame = S.Current; APValue Dummy; @@ -70,7 +129,24 @@ case Builtin::BI__builtin_strcmp: if (interp__builtin_strcmp(S, OpPC, Frame)) return Ret<PT_Sint32>(S, OpPC, Dummy); - return false; + break; + case Builtin::BI__builtin_nan: + case Builtin::BI__builtin_nanf: + 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)) + return Ret<PT_Float>(S, OpPC, Dummy); + break; + case Builtin::BI__builtin_nans: + case Builtin::BI__builtin_nansf: + 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)) + return Ret<PT_Float>(S, OpPC, Dummy); + break; + default: return false; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits