]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Bootstrapped/regtested on x86_64-linux, ok for trunk?
authorMarek Polacek <polacek@redhat.com>
Tue, 26 Apr 2016 11:32:26 +0000 (11:32 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Tue, 26 Apr 2016 11:32:26 +0000 (11:32 +0000)
2016-04-25  Marek Polacek  <polacek@redhat.com>

PR c++/70744
* call.c (build_conditional_expr_1): Call cp_stabilize_reference
instead of stabilize_reference.
(build_over_call): Likewise.
* cp-tree.h (cp_stabilize_reference): Declare.
* tree.c (cp_stabilize_reference): New function.
* typeck.c (cp_build_unary_op): Call cp_stabilize_reference instead of
stabilize_reference.
(unary_complex_lvalue): Likewise.
(cp_build_modify_expr): Likewise.

* g++.dg/ext/cond2.C: New test.

diff --git gcc/cp/call.c gcc/cp/call.c
index 11f2d42..476e806 100644
--- gcc/cp/call.c
+++ gcc/cp/call.c
@@ -4634,7 +4634,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,

       /* Make sure that lvalues remain lvalues.  See g++.oliva/ext1.C.  */
       if (real_lvalue_p (arg1))
- arg2 = arg1 = stabilize_reference (arg1);
+ arg2 = arg1 = cp_stabilize_reference (arg1);
       else
  arg2 = arg1 = save_expr (arg1);
     }
@@ -7644,8 +7644,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
         || (TREE_CODE (arg) == TARGET_EXPR
     && !unsafe_copy_elision_p (fa, arg)))
  {
-   tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
- complain));
+   tree to = cp_stabilize_reference (cp_build_indirect_ref (fa,
+    RO_NULL,
+    complain));

    val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
    return val;
@@ -7655,7 +7656,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
     && trivial_fn_p (fn)
     && !DECL_DELETED_FN (fn))
     {
-      tree to = stabilize_reference
+      tree to = cp_stabilize_reference
  (cp_build_indirect_ref (argarray[0], RO_NULL, complain));
       tree type = TREE_TYPE (to);
       tree as_base = CLASSTYPE_AS_BASE (type);
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
index ec92718..0e46ae1 100644
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -6494,6 +6494,7 @@ extern cp_lvalue_kind real_lvalue_p (const_tree);
 extern cp_lvalue_kind lvalue_kind (const_tree);
 extern bool lvalue_or_rvalue_with_address_p (const_tree);
 extern bool xvalue_p                         (const_tree);
+extern tree cp_stabilize_reference (tree);
 extern bool builtin_valid_in_constant_expr_p    (const_tree);
 extern tree build_min (enum tree_code, tree, ...);
 extern tree build_min_nt_loc (location_t, enum tree_code,
diff --git gcc/cp/tree.c gcc/cp/tree.c
index 112c8c7..137186f 100644
--- gcc/cp/tree.c
+++ gcc/cp/tree.c
@@ -296,6 +296,46 @@ xvalue_p (const_tree ref)
   return (lvalue_kind (ref) == clk_rvalueref);
 }

+/* C++-specific version of stabilize_reference.  */
+
+tree
+cp_stabilize_reference (tree ref)
+{
+  switch (TREE_CODE (ref))
+    {
+    /* We need to treat specially anything stabilize_reference doesn't
+       handle specifically.  */
+    case VAR_DECL:
+    case PARM_DECL:
+    case RESULT_DECL:
+    CASE_CONVERT:
+    case FLOAT_EXPR:
+    case FIX_TRUNC_EXPR:
+    case INDIRECT_REF:
+    case COMPONENT_REF:
+    case BIT_FIELD_REF:
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+    case COMPOUND_EXPR:
+    case ERROR_MARK:
+      break;
+    default:
+      cp_lvalue_kind kind = lvalue_kind (ref);
+      if ((kind & ~clk_class) != clk_none)
+ {
+   tree type = unlowered_expr_type (ref);
+   bool rval = !!(kind & clk_rvalueref);
+   type = cp_build_reference_type (type, rval);
+   /* This inhibits warnings in, eg, cxx_mark_addressable
+      (c++/60955).  */
+   warning_sentinel s (extra_warnings);
+   ref = build_static_cast (type, ref, tf_error);
+ }
+    }
+
+  return stabilize_reference (ref);
+}
+
 /* Test whether DECL is a builtin that may appear in a
    constant-expression. */

diff --git gcc/cp/typeck.c gcc/cp/typeck.c
index cef5604..7e12009 100644
--- gcc/cp/typeck.c
+++ gcc/cp/typeck.c
@@ -5912,7 +5912,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
  {
    tree real, imag;

-   arg = stabilize_reference (arg);
+   arg = cp_stabilize_reference (arg);
    real = cp_build_unary_op (REALPART_EXPR, arg, 1, complain);
    imag = cp_build_unary_op (IMAGPART_EXPR, arg, 1, complain);
    real = cp_build_unary_op (code, real, 1, complain);
@@ -6112,7 +6112,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
       tree lvalue = TREE_OPERAND (arg, 0);
       if (TREE_SIDE_EFFECTS (lvalue))
  {
-   lvalue = stabilize_reference (lvalue);
+   lvalue = cp_stabilize_reference (lvalue);
    arg = build2 (TREE_CODE (arg), TREE_TYPE (arg),
  lvalue, TREE_OPERAND (arg, 1));
  }
@@ -7496,7 +7496,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     case PREINCREMENT_EXPR:
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
  lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
-       stabilize_reference (TREE_OPERAND (lhs, 0)),
+       cp_stabilize_reference (TREE_OPERAND (lhs, 0)),
        TREE_OPERAND (lhs, 1));
       newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 0),
       modifycode, rhs, complain);
