Sema: disable implicit conversion from _Complex to real types in C++.

Converting a _Complex type to a real one simply discards the imaginary part.
This can easily lead to loss of information so for safety (and GCC
compatibility) this patch disallows that when the conversion would be implicit.

The one exception is bool, which actually compares both real and imaginary
parts and so is safe.

llvm-svn: 310427
This commit is contained in:
Tim Northover 2017-08-08 23:18:05 +00:00
parent d1fafc8b05
commit 0241637c0e
10 changed files with 37 additions and 248 deletions

View File

@ -3087,6 +3087,8 @@ def warn_impcast_vector_scalar : Warning<
def warn_impcast_complex_scalar : Warning<
"implicit conversion discards imaginary component: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
def err_impcast_complex_scalar : Error<
"implicit conversion from %0 to %1 is not permitted in C++">;
def warn_impcast_float_precision : Warning<
"implicit conversion loses floating-point precision: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;

View File

@ -9431,10 +9431,13 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
// Strip complex types.
if (isa<ComplexType>(Source)) {
if (!isa<ComplexType>(Target)) {
if (S.SourceMgr.isInSystemMacro(CC))
if (S.SourceMgr.isInSystemMacro(CC) || Target->isBooleanType())
return;
return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar);
return DiagnoseImpCast(S, E, T, CC,
S.getLangOpts().CPlusPlus
? diag::err_impcast_complex_scalar
: diag::warn_impcast_complex_scalar);
}
Source = cast<ComplexType>(Source)->getElementType().getTypePtr();

View File

