diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 5060e9e9e9..85504ac268 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -233,13 +233,12 @@ BUILTIN(__builtin_islessgreater , "i.", "nc") BUILTIN(__builtin_isunordered , "i.", "nc") // Unary FP classification -// BUILTIN(__builtin_fpclassify, "iiiii.", "nc") +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") -BUILTIN(__builtin_fpclassify, "iiiiii.", "nc") // Builtins for arithmetic. BUILTIN(__builtin_clz , "iUi" , "nc") diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 8db3eb1713..3c7492af61 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -4129,7 +4129,7 @@ private: CallExpr *TheCall); bool SemaBuiltinVAStart(CallExpr *TheCall); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); - bool SemaBuiltinUnaryFP(CallExpr *TheCall); + bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned LastArg=1); bool SemaBuiltinStackAddress(CallExpr *TheCall); public: diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 64cbde050b..f9466ca385 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -141,12 +141,16 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinUnorderedCompare(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_fpclassify: + if (SemaBuiltinFPClassification(TheCall, 6)) + 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)) + if (SemaBuiltinFPClassification(TheCall)) return ExprError(); break; case Builtin::BI__builtin_return_address: @@ -584,20 +588,21 @@ 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) +/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like +/// __builtin_isnan and friends. This is declared to take (...), so we have +/// to check everything. +bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned LastArg) { + if (TheCall->getNumArgs() < LastArg) return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) << 0 /*function call*/; - if (TheCall->getNumArgs() > 1) - return Diag(TheCall->getArg(1)->getLocStart(), + if (TheCall->getNumArgs() > LastArg) + return Diag(TheCall->getArg(LastArg)->getLocStart(), diag::err_typecheck_call_too_many_args) << 0 /*function call*/ - << SourceRange(TheCall->getArg(1)->getLocStart(), + << SourceRange(TheCall->getArg(LastArg)->getLocStart(), (*(TheCall->arg_end()-1))->getLocEnd()); - Expr *OrigArg = TheCall->getArg(0); + Expr *OrigArg = TheCall->getArg(LastArg-1); if (OrigArg->isTypeDependent()) return false; diff --git a/test/Sema/builtin-unary-fp.c b/test/Sema/builtin-unary-fp.c index 8f48d7ffc5..57568db8ae 100644 --- a/test/Sema/builtin-unary-fp.c +++ b/test/Sema/builtin-unary-fp.c @@ -9,4 +9,8 @@ void a() { 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}} + check(__builtin_fpclassify(0, 0, 0, 0, 0, 1.0)); + check(__builtin_fpclassify(0, 0, 0, 0, 0, 1)); // expected-error{{requires argument of floating point type}} + check(__builtin_fpclassify(0, 0, 0, 0, 1)); // expected-error{{too few arguments}} + check(__builtin_fpclassify(0, 0, 0, 0, 0, 1, 0)); // expected-error{{too many arguments}} }