t.p.northover updated this revision to Diff 109149.
t.p.northover added a comment.

Sounds like an improvement, I've updated the diff.


https://reviews.llvm.org/D35817

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenCXX/stmtexpr.cpp
  clang/test/OpenMP/atomic_capture_codegen.cpp
  clang/test/OpenMP/atomic_update_codegen.cpp
  clang/test/SemaCXX/complex-conversion.cpp
  clang/test/SemaCXX/complex-overload.cpp
  clang/test/SemaCXX/integer-overflow.cpp
  clang/test/SemaCXX/warn-absolute-value.cpp

Index: clang/test/SemaCXX/warn-absolute-value.cpp
===================================================================
--- clang/test/SemaCXX/warn-absolute-value.cpp
+++ clang/test/SemaCXX/warn-absolute-value.cpp
@@ -448,126 +448,23 @@
 }
 
 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}}
   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:14}:"cabs"
   (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_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 @@
   // 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}}
Index: clang/test/SemaCXX/integer-overflow.cpp
===================================================================
--- clang/test/SemaCXX/integer-overflow.cpp
+++ clang/test/SemaCXX/integer-overflow.cpp
@@ -164,7 +164,7 @@
 // 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)));
Index: clang/test/SemaCXX/complex-overload.cpp
===================================================================
--- clang/test/SemaCXX/complex-overload.cpp
+++ clang/test/SemaCXX/complex-overload.cpp
@@ -4,9 +4,10 @@
 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);
Index: clang/test/SemaCXX/complex-conversion.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/complex-conversion.cpp
@@ -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);
+}
Index: clang/test/OpenMP/atomic_update_codegen.cpp
===================================================================
--- clang/test/OpenMP/atomic_update_codegen.cpp
+++ clang/test/OpenMP/atomic_update_codegen.cpp
@@ -554,48 +554,6 @@
 // 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
Index: clang/test/OpenMP/atomic_capture_codegen.cpp
===================================================================
--- clang/test/OpenMP/atomic_capture_codegen.cpp
+++ clang/test/OpenMP/atomic_capture_codegen.cpp
@@ -611,50 +611,6 @@
 // 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
Index: clang/test/CodeGenCXX/stmtexpr.cpp
===================================================================
--- clang/test/CodeGenCXX/stmtexpr.cpp
+++ clang/test/CodeGenCXX/stmtexpr.cpp
@@ -173,7 +173,7 @@
 _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({{.*}})
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7514,6 +7514,12 @@
   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())) {
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -9369,10 +9369,13 @@
   // 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();
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3077,6 +3077,8 @@
 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;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to