@@ -7516,7 +7516,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     case MODIFY_EXPR:
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
  lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
-       stabilize_reference (TREE_OPERAND (lhs, 0)),
+       cp_stabilize_reference (TREE_OPERAND (lhs, 0)),
        TREE_OPERAND (lhs, 1));
       newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs,
       complain);
@@ -7665,7 +7665,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
       not intervene between the lvalue-to-rvalue conversion and the
       side effect associated with any single compound assignment
       operator. -- end note ]  */
-   lhs = stabilize_reference (lhs);
+   lhs = cp_stabilize_reference (lhs);
    rhs = rvalue (rhs);
    rhs = stabilize_expr (rhs, &init);
    newrhs = cp_build_binary_op (input_location,
diff --git gcc/testsuite/g++.dg/ext/cond2.C gcc/testsuite/g++.dg/ext/cond2.C
index e69de29..d9f1d59 100644
--- gcc/testsuite/g++.dg/ext/cond2.C
+++ gcc/testsuite/g++.dg/ext/cond2.C
@@ -0,0 +1,28 @@
+// PR c++/70744
+// { dg-do run }
+// { dg-options "" }
+
+static void
+fn1 (void)
+{
+  int x = 2;
+  ++x ? : 42;
+  if (x != 3)
+    __builtin_abort ();
+  --x ? : 42;
+  if (x != 2)
+    __builtin_abort ();
+  x++ ? : 42;
+  if (x != 3)
+    __builtin_abort ();
+  x-- ? : 42;
+  if (x != 2)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  fn1 ();
+  return 0;
+}

From-SVN: r235438

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/cond2.C [new file with mode: 0644]

index a81ffa0c0e24938adc424d33cbaecac657d23599..c78abe83bbb0bdfb5d4eb52fa1632a22a64f91b1 100644 (file)
@@ -1,3 +1,16 @@
+2016-04-26  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/70744
+       * call.c (build_conditional_expr_1): Call cp_stabilize_reference
+       instead of stabilize_reference.
+       (build_over_call): Likewise.
+       * cp-tree.h (cp_stabilize_reference): Declare.
+       * tree.c (cp_stabilize_reference): New function.
+       * typeck.c (cp_build_unary_op): Call cp_stabilize_reference instead of
+       stabilize_reference.
+       (unary_complex_lvalue): Likewise.
+       (cp_build_modify_expr): Likewise.
+
 2016-04-26  Jakub Jelinek  <jakub@redhat.com>
 
        PR bootstrap/70704
index 11f2d42108e7bc0f1b8d6f223657d718aba27503..476e806d41990821118508069d6a1bb123dd2f6e 100644 (file)
@@ -4634,7 +4634,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 
       /* Make sure that lvalues remain lvalues.  See g++.oliva/ext1.C.  */
       if (real_lvalue_p (arg1))
-       arg2 = arg1 = stabilize_reference (arg1);
+       arg2 = arg1 = cp_stabilize_reference (arg1);
       else
        arg2 = arg1 = save_expr (arg1);
     }
@@ -7644,8 +7644,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
               || (TREE_CODE (arg) == TARGET_EXPR
                   && !unsafe_copy_elision_p (fa, arg)))
        {
-         tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
-                                                               complain));
+         tree to = cp_stabilize_reference (cp_build_indirect_ref (fa,
+                                                                  RO_NULL,
+                                                                  complain));
 
          val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
          return val;