@ -7530,6 +7530,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS,
if (unsupportedTypeConversion(*this, LHSType, RHSType))
return Incompatible;
// Disallow assigning a _Complex to a real type in C++ mode since it simply
// discards the imaginary part.
if (getLangOpts().CPlusPlus && RHSType->getAs<ComplexType>() &&
!LHSType->getAs<ComplexType>())
return Incompatible;
// Arithmetic conversions.
if (LHSType->isArithmeticType() && RHSType->isArithmeticType() &&
!(getLangOpts().CPlusPlus && LHSType->isEnumeralType())) {

View File

@ -173,7 +173,7 @@ extern "C" int cleanup_exit_lvalue_local(bool cond) {
_Complex float bar_complex(A, int);
extern "C" int cleanup_exit_complex(bool b) {
_Complex float v = bar_complex(A(1), ({ if (b) return 42; 13; }));
return v;
return (float)v;
}
// CHECK-LABEL: define{{.*}} i32 @cleanup_exit_complex({{.*}})

View File

@ -611,50 +611,6 @@ int main() {
// CHECK: store i8 [[DESIRED_I8]], i8* @{{.+}},
#pragma omp atomic capture
{bx = civ - bx; bv = bx;}
// CHECK: [[EXPR_RE:%.+]] = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @{{.+}}, i32 0, i32 0)
// CHECK: [[EXPR_IM:%.+]] = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @{{.+}}, i32 0, i32 1)
// CHECK: [[X:%.+]] = load atomic i16, i16* [[X_ADDR:@.+]] monotonic
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[EXPECTED:%.+]] = phi i16 [ [[X]], %{{.+}} ], [ [[OLD_X:%.+]], %[[CONT]] ]
// CHECK: [[CONV:%.+]] = zext i16 [[EXPECTED]] to i32
// CHECK: [[X_RVAL:%.+]] = sitofp i32 [[CONV]] to float
// <Skip checks for complex calculations>
// CHECK: [[X_RE_ADDR:%.+]] = getelementptr inbounds { float, float }, { float, float }* [[TEMP:%.+]], i32 0, i32 0
// CHECK: [[X_RE:%.+]] = load float, float* [[X_RE_ADDR]]
// CHECK: [[X_IM_ADDR:%.+]] = getelementptr inbounds { float, float }, { float, float }* [[TEMP]], i32 0, i32 1
// CHECK: [[X_IM:%.+]] = load float, float* [[X_IM_ADDR]]
// CHECK: [[NEW:%.+]] = fptoui float [[X_RE]] to i16
// CHECK: store i16 [[NEW]], i16* [[TEMP:%.+]],
// CHECK: [[DESIRED:%.+]] = load i16, i16* [[TEMP]],
// CHECK: [[RES:%.+]] = cmpxchg i16* [[X_ADDR]], i16 [[EXPECTED]], i16 [[DESIRED]] monotonic monotonic
// CHECK: [[OLD_X]] = extractvalue { i16, i1 } [[RES]], 0
// CHECK: [[SUCCESS_FAIL:%.+]] = extractvalue { i16, i1 } [[RES]], 1
// CHECK: br i1 [[SUCCESS_FAIL]], label %[[EXIT:.+]], label %[[CONT]]
// CHECK: [[EXIT]]
// CHECK: store i16 [[NEW]], i16* @{{.+}},
#pragma omp atomic capture
usv = usx /= cfv;
// CHECK: [[EXPR_RE:%.+]] = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @{{.+}}, i32 0, i32 0)
// CHECK: [[EXPR_IM:%.+]] = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @{{.+}}, i32 0, i32 1)
// CHECK: [[X:%.+]] = load atomic i64, i64* [[X_ADDR:@.+]] monotonic
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[EXPECTED:%.+]] = phi i64 [ [[X]], %{{.+}} ], [ [[OLD_X:%.+]], %[[CONT]] ]
// CHECK: [[X_RVAL:%.+]] = sitofp i64 [[EXPECTED]] to double
// CHECK: [[ADD_RE:%.+]] = fadd double [[X_RVAL]], [[EXPR_RE]]
// CHECK: [[ADD_IM:%.+]] = fadd double 0.000000e+00, [[EXPR_IM]]
// CHECK: [[DESIRED:%.+]] = fptosi double [[ADD_RE]] to i64
// CHECK: store i64 [[DESIRED]], i64* [[TEMP:%.+]],
// CHECK: [[DESIRED:%.+]] = load i64, i64* [[TEMP]],
// CHECK: [[RES:%.+]] = cmpxchg i64* [[X_ADDR]], i64 [[EXPECTED]], i64 [[DESIRED]] monotonic monotonic
// CHECK: [[OLD_X]] = extractvalue { i64, i1 } [[RES]], 0
// CHECK: [[SUCCESS_FAIL:%.+]] = extractvalue { i64, i1 } [[RES]], 1
// CHECK: br i1 [[SUCCESS_FAIL]], label %[[EXIT:.+]], label %[[CONT]]
// CHECK: [[EXIT]]
// CHECK: store i64 [[EXPECTED]], i64* @{{.+}},
#pragma omp atomic capture
{llv = llx; llx += cdv;}
// CHECK: [[IDX:%.+]] = load i16, i16* @{{.+}}
// CHECK: load i8, i8*
// CHECK: [[VEC_ITEM_VAL:%.+]] = zext i1 %{{.+}} to i32

View File

@ -554,48 +554,6 @@ int main() {
// CHECK: [[EXIT]]
#pragma omp atomic
bx = civ - bx;
// CHECK: [[EXPR_RE:%.+]] = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @{{.+}}, i32 0, i32 0)
// CHECK: [[EXPR_IM:%.+]] = load float, float* getelementptr inbounds ({ float, float }, { float, float }* @{{.+}}, i32 0, i32 1)
// CHECK: [[X:%.+]] = load atomic i16, i16* [[X_ADDR:@.+]] monotonic
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[EXPECTED:%.+]] = phi i16 [ [[X]], %{{.+}} ], [ [[OLD_X:%.+]], %[[CONT]] ]
// CHECK: [[CONV:%.+]] = zext i16 [[EXPECTED]] to i32
// CHECK: [[X_RVAL:%.+]] = sitofp i32 [[CONV]] to float
// <Skip checks for complex calculations>
// CHECK: [[X_RE_ADDR:%.+]] = getelementptr inbounds { float, float }, { float, float }* [[TEMP:%.+]], i32 0, i32 0
// CHECK: [[X_RE:%.+]] = load float, float* [[X_RE_ADDR]]
// CHECK: [[X_IM_ADDR:%.+]] = getelementptr inbounds { float, float }, { float, float }* [[TEMP]], i32 0, i32 1
// CHECK: [[X_IM:%.+]] = load float, float* [[X_IM_ADDR]]
// CHECK: [[DESIRED:%.+]] = fptoui float [[X_RE]] to i16
// CHECK: store i16 [[DESIRED]], i16* [[TEMP:%.+]]
// CHECK: [[DESIRED:%.+]] = load i16, i16* [[TEMP]]
// CHECK: [[RES:%.+]] = cmpxchg i16* [[X_ADDR]], i16 [[EXPECTED]], i16 [[DESIRED]] monotonic monotonic
// CHECK: [[OLD_X]] = extractvalue { i16, i1 } [[RES]], 0
// CHECK: [[SUCCESS_FAIL:%.+]] = extractvalue { i16, i1 } [[RES]], 1
// CHECK: br i1 [[SUCCESS_FAIL]], label %[[EXIT:.+]], label %[[CONT]]
// CHECK: [[EXIT]]
#pragma omp atomic update
usx /= cfv;
// CHECK: [[EXPR_RE:%.+]] = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @{{.+}}, i32 0, i32 0)
// CHECK: [[EXPR_IM:%.+]] = load double, double* getelementptr inbounds ({ double, double }, { double, double }* @{{.+}}, i32 0, i32 1)
// CHECK: [[X:%.+]] = load atomic i64, i64* [[X_ADDR:@.+]] monotonic
// CHECK: br label %[[CONT:.+]]
// CHECK: [[CONT]]
// CHECK: [[EXPECTED:%.+]] = phi i64 [ [[X]], %{{.+}} ], [ [[OLD_X:%.+]], %[[CONT]] ]
// CHECK: [[X_RVAL:%.+]] = sitofp i64 [[EXPECTED]] to double
// CHECK: [[ADD_RE:%.+]] = fadd double [[X_RVAL]], [[EXPR_RE]]
// CHECK: [[ADD_IM:%.+]] = fadd double 0.000000e+00, [[EXPR_IM]]
// CHECK: [[DESIRED:%.+]] = fptosi double [[ADD_RE]] to i64
// CHECK: store i64 [[DESIRED]], i64* [[TEMP:%.+]]
// CHECK: [[DESIRED:%.+]] = load i64, i64* [[TEMP]]
// CHECK: [[RES:%.+]] = cmpxchg i64* [[X_ADDR]], i64 [[EXPECTED]], i64 [[DESIRED]] monotonic monotonic
// CHECK: [[OLD_X]] = extractvalue { i64, i1 } [[RES]], 0
// CHECK: [[SUCCESS_FAIL:%.+]] = extractvalue { i64, i1 } [[RES]], 1
// CHECK: br i1 [[SUCCESS_FAIL]], label %[[EXIT:.+]], label %[[CONT]]
// CHECK: [[EXIT]]
#pragma omp atomic
llx += cdv;
// CHECK: [[IDX:%.+]] = load i16, i16* @{{.+}}
// CHECK: load i8, i8*
// CHECK: [[VEC_ITEM_VAL:%.+]] = zext i1 %{{.+}} to i32

View File

@ -0,0 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
template<typename T> void take(T);
void func(float Real, _Complex float Complex) {
Real += Complex; // expected-error {{assigning to 'float' from incompatible type '_Complex float'}}
Real += (float)Complex;
Real = Complex; // expected-error {{implicit conversion from '_Complex float' to 'float' is not permitted in C++}}
Real = (float)Complex;
take<float>(Complex); // expected-error {{implicit conversion from '_Complex float' to 'float' is not permitted in C++}}
take<double>(1.0i); // expected-error {{implicit conversion from '_Complex double' to 'double' is not permitted in C++}}
take<_Complex float>(Complex);
// Conversion to bool doesn't actually discard the imaginary part.
take<bool>(Complex);
}

View File

@ -4,9 +4,10 @@ char *foo(float);
void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) {
char *cp1 = foo(fv);
char *cp2 = foo(dv);
// Note: GCC and EDG reject these two, but they are valid C99 conversions
char *cp3 = foo(fc);
char *cp4 = foo(dc);
// Note: GCC and EDG reject these two, they are valid C99 conversions but
// shouldn't be accepted in C++ because the result is surprising.
char *cp3 = foo(fc); // expected-error {{implicit conversion from '_Complex float' to 'float' is not permitted in C++}}
char *cp4 = foo(dc); // expected-error {{implicit conversion from '_Complex double' to 'float' is not permitted in C++}}
}
int *foo(float _Complex);

