summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--parse.y28
-rw-r--r--test/ruby/test_parse.rb84
3 files changed, 97 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 8431ecfb4b..01a0bc4063 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sat Aug 13 10:52:19 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * parse.y (stmt, arg): rescue modifier in command op assignment
+ should be limited to rhs only. [ruby-core:75621] [Bug #12402]
+
Sat Aug 13 07:51:40 2016 Masaki Suketa <masaki.suketa@nifty.ne.jp>
* ext/win32ole/win32ole.c (ole_val2variant): fix integer conversion in
diff --git a/parse.y b/parse.y
index afe56e5664..41a164c02a 100644
--- a/parse.y
+++ b/parse.y
@@ -1284,12 +1284,12 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
$$ = dispatch2(massign, $1, $3);
%*/
}
- | var_lhs tOP_ASGN command_call
+ | var_lhs tOP_ASGN command_rhs
{
value_expr($3);
$$ = new_op_assign($1, $2, $3);
}
- | primary_value '[' opt_call_args rbracket tOP_ASGN command_call
+ | primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
{
/*%%%*/
NODE *args;
@@ -1310,27 +1310,27 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
$$ = dispatch3(opassign, $$, $5, $6);
%*/
}
- | primary_value call_op tIDENTIFIER tOP_ASGN command_call
+ | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
{
value_expr($5);
$$ = new_attr_op_assign($1, $2, $3, $4, $5);
}
- | primary_value call_op tCONSTANT tOP_ASGN command_call
+ | primary_value call_op tCONSTANT tOP_ASGN command_rhs
{
value_expr($5);
$$ = new_attr_op_assign($1, $2, $3, $4, $5);
}
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
{
$$ = const_path_field($1, $3);
$$ = new_const_op_assign($$, $4, $5);
}
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
{
value_expr($5);
$$ = new_attr_op_assign($1, idCOLON2, $3, $4, $5);
}
- | backref tOP_ASGN command_call
+ | backref tOP_ASGN command_rhs
{
$1 = var_field($1);
$$ = backref_assign_error($1, node_assign($1, $3));
@@ -2002,7 +2002,7 @@ arg : lhs '=' arg_rhs
{
$$ = new_op_assign($1, $2, $3);
}
- | primary_value '[' opt_call_args rbracket tOP_ASGN arg
+ | primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs
{
/*%%%*/
NODE *args;
@@ -2028,32 +2028,32 @@ arg : lhs '=' arg_rhs
$$ = dispatch3(opassign, $1, $5, $6);
%*/
}
- | primary_value call_op tIDENTIFIER tOP_ASGN arg
+ | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
{
value_expr($5);
$$ = new_attr_op_assign($1, $2, $3, $4, $5);
}
- | primary_value call_op tCONSTANT tOP_ASGN arg
+ | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
{
value_expr($5);
$$ = new_attr_op_assign($1, $2, $3, $4, $5);
}
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
{
value_expr($5);
$$ = new_attr_op_assign($1, idCOLON2, $3, $4, $5);
}
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
{
$$ = const_path_field($1, $3);
$$ = new_const_op_assign($$, $4, $5);
}
- | tCOLON3 tCONSTANT tOP_ASGN arg
+ | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
{
$$ = top_const_field($2);
$$ = new_const_op_assign($$, $3, $4);
}
- | backref tOP_ASGN arg
+ | backref tOP_ASGN arg_rhs
{
$1 = var_field($1);
$$ = backref_assign_error($1, new_op_assign($1, $2, $3));
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index 7f0177819e..434533fcab 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -876,12 +876,84 @@ x = __ENCODING__
def test_rescue_in_command_assignment
bug = '[ruby-core:75621] [Bug #12402]'
- v = bug
- v = raise(v) rescue "ok"
- assert_equal("ok", v)
- v = bug
- v = raise v rescue "ok"
- assert_equal("ok", v)
+ all_assertions(bug) do |a|
+ a.for("lhs = arg") do
+ v = bug
+ v = raise(bug) rescue "ok"
+ assert_equal("ok", v)
+ end
+ a.for("lhs op_asgn arg") do
+ v = 0
+ v += raise(bug) rescue 1
+ assert_equal(1, v)
+ end
+ a.for("lhs[] op_asgn arg") do
+ v = [0]
+ v[0] += raise(bug) rescue 1
+ assert_equal([1], v)
+ end
+ a.for("lhs.m op_asgn arg") do
+ k = Struct.new(:m)
+ v = k.new(0)
+ v.m += raise(bug) rescue 1
+ assert_equal(k.new(1), v)
+ end
+ a.for("lhs::m op_asgn arg") do
+ k = Struct.new(:m)
+ v = k.new(0)
+ v::m += raise(bug) rescue 1
+ assert_equal(k.new(1), v)
+ end
+ a.for("lhs.C op_asgn arg") do
+ k = Struct.new(:C)
+ v = k.new(0)
+ v.C += raise(bug) rescue 1
+ assert_equal(k.new(1), v)
+ end
+ a.for("lhs::C op_asgn arg") do
+ v = Class.new
+ v::C ||= raise(bug) rescue 1
+ assert_equal(1, v::C)
+ end
+ a.for("lhs = command") do
+ v = bug
+ v = raise bug rescue "ok"
+ assert_equal("ok", v)
+ end
+ a.for("lhs op_asgn command") do
+ v = 0
+ v += raise bug rescue 1
+ assert_equal(1, v)
+ end
+ a.for("lhs[] op_asgn command") do
+ v = [0]
+ v[0] += raise bug rescue 1
+ assert_equal([1], v)
+ end
+ a.for("lhs.m op_asgn command") do
+ k = Struct.new(:m)
+ v = k.new(0)
+ v.m += raise bug rescue 1
+ assert_equal(k.new(1), v)
+ end
+ a.for("lhs::m op_asgn command") do
+ k = Struct.new(:m)
+ v = k.new(0)
+ v::m += raise bug rescue 1
+ assert_equal(k.new(1), v)
+ end
+ a.for("lhs.C op_asgn command") do
+ k = Struct.new(:C)
+ v = k.new(0)
+ v.C += raise bug rescue 1
+ assert_equal(k.new(1), v)
+ end
+ a.for("lhs::C op_asgn command") do
+ v = Class.new
+ v::C ||= raise bug rescue 1
+ assert_equal(1, v::C)
+ end
+ end
end
=begin