diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 6d84bd03de810..e8c8b6235b604 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -2036,6 +2036,10 @@ class FunctionDecl : public DeclaratorDecl, /// the DeclaratorDecl base class. DeclarationNameLoc DNLoc; + /// Represents the language version since this function has been declared + /// constexpr. + clang::LangStandard::Kind ConstexprSinceVersion; + /// Specify that this function declaration is actually a function /// template specialization. /// @@ -2151,6 +2155,20 @@ class FunctionDecl : public DeclaratorDecl, void setDeclarationNameLoc(DeclarationNameLoc L) { DNLoc = L; } + /// Set the language standard version at which this builtin became constexpr. + void setConstexprBuiltinSinceVersion(IdentifierInfo *builtinIdentifier); + + /// Get the language standard version at which this builtin became constexpr. + clang::LangStandard::Kind getConstexprBuiltinSinceVersion() const { + return ConstexprSinceVersion; + } + + /// Set the version of the language standard at which this declaration became + /// constexpr. + void setConstexprSinceVersion(clang::LangStandard::Kind LangVersion) { + ConstexprSinceVersion = LangVersion; + } + /// Returns the location of the ellipsis of a variadic function. SourceLocation getEllipsisLoc() const { const auto *FPT = getType()->getAs(); diff --git a/clang/include/clang/Basic/Builtins.h b/clang/include/clang/Basic/Builtins.h index e85ec5b2dca14..a00efed2f126c 100644 --- a/clang/include/clang/Basic/Builtins.h +++ b/clang/include/clang/Basic/Builtins.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_BASIC_BUILTINS_H #define LLVM_CLANG_BASIC_BUILTINS_H +#include "LangStandard.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -74,6 +75,7 @@ struct Info { const char *Features; HeaderDesc Header; LanguageID Langs; + LangStandard UnprefixedOnlyConstexprSince; }; /// Holds information about both target-independent and @@ -161,6 +163,12 @@ class Context { return strchr(getRecord(ID).Attributes, 'f') != nullptr; } + clang::LangStandard::Kind isBuiltinConstant(unsigned ID) const { + return strchr(getRecord(ID).Attributes, 'O') != nullptr + ? LangStandard::lang_cxx23 + : LangStandard::lang_cxx20; // Not constexpr + } + /// Returns true if this builtin requires appropriate header in other /// compilers. In Clang it will work even without including it, but we can emit /// a warning about missing header. @@ -277,7 +285,8 @@ class Context { /// Return true if this function can be constant evaluated by Clang frontend. bool isConstantEvaluated(unsigned ID) const { - return strchr(getRecord(ID).Attributes, 'E') != nullptr; + return (strchr(getRecord(ID).Attributes, 'E') != nullptr || + strchr(getRecord(ID).Attributes, 'O') != nullptr); } /// Returns true if this is an immediate (consteval) function diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index ac33672a32b33..2b61ea39824dd 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -253,8 +253,9 @@ def FmodF16F128 : F16F128MathTemplate, Builtin { def FrexpF16F128 : F16F128MathTemplate, Builtin { let Spellings = ["__builtin_frexp"]; - let Attributes = [FunctionWithBuiltinPrefix, NoThrow]; + let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Constexpr]; let Prototype = "T(T, int*)"; + let BuiltinPrefixedAliasIsConstexpr = 1; } def HugeVal : Builtin, FPMathWithF128Template { @@ -3463,7 +3464,7 @@ def Copysign : FPMathTemplate, LibBuiltin<"math.h"> { let Attributes = [NoThrow, Const]; let Prototype = "T(T, T)"; let AddBuiltinPrefixedAlias = 1; - let OnlyBuiltinPrefixedAliasIsConstexpr = 1; + let BuiltinPrefixedAliasIsConstexpr = 1; } def Fabs : FPMathTemplate, LibBuiltin<"math.h"> { @@ -3471,7 +3472,7 @@ def Fabs : FPMathTemplate, LibBuiltin<"math.h"> { let Attributes = [NoThrow, Const]; let Prototype = "T(T)"; let AddBuiltinPrefixedAlias = 1; - let OnlyBuiltinPrefixedAliasIsConstexpr = 1; + let BuiltinPrefixedAliasIsConstexpr = 1; } def Finite : FPMathTemplate, GNULibBuiltin<"math.h"> { @@ -3496,9 +3497,10 @@ def Fmod : FPMathTemplate, LibBuiltin<"math.h"> { def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["frexp"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; let Prototype = "T(T, int*)"; let AddBuiltinPrefixedAlias = 1; + let BuiltinPrefixedAliasIsConstexpr = 1; } def Ldexp : FPMathTemplate, LibBuiltin<"math.h"> { @@ -3520,7 +3522,7 @@ def Nan : FPMathTemplate, LibBuiltin<"math.h"> { let Attributes = [Pure, NoThrow]; let Prototype = "T(char const*)"; let AddBuiltinPrefixedAlias = 1; - let OnlyBuiltinPrefixedAliasIsConstexpr = 1; + let BuiltinPrefixedAliasIsConstexpr = 1; } def Pow : FPMathTemplate, LibBuiltin<"math.h"> { @@ -3666,18 +3668,18 @@ def Fma : FPMathTemplate, LibBuiltin<"math.h"> { def Fmax : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["fmax"]; - let Attributes = [NoThrow, Const]; + let Attributes = [NoThrow, Const, Constexpr]; let Prototype = "T(T, T)"; let AddBuiltinPrefixedAlias = 1; - let OnlyBuiltinPrefixedAliasIsConstexpr = 1; + let BuiltinPrefixedAliasIsConstexpr = 1; } def Fmin : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["fmin"]; - let Attributes = [NoThrow, Const]; + let Attributes = [NoThrow, Const, Constexpr]; let Prototype = "T(T, T)"; let AddBuiltinPrefixedAlias = 1; - let OnlyBuiltinPrefixedAliasIsConstexpr = 1; + let BuiltinPrefixedAliasIsConstexpr = 1; } def Hypot : FPMathTemplate, LibBuiltin<"math.h"> { diff --git a/clang/include/clang/Basic/BuiltinsBase.td b/clang/include/clang/Basic/BuiltinsBase.td index 58dee22fc0a45..a5461c0a70057 100644 --- a/clang/include/clang/Basic/BuiltinsBase.td +++ b/clang/include/clang/Basic/BuiltinsBase.td @@ -84,6 +84,7 @@ class Builtin { // On some platforms, some functions are actually macros. In that case we need // to #undef them. bit RequiresUndef = 0; + bit BuiltinPrefixedAliasIsConstexpr = 0; } class CustomEntry { @@ -99,7 +100,7 @@ class LibBuiltin : Builtin { string Header = header; string Languages = languages; bit AddBuiltinPrefixedAlias = 0; - bit OnlyBuiltinPrefixedAliasIsConstexpr = 0; + bit BuiltinPrefixedAliasIsConstexpr = 0; } class MSLibBuiltin : LibBuiltin; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 90caf81757ac9..7a8b9ede17a7e 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -71,6 +71,7 @@ #include #include #include +#include using namespace clang; @@ -3066,6 +3067,25 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, setTrailingRequiresClause(TrailingRequiresClause); } +void FunctionDecl::setConstexprBuiltinSinceVersion(IdentifierInfo *I) { + const std::unordered_set ConstexprFunctions = { + "__builtin_fmax", "__builtin_fmaxf", "__builtin_fmaxl", + "__builtin_fmin", "__builtin_fminf", "__builtin_fminl"}; + const std::unordered_set ConstexprFunctionsFrexp = { + "__builtin_frexp", "__builtin_frexpf", "__builtin_frexpl", + "__builtin_frexpf16", "__builtin_frexpf128"}; + std::string BuiltinName = I->getName().str(); + if (ConstexprFunctions.count(BuiltinName)) { + setConstexprSinceVersion(getLangOpts().CPlusPlus23 + ? LangStandard::lang_cxx23 + : getLangOpts().LangStd); + } else if (ConstexprFunctionsFrexp.count(BuiltinName)) { + setConstexprSinceVersion(LangStandard::lang_cxx23); + } else { + setConstexprSinceVersion(getLangOpts().LangStd); + } +} + void FunctionDecl::getNameForDiagnostic( raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 826cc5f58bdf5..ede8c5851415e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14942,6 +14942,16 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, return true; } +// Checks that the value x is in the range (-1;-0.5], [0.5; 1) +static bool isInFrexpResultRange(const llvm::APFloat &x) { + llvm::APFloat AbsX = abs(x); + + llvm::APFloat half(x.getSemantics(), "0.5"); + llvm::APFloat one(x.getSemantics(), "1.0"); + + return (AbsX.compare(half) != llvm::APFloat::cmpLessThan && + AbsX.compare(one) == llvm::APFloat::cmpLessThan); +} bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { if (!IsConstantEvaluatedBuiltinCall(E)) @@ -14951,6 +14961,36 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { default: return false; + case Builtin::BIfrexp: + case Builtin::BIfrexpf: + case Builtin::BIfrexpl: + case Builtin::BI__builtin_frexp: + case Builtin::BI__builtin_frexpf: + case Builtin::BI__builtin_frexpl: + case Builtin::BI__builtin_frexpf16: + case Builtin::BI__builtin_frexpf128: { + const auto *FDecl = E->getDirectCallee(); + clang::LangStandard::Kind ConstExprSinceVersion = + FDecl->getConstexprBuiltinSinceVersion(); + if (ConstExprSinceVersion > Info.Ctx.getLangOpts().LangStd) + return false; + LValue Pointer; + if (!EvaluateFloat(E->getArg(0), Result, Info) || + !EvaluatePointer(E->getArg(1), Pointer, Info)) + return false; + int FrexpExp; + llvm::RoundingMode RM = getActiveRoundingMode(Info, E); + Result = llvm::frexp(Result, FrexpExp, RM); + assert((Result.isZero() || Result.isNaN() || Result.isInfinity() || + isInFrexpResultRange(Result)) && + "The value is not in the expected range for frexp."); + APValue ExpVal{Result}; + if (!handleAssignment(Info, E, Pointer, + E->getArg(1)->getType()->getPointeeType(), ExpVal)) + return false; + return true; + } + case Builtin::BI__builtin_huge_val: case Builtin::BI__builtin_huge_valf: case Builtin::BI__builtin_huge_vall: @@ -15024,12 +15064,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmax: + case Builtin::BIfmaxf: + case Builtin::BIfmaxl: case Builtin::BI__builtin_fmax: case Builtin::BI__builtin_fmaxf: case Builtin::BI__builtin_fmaxl: case Builtin::BI__builtin_fmaxf16: case Builtin::BI__builtin_fmaxf128: { // TODO: Handle sNaN. + const auto *FDecl = E->getDirectCallee(); + clang::LangStandard::Kind ConstExprSinceVersion = + FDecl->getConstexprBuiltinSinceVersion(); + if (ConstExprSinceVersion > Info.Ctx.getLangOpts().LangStd) + return false; APFloat RHS(0.); if (!EvaluateFloat(E->getArg(0), Result, Info) || !EvaluateFloat(E->getArg(1), RHS, Info)) @@ -15042,12 +15090,20 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) { return true; } + case Builtin::BIfmin: + case Builtin::BIfminf: + case Builtin::BIfminl: case Builtin::BI__builtin_fmin: case Builtin::BI__builtin_fminf: case Builtin::BI__builtin_fminl: case Builtin::BI__builtin_fminf16: case Builtin::BI__builtin_fminf128: { // TODO: Handle sNaN. + const auto *FDecl = E->getDirectCallee(); + clang::LangStandard::Kind ConstExprSinceVersion = + FDecl->getConstexprBuiltinSinceVersion(); + if (ConstExprSinceVersion > Info.Ctx.getLangOpts().LangStd) + return false; APFloat RHS(0.); if (!EvaluateFloat(E->getArg(0), Result, Info) || !EvaluateFloat(E->getArg(1), RHS, Info)) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b0ccbbe34b70c..9c98ac0530a91 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2308,6 +2308,7 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, Type->isFunctionProtoType(), ConstexprKind); New->setImplicit(); New->addAttr(BuiltinAttr::CreateImplicit(Context, ID)); + New->setConstexprBuiltinSinceVersion(II); // Create Decl objects for each parameter, adding them to the // FunctionDecl. diff --git a/clang/test/CodeGenCXX/constexpr-math.cpp b/clang/test/CodeGenCXX/constexpr-math.cpp new file mode 100644 index 0000000000000..a6bcfd43d2b9b --- /dev/null +++ b/clang/test/CodeGenCXX/constexpr-math.cpp @@ -0,0 +1,121 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4 + +// RUN: %clang_cc1 -x c++ -triple x86_64-unknown-unknown -std=c++23 \ +// RUN: -emit-llvm -o - %s | FileCheck %s + +// RUN: %clang_cc1 -emit-llvm -triple powerpc64-unknown-unknown \ +// RUN: -DFLOAT128 -target-feature +float128 -std=c++23 %s -o - \ +// RUN: | FileCheck -check-prefix=FLOAT128 %s + +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) + +#if !defined(FLOAT128) +// CHECK-LABEL: define dso_local noundef i32 @_Z4funcv( +// CHECK-SAME: ) #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: entry: +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[MIN1:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[MIN2:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[MIN3:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[MIN4:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MIN5:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MIN6:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MIN7:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MIN8:%.*]] = alloca x86_fp80, align 16 +// CHECK-NEXT: [[MAX1:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[MAX2:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[MAX3:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[MAX4:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MAX5:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MAX6:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MAX7:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[MAX8:%.*]] = alloca x86_fp80, align 16 +// CHECK-NEXT: [[FREXP1:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[FREXP2:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[FREXP3:%.*]] = alloca double, align 8 +// CHECK-NEXT: [[FREXP4:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[FREXP5:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[FREXP6:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[FREXP7:%.*]] = alloca float, align 4 +// CHECK-NEXT: [[FREXP8:%.*]] = alloca x86_fp80, align 16 +// CHECK-NEXT: [[FREXP9:%.*]] = alloca half, align 2 +// CHECK-NEXT: store double 1.300000e+00, ptr [[MIN1]], align 8 +// CHECK-NEXT: store double -0.000000e+00, ptr [[MIN2]], align 8 +// CHECK-NEXT: store double -0.000000e+00, ptr [[MIN3]], align 8 +// CHECK-NEXT: store float 0x7FF8000000000000, ptr [[MIN4]], align 4 +// CHECK-NEXT: store float -1.000000e+00, ptr [[MIN5]], align 4 +// CHECK-NEXT: store float 0xFFF0000000000000, ptr [[MIN6]], align 4 +// CHECK-NEXT: store float 0.000000e+00, ptr [[MIN7]], align 4 +// CHECK-NEXT: store x86_fp80 0xK4005F6E978D4FDF3B646, ptr [[MIN8]], align 16 +// CHECK-NEXT: store double 1.524000e+01, ptr [[MAX1]], align 8 +// CHECK-NEXT: store double 0.000000e+00, ptr [[MAX2]], align 8 +// CHECK-NEXT: store double 0.000000e+00, ptr [[MAX3]], align 8 +// CHECK-NEXT: store float -1.000000e+00, ptr [[MAX4]], align 4 +// CHECK-NEXT: store float 0x7FF0000000000000, ptr [[MAX5]], align 4 +// CHECK-NEXT: store float 0.000000e+00, ptr [[MAX6]], align 4 +// CHECK-NEXT: store float 0x7FF8000000000000, ptr [[MAX7]], align 4 +// CHECK-NEXT: store x86_fp80 0xK4008C540C49BA5E353F8, ptr [[MAX8]], align 16 +// CHECK-NEXT: store double 0x3FEEDCCCCCCCCCCD, ptr [[FREXP1]], align 8 +// CHECK-NEXT: store double 0.000000e+00, ptr [[FREXP2]], align 8 +// CHECK-NEXT: store double -0.000000e+00, ptr [[FREXP3]], align 8 +// CHECK-NEXT: store float 0x7FF8000000000000, ptr [[FREXP4]], align 4 +// CHECK-NEXT: store float 0xFFF8000000000000, ptr [[FREXP5]], align 4 +// CHECK-NEXT: store float 0x7FF0000000000000, ptr [[FREXP6]], align 4 +// CHECK-NEXT: store float 0xFFF0000000000000, ptr [[FREXP7]], align 4 +// CHECK-NEXT: store x86_fp80 0xK3FFE81A9FBE76C8B4396, ptr [[FREXP8]], align 16 +// CHECK-NEXT: store half 0xH3B00, ptr [[FREXP9]], align 2 +// CHECK-NEXT: ret i32 0 +// +int func() +{ + int i; + + // fmin + constexpr double min1 = __builtin_fmin(15.24, 1.3); + constexpr double min2 = __builtin_fmin(-0.0, +0.0); + constexpr double min3 = __builtin_fmin(+0.0, -0.0); + constexpr float min4 = __builtin_fminf(NAN, NAN); + constexpr float min5 = __builtin_fminf(NAN, -1); + constexpr float min6 = __builtin_fminf(-INFINITY, 0); + constexpr float min7 = __builtin_fminf(INFINITY, 0); + constexpr long double min8 = __builtin_fminl(123.456L, 789.012L); + + // fmax + constexpr double max1 = __builtin_fmax(15.24, 1.3); + constexpr double max2 = __builtin_fmax(-0.0, +0.0); + constexpr double max3 = __builtin_fmax(+0.0, -0.0); + constexpr float max4 = __builtin_fmaxf(NAN, -1); + constexpr float max5 = __builtin_fmaxf(+INFINITY, 0); + constexpr float max6 = __builtin_fmaxf(-INFINITY, 0); + constexpr float max7 = __builtin_fmaxf(NAN, NAN); + constexpr long double max8 = __builtin_fmaxl(123.456L, 789.012L); + + // frexp + constexpr double frexp1 = __builtin_frexp(123.45, (int [1]){}); + constexpr double frexp2 = __builtin_frexp(0.0, (int [1]){}); + constexpr double frexp3 = __builtin_frexp(-0.0, (int [1]){}); + constexpr float frexp4 = __builtin_frexpf(NAN, (int [1]){}); + constexpr float frexp5 = __builtin_frexpf(-NAN, (int [1]){}); + constexpr float frexp6 = __builtin_frexpf(+INFINITY, (int [1]){}); + constexpr float frexp7 = __builtin_frexpf(-INFINITY, (int [1]){}); + constexpr long double frexp8 = __builtin_frexpl(259.328L, (int [1]){}); + constexpr __fp16 frexp9 = __builtin_frexpf16(3.5, (int [1]){}); + return 0; +} +#elif FLOAT128 +// FLOAT128-LABEL: define dso_local noundef signext i32 @_Z9func_f128v( +// FLOAT128-SAME: ) #[[ATTR0:[0-9]+]] { +// FLOAT128-NEXT: entry: +// FLOAT128-NEXT: [[I:%.*]] = alloca i32, align 4 +// FLOAT128-NEXT: [[FREXP10:%.*]] = alloca fp128, align 16 +// FLOAT128-NEXT: store fp128 0xL90000000000000003FFED58F5C28F5C2, ptr [[FREXP10]], align 16 +// FLOAT128-NEXT: ret i32 0 +// +int func_f128() { + int i; + constexpr __float128 frexp10 = __builtin_frexpf128(234.78, (int [1]){}); // expected-error {{__float128 is not supported on this target}} + + return 0; +} +#endif diff --git a/clang/test/SemaCXX/constexpr-math.cpp b/clang/test/SemaCXX/constexpr-math.cpp new file mode 100644 index 0000000000000..95ceb53e05a9c --- /dev/null +++ b/clang/test/SemaCXX/constexpr-math.cpp @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 -DWIN -verify=nan-not-constant -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify -std=c++23 -fsyntax-only %s +// RUN: %clang_cc1 -verify=cplusplus20andless -std=c++20 -fsyntax-only %s + +// expected-no-diagnostics + + +#ifdef WIN +#define INFINITY ((float)(1e+300 * 1e+300)) +#define NAN (-(float)(INFINITY * 0.0F)) +#else +#define NAN (__builtin_nanf("")) +#define INFINITY (__builtin_inff()) +#endif + +template constexpr bool is_same_val = false; +template constexpr bool is_same_val = true; + +extern "C" { + double fmin(double, double); + float fminf(float, float); + long double fminl(long double, long double); + + double fmax(double, double); + float fmaxf(float, float); + long double fmaxl(long double, long double); + + double frexp(double, int*); + float frexpf(float, int*); + long double frexpl(long double, int*); +} + +#if __cplusplus <= 202002L +#define CALL_BUILTIN(BASE_NAME, ...) __builtin_##BASE_NAME(__VA_ARGS__) +#else +#define CALL_BUILTIN(BASE_NAME, ...) BASE_NAME(__VA_ARGS__) +#endif + +int main() { + int i; + + // fmin + static_assert(is_same_val); + static_assert(is_same_val); + static_assert(is_same_val); + static_assert(is_same_val); + // nan-not-constant-error@-1 {{non-type template argument is not a constant expression}} + // nan-not-constant-note@-2 {{floating point arithmetic produces a NaN}} + static_assert(is_same_val); + static_assert(is_same_val); + static_assert(is_same_val); + // nan-not-constant-error@-1 {{non-type template argument is not a constant expression}} + // nan-not-constant-note@-2 {{floating point arithmetic produces a NaN}} + static_assert(is_same_val); + + static_assert(is_same_val); + static_assert(is_same_val); + static_assert(is_same_val); + static_assert(is_same_val); + // nan-not-constant-error@-1 {{non-type template argument is not a constant expression}} + // nan-not-constant-note@-2 {{floating point arithmetic produces a NaN}} + static_assert(is_same_val); + static_assert(is_same_val); + static_assert(is_same_val); + // nan-not-constant-error@-1 {{non-type template argument is not a constant expression}} + // nan-not-constant-note@-2 {{floating point arithmetic produces a NaN}} + static_assert(is_same_val); + + // frexp + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // nan-not-constant-error@-1 {{non-type template argument is not a constant expression}} + // nan-not-constant-note@-2 {{floating point arithmetic produces a NaN}} + // cplusplus20andless-error@-3 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // nan-not-constant-error@-1 {{non-type template argument is not a constant expression}} + // nan-not-constant-note@-2 {{floating point arithmetic produces a NaN}} + // cplusplus20andless-error@-3 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + static_assert(is_same_val); + // cplusplus20andless-error@-1 {{non-type template argument is not a constant expression}} + + return 0; +} diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp index 94f12a08164fd..43e4a25baaed0 100644 --- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp +++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp @@ -222,7 +222,7 @@ void PrintAttributes(const Record *Builtin, BuiltinType BT, OS << 'f'; } else { OS << 'F'; - if (Builtin->getValueAsBit("OnlyBuiltinPrefixedAliasIsConstexpr")) + if (Builtin->getValueAsBit("BuiltinPrefixedAliasIsConstexpr")) OS << 'E'; } }