@@ -7655,7 +7656,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
           && trivial_fn_p (fn)
           && !DECL_DELETED_FN (fn))
     {
-      tree to = stabilize_reference
+      tree to = cp_stabilize_reference
        (cp_build_indirect_ref (argarray[0], RO_NULL, complain));
       tree type = TREE_TYPE (to);
       tree as_base = CLASSTYPE_AS_BASE (type);
index ec92718626c22d52670b0013307b92acbc02609d..0e46ae17f0ccd21b36f99435fd3caccf1b78a6ce 100644 (file)
@@ -6494,6 +6494,7 @@ extern cp_lvalue_kind real_lvalue_p               (const_tree);
 extern cp_lvalue_kind lvalue_kind              (const_tree);
 extern bool lvalue_or_rvalue_with_address_p    (const_tree);
 extern bool xvalue_p                           (const_tree);
+extern tree cp_stabilize_reference             (tree);
 extern bool builtin_valid_in_constant_expr_p    (const_tree);
 extern tree build_min                          (enum tree_code, tree, ...);
 extern tree build_min_nt_loc                   (location_t, enum tree_code,
index 381c24faa3d2915da30af362c174b3555dfef1e2..5b5d5ba48f95dcfbda21f099bcf7b2546678c02d 100644 (file)
@@ -296,6 +296,45 @@ xvalue_p (const_tree ref)
   return (lvalue_kind (ref) == clk_rvalueref);
 }
 
+/* C++-specific version of stabilize_reference.  */
+
+tree
+cp_stabilize_reference (tree ref)
+{
+  switch (TREE_CODE (ref))
+    {
+    /* We need to treat specially anything stabilize_reference doesn't
+       handle specifically.  */
+    case VAR_DECL:
+    case PARM_DECL:
+    case RESULT_DECL:
+    CASE_CONVERT:
+    case FLOAT_EXPR:
+    case FIX_TRUNC_EXPR:
+    case INDIRECT_REF:
+    case COMPONENT_REF:
+    case BIT_FIELD_REF:
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+    case ERROR_MARK:
+      break;
+    default:
+      cp_lvalue_kind kind = lvalue_kind (ref);
+      if ((kind & ~clk_class) != clk_none)
+       {
+         tree type = unlowered_expr_type (ref);
+         bool rval = !!(kind & clk_rvalueref);
+         type = cp_build_reference_type (type, rval);
+         /* This inhibits warnings in, eg, cxx_mark_addressable
+            (c++/60955).  */
+         warning_sentinel s (extra_warnings);
+         ref = build_static_cast (type, ref, tf_error);
+       }
+    }
+
+  return stabilize_reference (ref);
+}
+
 /* Test whether DECL is a builtin that may appear in a
    constant-expression. */
 
index cef5604bd0b478255f02e3a5eb15c63effd3e68f..7e12009a5e5fe0da53dfa1e3af6550579f0b158b 100644 (file)
@@ -5912,7 +5912,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
        {
          tree real, imag;
 
-         arg = stabilize_reference (arg);
+         arg = cp_stabilize_reference (arg);
          real = cp_build_unary_op (REALPART_EXPR, arg, 1, complain);
          imag = cp_build_unary_op (IMAGPART_EXPR, arg, 1, complain);
          real = cp_build_unary_op (code, real, 1, complain);
@@ -6112,7 +6112,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
       tree lvalue = TREE_OPERAND (arg, 0);
       if (TREE_SIDE_EFFECTS (lvalue))
        {
-         lvalue = stabilize_reference (lvalue);
+         lvalue = cp_stabilize_reference (lvalue);
          arg = build2 (TREE_CODE (arg), TREE_TYPE (arg),
                        lvalue, TREE_OPERAND (arg, 1));
        }
@@ -7496,7 +7496,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     case PREINCREMENT_EXPR:
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
        lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
-                     stabilize_reference (TREE_OPERAND (lhs, 0)),
+                     cp_stabilize_reference (TREE_OPERAND (lhs, 0)),
                      TREE_OPERAND (lhs, 1));
       newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 0),
                                     modifycode, rhs, complain);
@@ -7516,7 +7516,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
     case MODIFY_EXPR:
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
        lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
-                     stabilize_reference (TREE_OPERAND (lhs, 0)),
+                     cp_stabilize_reference (TREE_OPERAND (lhs, 0)),
                      TREE_OPERAND (lhs, 1));
       newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs,
                                     complain);
@@ -7665,7 +7665,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
             not intervene between the lvalue-to-rvalue conversion and the
             side effect associated with any single compound assignment
             operator. -- end note ]  */
-         lhs = stabilize_reference (lhs);
+         lhs = cp_stabilize_reference (lhs);
          rhs = rvalue (rhs);
          rhs = stabilize_expr (rhs, &init);
          newrhs = cp_build_binary_op (input_location,
index da1838c10073c7fbaf75ea1e4d9062022bcb8687..de57f567c2016da1704518207e2413479a4da773 100644 (file)
@@ -1,3 +1,8 @@
+2016-04-26  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/70744
+       * g++.dg/ext/cond2.C: New test.
+
 2016-04-26  Bin Cheng  <bin.cheng@arm.com>
 
        PR tree-optimization/70771
diff --git a/gcc/testsuite/g++.dg/ext/cond2.C b/gcc/testsuite/g++.dg/ext/cond2.C
new file mode 100644 (file)
index 0000000..d9f1d59
--- /dev/null
@@ -0,0 +1,28 @@
+// PR c++/70744
+// { dg-do run }
+// { dg-options "" }
+
+static void
+fn1 (void)
+{
+  int x = 2;
+  ++x ? : 42;
+  if (x != 3)
+    __builtin_abort ();
+  --x ? : 42;
+  if (x != 2)
+    __builtin_abort ();
+  x++ ? : 42;
+  if (x != 3)
+    __builtin_abort ();
+  x-- ? : 42;
+  if (x != 2)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  fn1 ();
+  return 0;
+}