diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9609,6 +9609,24 @@ return Success(N == Val.getBitWidth() ? 0 : N + 1, E); } + case Builtin::BI__builtin_lround: + case Builtin::BI__builtin_lroundf: + case Builtin::BI__builtin_lroundl: + case Builtin::BI__builtin_llround: + case Builtin::BI__builtin_llroundf: + case Builtin::BI__builtin_llroundl: { + APFloat FPVal(0.0); + APSInt IVal(Info.Ctx.getIntWidth(E->getType()), 0); + bool IsExact = true; + + if (!EvaluateFloat(E->getArg(0), FPVal, Info)) return false; + APFloat::opStatus RoundStatus = + FPVal.convertToInteger(IVal, APFloat::rmNearestTiesToAway, &IsExact); + if (RoundStatus != APFloat::opInexact && RoundStatus != APFloat::opOK) return false; + + return Success(IVal, E); + } + case Builtin::BI__builtin_fpclassify: { APFloat Val(0.0); if (!EvaluateFloat(E->getArg(5), Val, Info)) diff --git a/clang/test/SemaCXX/math-builtins.cpp b/clang/test/SemaCXX/math-builtins.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/math-builtins.cpp @@ -0,0 +1,58 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s + +int main() +{ + constexpr float f1 = 12345.6789; + constexpr float f2 = 12345.4321; + constexpr float f3 = 0.5; + constexpr float f4 = -0.5; + + static_assert(__builtin_llround(f1) == 12346, ""); + static_assert(__builtin_llroundf(f1) == 12346, ""); + static_assert(__builtin_llroundl(f1) == 12346, ""); + + static_assert(__builtin_lround(f1) == 12346, ""); + static_assert(__builtin_lroundf(f1) == 12346, ""); + static_assert(__builtin_lroundl(f1) == 12346, ""); + + static_assert(__builtin_llround(f2) == 12345, ""); + static_assert(__builtin_llroundf(f2) == 12345, ""); + static_assert(__builtin_llroundl(f2) == 12345, ""); + + static_assert(__builtin_lround(f2) == 12345, ""); + static_assert(__builtin_lroundf(f2) == 12345, ""); + static_assert(__builtin_lroundl(f2) == 12345, ""); + + static_assert(__builtin_llround(f3) == 1, ""); + static_assert(__builtin_llroundf(f3) == 1, ""); + static_assert(__builtin_llroundl(f3) == 1, ""); + + static_assert(__builtin_lround(f3) == 1, ""); + static_assert(__builtin_lroundf(f3) == 1, ""); + static_assert(__builtin_lroundl(f3) == 1, ""); + + static_assert(__builtin_llround(f4) == -1, ""); + static_assert(__builtin_llroundf(f4) == -1, ""); + static_assert(__builtin_llroundl(f4) == -1, ""); + + static_assert(__builtin_lround(f4) == -1, ""); + static_assert(__builtin_lroundf(f4) == -1, ""); + static_assert(__builtin_lroundl(f4) == -1, ""); + + static_assert(__builtin_llround(__builtin_nanf("")) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_llroundf(__builtin_nanf("")) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_llroundl(__builtin_nanf("")) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + + static_assert(__builtin_lround(__builtin_nanf("")) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_lroundf(__builtin_nanf("")) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_lroundl(__builtin_nanf("")) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + + static_assert(__builtin_llround(__FLT_MAX__) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_llroundf(__FLT_MAX__) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_llroundl(__FLT_MAX__) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + + static_assert(__builtin_lround(__FLT_MAX__) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_lroundf(__FLT_MAX__) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + static_assert(__builtin_lroundl(__FLT_MAX__) == 0, ""); // expected-error {{static_assert expression is not an integral constant expression}} + +} \ No newline at end of file