2010-02-18 Jason Merrill <jason@redhat.com>
+ PR c++/43108
+ * typeck.c (cp_build_binary_op): Adapt mixed complex/non handling from
+ C build_binary_op.
+ * cp-tree.h (WANT_VECTOR_OR_COMPLEX): Rename from WANT_VECTOR.
+ * cvt.c (build_expr_type_conversion): Allow COMPLEX_TYPE.
+
PR c++/43070
* semantics.c (finish_goto_stmt): Don't call decay_conversion.
#define WANT_ENUM 4 /* enumerated types */
#define WANT_POINTER 8 /* pointer types */
#define WANT_NULL 16 /* null pointer constant */
-#define WANT_VECTOR 32 /* vector types */
-#define WANT_ARITH (WANT_INT | WANT_FLOAT | WANT_VECTOR)
+#define WANT_VECTOR_OR_COMPLEX 32 /* vector or complex types */
+#define WANT_ARITH (WANT_INT | WANT_FLOAT | WANT_VECTOR_OR_COMPLEX)
/* Used with comptypes, and related functions, to guide type
comparison. */
return (desires & WANT_POINTER) ? decay_conversion (expr)
: NULL_TREE;
+ case COMPLEX_TYPE:
case VECTOR_TYPE:
- if ((desires & WANT_VECTOR) == 0)
+ if ((desires & WANT_VECTOR_OR_COMPLEX) == 0)
return NULL_TREE;
switch (TREE_CODE (TREE_TYPE (basetype)))
{
case POINTER_TYPE:
win = (desires & WANT_POINTER); break;
+ case COMPLEX_TYPE:
case VECTOR_TYPE:
- if ((desires & WANT_VECTOR) == 0)
+ if ((desires & WANT_VECTOR_OR_COMPLEX) == 0)
break;
switch (TREE_CODE (TREE_TYPE (candidate)))
{
if (arithmetic_types_p)
{
- int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+ bool first_complex = (code0 == COMPLEX_TYPE);
+ bool second_complex = (code1 == COMPLEX_TYPE);
+ int none_complex = (!first_complex && !second_complex);
+
+ /* Adapted from patch for c/24581. */
+ if (first_complex != second_complex
+ && (code == PLUS_EXPR
+ || code == MINUS_EXPR
+ || code == MULT_EXPR
+ || (code == TRUNC_DIV_EXPR && first_complex))
+ && TREE_CODE (TREE_TYPE (result_type)) == REAL_TYPE
+ && flag_signed_zeros)
+ {
+ /* An operation on mixed real/complex operands must be
+ handled specially, but the language-independent code can
+ more easily optimize the plain complex arithmetic if
+ -fno-signed-zeros. */
+ tree real_type = TREE_TYPE (result_type);
+ tree real, imag;
+ if (first_complex)
+ {
+ if (TREE_TYPE (op0) != result_type)
+ op0 = cp_convert_and_check (result_type, op0);
+ if (TREE_TYPE (op1) != real_type)
+ op1 = cp_convert_and_check (real_type, op1);
+ }
+ else
+ {
+ if (TREE_TYPE (op0) != real_type)
+ op0 = cp_convert_and_check (real_type, op0);
+ if (TREE_TYPE (op1) != result_type)
+ op1 = cp_convert_and_check (result_type, op1);
+ }
+ if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+ return error_mark_node;
+ if (first_complex)
+ {
+ op0 = save_expr (op0);
+ real = cp_build_unary_op (REALPART_EXPR, op0, 1, complain);
+ imag = cp_build_unary_op (IMAGPART_EXPR, op0, 1, complain);
+ switch (code)
+ {
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ imag = build2 (resultcode, real_type, imag, op1);
+ /* Fall through. */
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ real = build2 (resultcode, real_type, real, op1);
+ break;
+ default:
+ gcc_unreachable();
+ }
+ }
+ else
+ {
+ op1 = save_expr (op1);
+ real = cp_build_unary_op (REALPART_EXPR, op1, 1, complain);
+ imag = cp_build_unary_op (IMAGPART_EXPR, op1, 1, complain);
+ switch (code)
+ {
+ case MULT_EXPR:
+ imag = build2 (resultcode, real_type, op0, imag);
+ /* Fall through. */
+ case PLUS_EXPR:
+ real = build2 (resultcode, real_type, op0, real);
+ break;
+ case MINUS_EXPR:
+ real = build2 (resultcode, real_type, op0, real);
+ imag = build1 (NEGATE_EXPR, real_type, imag);
+ break;
+ default:
+ gcc_unreachable();
+ }
+ }
+ return build2 (COMPLEX_EXPR, result_type, real, imag);
+ }
/* For certain operations (which identify themselves by shorten != 0)
if both args were extended from the same smaller type,
arg = default_conversion (arg);
}
else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM
- | WANT_VECTOR,
+ | WANT_VECTOR_OR_COMPLEX,
arg, true)))
errstring = _("wrong type argument to bit-complement");
else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
2010-02-18 Jason Merrill <jason@redhat.com>
+ PR c++/43108
+ * c-c++-common/complex-sign.h,
+ c-c++-common/complex-sign-add.c,
+ c-c++-common/complex-sign-mixed-add.c,
+ c-c++-common/complex-sign-mixed-div.c,
+ c-c++-common/complex-sign-mixed-mul.c,
+ c-c++-common/complex-sign-mixed-sub.c,
+ c-c++-common/complex-sign-mul.c,
+ c-c++-common/complex-sign-sub.c: Move from gcc.dg/torture.
+ Adapt for C++ compilation as well.
+
PR c++/43070
* g++.dg/ext/label1.C: Update.
* g++.dg/ext/label2.C: Update.
/* Accesses to complex numbers were sometimes marked as scalar and
sometimes as struct accesses. */
/* { dg-do run } */
-/* { dg-options "-std=c99" } */
+/* { dg-options "-std=c99" { target c } } */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
+#ifdef __cplusplus
+}
+#endif
static double _Complex *fp_cxd(double _Complex *cx) {
return cx;
}
/* Test complex arithmetic with signed zeros. Pure complex
addition. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Mixed real/complex
addition. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Mixed real/complex
division. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Mixed real/complex
multiplication. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Mixed real/complex
subtraction. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Pure complex
multiplication with -1.0 + 0.0i. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Pure complex
multiplication with 1.0 + 0.0i. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Pure complex
multiplication. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Test complex arithmetic with signed zeros. Pure complex
subtraction. */
/* { dg-do run } */
-/* { dg-options "-std=gnu99" } */
+/* { dg-options "-std=gnu99" { target c } } */
#include "complex-sign.h"
/* Common header for complex arithmetic sign tests. */
+#ifdef __cplusplus
+extern "C" {
+#endif
extern void abort (void);
extern void exit (int);
+#ifdef __cplusplus
+}
+#endif
#define CHECK_RES(VALUE, COPY, SIGN_REAL, SIGN_IMAG) \
do { \