OSDN Git Service

PR c++/43108
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Feb 2010 19:58:41 +0000 (19:58 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Feb 2010 19:58:41 +0000 (19:58 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@156874 138bc75d-0d04-0410-961f-82ee72b054a4

16 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/complex-alias-1.c [moved from gcc/testsuite/gcc.dg/torture/complex-alias-1.c with 85% similarity]
gcc/testsuite/c-c++-common/complex-sign-add.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-add.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign-mixed-add.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-add.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign-mixed-div.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-div.c with 96% similarity]
gcc/testsuite/c-c++-common/complex-sign-mixed-mul.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-mul.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign-mixed-sub.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-mixed-sub.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign-mul-minus-one.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-mul-minus-one.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign-mul-one.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-mul-one.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign-mul.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-mul.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign-sub.c [moved from gcc/testsuite/gcc.dg/torture/complex-sign-sub.c with 97% similarity]
gcc/testsuite/c-c++-common/complex-sign.h [moved from gcc/testsuite/gcc.dg/torture/complex-sign.h with 97% similarity]

index a54d30a..3140ecf 100644 (file)
@@ -1,5 +1,11 @@
 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.
 
index 8b5bb56..aff3f91 100644 (file)
@@ -4167,8 +4167,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 #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.  */
index 9dd0c59..344816c 100644 (file)
@@ -1170,8 +1170,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
        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)))
          {
@@ -1226,8 +1227,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
        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)))
            {
index 18d56f4..01384de 100644 (file)
@@ -4230,7 +4230,83 @@ cp_build_binary_op (location_t location,
 
   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,
@@ -4615,7 +4691,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
            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)))
index f3957e1..db7fa41 100644 (file)
@@ -1,5 +1,16 @@
 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.
@@ -1,9 +1,15 @@
 /* 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;
 }
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
@@ -1,7 +1,7 @@
 /* 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"
 
similarity index 97%
rename from gcc/testsuite/gcc.dg/torture/complex-sign.h
rename to gcc/testsuite/c-c++-common/complex-sign.h
index f12e25d..9626110 100644 (file)
@@ -1,7 +1,13 @@
 /* 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 {                                                         \