From 9ac6f62a77be5b281a7ddc24a16669b457ac47c2 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Mon, 31 Aug 2009 20:06:00 +0000 Subject: [PATCH] PR4836, part 1: add Sema support for __builtin_isnan and friends; they are apparently used by Solaris libc despite the fact that clang claims to be compatible with gcc 4.2, which doesn't support them. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80610 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Builtins.def | 8 +++++ include/clang/Basic/DiagnosticSemaKinds.td | 3 ++ lib/Sema/Sema.h | 1 + lib/Sema/SemaChecking.cpp | 35 ++++++++++++++++++++++ test/Sema/builtin-unary-fp.c | 12 ++++++++ 5 files changed, 59 insertions(+) create mode 100644 test/Sema/builtin-unary-fp.c diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index d30a7c84ef..e0268b7122 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -106,6 +106,14 @@ BUILTIN(__builtin_islessequal , "i.", "nc") BUILTIN(__builtin_islessgreater , "i.", "nc") BUILTIN(__builtin_isunordered , "i.", "nc") +// Unary FP classification +// BUILTIN(__builtin_fpclassify, "iiiii.", "nc") +BUILTIN(__builtin_isfinite, "i.", "nc") +BUILTIN(__builtin_isinf, "i.", "nc") +BUILTIN(__builtin_isinf_sign, "i.", "nc") +BUILTIN(__builtin_isnan, "i.", "nc") +BUILTIN(__builtin_isnormal, "i.", "nc") + // Builtins for arithmetic. BUILTIN(__builtin_clz , "iUi" , "nc") BUILTIN(__builtin_clzl , "iULi" , "nc") diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 564eacb4b4..5e9c7486d3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1681,6 +1681,9 @@ def warn_cannot_pass_non_pod_arg_to_vararg : Warning< def err_typecheck_call_invalid_ordered_compare : Error< "ordered compare requires two args of floating point type (%0 and %1)">; +def err_typecheck_call_invalid_unary_fp : Error< + "floating point classification requires argument of floating point type " + "(passed in %0)">; def err_typecheck_cond_expect_scalar : Error< "used type %0 where arithmetic or pointer type is required">; def ext_typecheck_cond_one_void : Extension< diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index f9c893f0a0..2a2515ff11 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -3494,6 +3494,7 @@ private: CallExpr *TheCall); bool SemaBuiltinVAStart(CallExpr *TheCall); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); + bool SemaBuiltinUnaryFP(CallExpr *TheCall); bool SemaBuiltinStackAddress(CallExpr *TheCall); public: diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index e6fa372736..449c5f3384 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -125,6 +125,14 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinUnorderedCompare(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_isfinite: + case Builtin::BI__builtin_isinf: + case Builtin::BI__builtin_isinf_sign: + case Builtin::BI__builtin_isnan: + case Builtin::BI__builtin_isnormal: + if (SemaBuiltinUnaryFP(TheCall)) + return ExprError(); + break; case Builtin::BI__builtin_return_address: case Builtin::BI__builtin_frame_address: if (SemaBuiltinStackAddress(TheCall)) @@ -557,6 +565,33 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { return false; } +/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isnan and +/// friends. This is declared to take (...), so we have to check everything. +bool Sema::SemaBuiltinUnaryFP(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 1) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 /*function call*/; + if (TheCall->getNumArgs() > 1) + return Diag(TheCall->getArg(1)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ + << SourceRange(TheCall->getArg(1)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + Expr *OrigArg = TheCall->getArg(0); + + if (OrigArg->isTypeDependent()) + return false; + + // This operation requires a floating-point number + if (!OrigArg->getType()->isRealFloatingType()) + return Diag(OrigArg->getLocStart(), + diag::err_typecheck_call_invalid_unary_fp) + << OrigArg->getType() << OrigArg->getSourceRange(); + + return false; +} + bool Sema::SemaBuiltinStackAddress(CallExpr *TheCall) { // The signature for these builtins is exact; the only thing we need // to check is that the argument is a constant. diff --git a/test/Sema/builtin-unary-fp.c b/test/Sema/builtin-unary-fp.c new file mode 100644 index 0000000000..70c7a297fb --- /dev/null +++ b/test/Sema/builtin-unary-fp.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic +void check(int); +void a() { + check(__builtin_isfinite(1.0f)); + check(__builtin_isinf(1.0)); + check(__builtin_isinf_sign(1.0L)); + check(__builtin_isnan(1.0f)); + check(__builtin_isnormal(1.0f)); + check(__builtin_isfinite(1)); // expected-error{{requires argument of floating point type}} + check(__builtin_isinf()); // expected-error{{too few arguments}} + check(__builtin_isnan(1,2)); // expected-error{{too many arguments}} +} -- 2.40.0