Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -960,6 +960,9 @@ case Builtin::BI__builtin_isinf_sign: case Builtin::BI__builtin_isnan: case Builtin::BI__builtin_isnormal: + case Builtin::BI__builtin_signbit: + case Builtin::BI__builtin_signbitf: + case Builtin::BI__builtin_signbitl: if (SemaBuiltinFPClassification(TheCall, 1)) return ExprError(); break; @@ -4574,15 +4577,19 @@ diag::err_typecheck_call_invalid_unary_fp) << OrigArg->getType() << OrigArg->getSourceRange(); - // If this is an implicit conversion from float -> float or double, remove it. + // If this is an implicit conversion from float -> float, double, or + // long double, remove it. if (ImplicitCastExpr *Cast = dyn_cast(OrigArg)) { // Only remove standard FloatCasts, leaving other casts inplace if (Cast->getCastKind() == CK_FloatingCast) { Expr *CastArg = Cast->getSubExpr(); if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { - assert((Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || - Cast->getType()->isSpecificBuiltinType(BuiltinType::Float)) && - "promotion from float to either float or double is the only expected cast here"); + assert( + (Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::Float) || + Cast->getType()->isSpecificBuiltinType(BuiltinType::LongDouble)) && + "promotion from float to either float, double, or long double is " + "the only expected cast here"); Cast->setSubExpr(nullptr); TheCall->setArg(NumArgs-1, CastArg); } Index: test/Sema/builtins.c =================================================================== --- test/Sema/builtins.c +++ test/Sema/builtins.c @@ -253,3 +253,26 @@ __sync_fetch_and_add(ptr, 1); // expected-error{{address argument to atomic builtin cannot be const-qualified ('const int *' invalid)}} __atomic_fetch_add(ptr, 1, 0); // expected-error {{address argument to atomic operation must be a pointer to non-const type ('const int *' invalid)}} } + +void test22(void) { + (void)__builtin_signbit(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbit(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbit(1); // expected-error {{floating point classification requires argument of floating point type (passed in 'int')}} + (void)__builtin_signbit(1.0); + (void)__builtin_signbit(1.0f); + (void)__builtin_signbit(1.0L); + + (void)__builtin_signbitf(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbitf(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbitf(1); + (void)__builtin_signbitf(1.0); + (void)__builtin_signbitf(1.0f); + (void)__builtin_signbitf(1.0L); + + (void)__builtin_signbitl(); // expected-error{{too few arguments to function call, expected 1, have 0}} + (void)__builtin_signbitl(1.0, 2.0, 3.0); // expected-error{{too many arguments to function call, expected 1, have 3}} + (void)__builtin_signbitl(1); + (void)__builtin_signbitl(1.0); + (void)__builtin_signbitl(1.0f); + (void)__builtin_signbitl(1.0L); +}