summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormpolacek <mpolacek@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-26 11:32:26 +0000
committermpolacek <mpolacek@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-26 11:32:26 +0000
commit514727a95513c8562210781384c40b3e30d54ef1 (patch)
tree5d86195cbde447cd506b7add671d38c96ba313f5
parentdb5c1c9a63c45e73f62263f873c699e3e30c9950 (diff)
downloadgcc-514727a95513c8562210781384c40b3e30d54ef1.tar.gz
Bootstrapped/regtested on x86_64-linux, ok for trunk?
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; +} git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235438 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/call.c9
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/tree.c39
-rw-r--r--gcc/cp/typeck.c10
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ext/cond2.C28
7 files changed, 96 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a81ffa0c0e2..c78abe83bbb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 11f2d42108e..476e806d419 100644
--- a/gcc/cp/call.c
+++ b/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 a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ec92718626c..0e46ae17f0c 100644
--- a/gcc/cp/cp-tree.h
+++ b/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 a/gcc/cp/tree.c b/gcc/cp/tree.c
index 381c24faa3d..5b5d5ba48f9 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index cef5604bd0b..7e12009a5e5 100644
--- a/gcc/cp/typeck.c
+++ b/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 a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index da1838c1007..de57f567c20 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..d9f1d59a3be
--- /dev/null
+++ b/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;
+}