View File

@ -164,7 +164,7 @@ uint64_t check_integer_overflows(int i) { //expected-note {{declared here}}
// expected-warning@+3 {{array index 536870912 is past the end of the array (which contains 10 elements)}}
// expected-note@+1 {{array 'a' declared here}}
uint64_t a[10];
a[4608 * 1024 * 1024] = 1i;
a[4608 * 1024 * 1024] = 1;
// expected-warning@+1 2{{overflow in expression; result is 536870912 with type 'int'}}
return ((4608 * 1024 * 1024) + ((uint64_t)(4608 * 1024 * 1024)));

View File

@ -448,94 +448,16 @@ void test_long_double(long double x) {
}
void test_complex_float(_Complex float x) {
(void)abs(x);
// expected-warning@-1 {{using integer absolute value function 'abs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"cabsf"
(void)labs(x);
// expected-warning@-1 {{using integer absolute value function 'labs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsf"
(void)llabs(x);
// expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsf"
(void)fabsf(x);
// expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsf"
(void)fabs(x);
// expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsf"
(void)fabsl(x);
// expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsf"
(void)cabsf(x);
(void)cabs(x);
(void)cabsl(x);
(void)__builtin_abs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"__builtin_cabsf"
(void)__builtin_labs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsf"
(void)__builtin_llabs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsf"
(void)__builtin_fabsf(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsf"
(void)__builtin_fabs(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsf"
(void)__builtin_fabsl(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsf' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsf"
(void)__builtin_cabsf(x);
(void)__builtin_cabs(x);
(void)__builtin_cabsl(x);
}
void test_complex_double(_Complex double x) {
(void)abs(x);
// expected-warning@-1 {{using integer absolute value function 'abs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"cabs"
(void)labs(x);
// expected-warning@-1 {{using integer absolute value function 'labs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabs"
(void)llabs(x);
// expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs"
(void)fabsf(x);
// expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of complex type}}
// expected-note@-2 {{use function 'cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs"
(void)fabs(x);
// expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabs"
(void)fabsl(x);
// expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of complex type}}
// expected-note@-2 {{use function 'cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs"
(void)cabsf(x);
// expected-warning@-1 {{absolute value function 'cabsf' given an argument of type '_Complex double' but has parameter of type '_Complex float' which may cause truncation of value}}
// expected-note@-2 {{use function 'cabs' instead}}
@ -543,31 +465,6 @@ void test_complex_double(_Complex double x) {
(void)cabs(x);
(void)cabsl(x);
(void)__builtin_abs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"__builtin_cabs"
(void)__builtin_labs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabs"
(void)__builtin_llabs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabs"
(void)__builtin_fabsf(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabs"
(void)__builtin_fabs(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabs"
(void)__builtin_fabsl(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabs' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabs"
(void)__builtin_cabsf(x);
// expected-warning@-1 {{absolute value function '__builtin_cabsf' given an argument of type '_Complex double' but has parameter of type '_Complex float' which may cause truncation of value}}
@ -578,32 +475,6 @@ void test_complex_double(_Complex double x) {
}
void test_complex_long_double(_Complex long double x) {
(void)abs(x);
// expected-warning@-1 {{using integer absolute value function 'abs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:12}:"cabsl"
(void)labs(x);
// expected-warning@-1 {{using integer absolute value function 'labs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsl"
(void)llabs(x);
// expected-warning@-1 {{using integer absolute value function 'llabs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsl"
(void)fabsf(x);
// expected-warning@-1 {{using floating point absolute value function 'fabsf' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsl"
(void)fabs(x);
// expected-warning@-1 {{using floating point absolute value function 'fabs' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsl"
(void)fabsl(x);
// expected-warning@-1 {{using floating point absolute value function 'fabsl' when argument is of complex type}}
// expected-note@-2 {{use function 'cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabsl"
(void)cabsf(x);
// expected-warning@-1 {{absolute value function 'cabsf' given an argument of type '_Complex long double' but has parameter of type '_Complex float' which may cause truncation of value}}
// expected-note@-2 {{use function 'cabsl' instead}}
@ -614,32 +485,6 @@ void test_complex_long_double(_Complex long double x) {
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:13}:"cabsl"
(void)cabsl(x);
(void)__builtin_abs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_abs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:22}:"__builtin_cabsl"
(void)__builtin_labs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_labs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsl"
(void)__builtin_llabs(x);
// expected-warning@-1 {{using integer absolute value function '__builtin_llabs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsl"
(void)__builtin_fabsf(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabsf' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsl"
(void)__builtin_fabs(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabs' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:23}:"__builtin_cabsl"
(void)__builtin_fabsl(x);
// expected-warning@-1 {{using floating point absolute value function '__builtin_fabsl' when argument is of complex type}}
// expected-note@-2 {{use function '__builtin_cabsl' instead}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:24}:"__builtin_cabsl"
(void)__builtin_cabsf(x);
// expected-warning@-1 {{absolute value function '__builtin_cabsf' given an argument of type '_Complex long double' but has parameter of type '_Complex float' which may cause truncation of value}}
// expected-note@-2 {{use function '__builtin_cabsl' instead}}