
The FP-classification builtins (__builtin_isfinite, etc) use variadic packs in the definition file to mean an overload set. Because of that, floats were converted to doubles, which is incorrect. There WAS a patch to remove the cast after the fact. THis patch switches these builtins to just be custom type checking, calls the implicit conversions for the integer members, and makes sure the correct L->R casts are put into place, then does type checking like normal. A future direction (that wouldn't be NFC) would consider making conversions for the floating point parameter legal. Note: The initial patch for this missed that certain systems need to still convert half to float, since they dont' support that type.
92 lines
2.9 KiB
C
92 lines
2.9 KiB
C
// RUN: %clang_cc1 %s -Wno-unused-value -verify -fsyntax-only
|
|
// RUN: %clang_cc1 %s -Wno-unused-value -ast-dump -DAST_CHECK | FileCheck %s
|
|
|
|
struct S {};
|
|
void usage(float f, int i, double d) {
|
|
#ifdef AST_CHECK
|
|
__builtin_fpclassify(d, 1, i, i, 3, d);
|
|
//CHECK: CallExpr
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: <BuiltinFnToFnPtr>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: '__builtin_fpclassify'
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'int' <FloatingToIntegral>
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'double' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'd' 'double'
|
|
//CHECK-NEXT: IntegerLiteral
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'int' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'i' 'int'
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'int' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'i' 'int'
|
|
//CHECK-NEXT: IntegerLiteral
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'double' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'd' 'double'
|
|
|
|
__builtin_fpclassify(f, 1, i, i, 3, f);
|
|
//CHECK: CallExpr
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: <BuiltinFnToFnPtr>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: '__builtin_fpclassify'
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'int' <FloatingToIntegral>
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'float' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'f' 'float'
|
|
//CHECK-NEXT: IntegerLiteral
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'int' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'i' 'int'
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'int' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'i' 'int'
|
|
//CHECK-NEXT: IntegerLiteral
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'float' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'f' 'float'
|
|
|
|
__builtin_isfinite(f);
|
|
//CHECK: CallExpr
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: <BuiltinFnToFnPtr>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: '__builtin_isfinite'
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'float' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'f' 'float'
|
|
|
|
__builtin_isfinite(d);
|
|
//CHECK: CallExpr
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: <BuiltinFnToFnPtr>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: '__builtin_isfinite'
|
|
//CHECK-NEXT: ImplicitCastExpr
|
|
//CHECK-SAME: 'double' <LValueToRValue>
|
|
//CHECK-NEXT: DeclRefExpr
|
|
//CHECK-SAME: 'd' 'double'
|
|
#else
|
|
struct S s;
|
|
// expected-error@+1{{passing 'struct S' to parameter of incompatible type 'int'}}
|
|
__builtin_fpclassify(d, s, i, i, 3, d);
|
|
// expected-error@+1{{floating point classification requires argument of floating point type (passed in 'int')}}
|
|
__builtin_fpclassify(d, 1, i, i, 3, i);
|
|
// expected-error@+1{{floating point classification requires argument of floating point type (passed in 'int')}}
|
|
__builtin_isfinite(i);
|
|
#endif
|
|
}
|