1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

parse.y: remove duplicate keys

* parse.y (remove_duplicate_keys): remove duplicate literal keys,
  i.e., symbols and strings.  [ruby-core:65368] [Bug #10315]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47879 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2014-10-11 04:47:06 +00:00
parent 8771d1a0fc
commit 5fa4d56263
2 changed files with 68 additions and 8 deletions

View file

@ -1,4 +1,7 @@
Sat Oct 11 13:46:58 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
Sat Oct 11 13:47:13 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (remove_duplicate_keys): remove duplicate literal keys,
i.e., symbols and strings. [ruby-core:65368] [Bug #10315]
* vm.c (kwmerge_i): override existing keys by new keys.
[ruby-core:65368] [Bug #10315]

71
parse.y
View file

@ -430,6 +430,9 @@ static NODE *new_attr_op_assign_gen(struct parser_params *parser, NODE *lhs, ID
static NODE *new_const_op_assign_gen(struct parser_params *parser, NODE *lhs, ID op, NODE *rhs);
#define new_const_op_assign(lhs, op, rhs) new_const_op_assign_gen(parser, (lhs), (op), (rhs))
static NODE *new_hash_gen(struct parser_params *parser, NODE *hash);
#define new_hash(hash) new_hash_gen(parser, (hash))
#define new_defined(expr) NEW_DEFINED(remove_begin_all(expr))
static NODE *match_op_gen(struct parser_params*,NODE*,NODE*);
@ -2348,7 +2351,7 @@ aref_args : none
| args ',' assocs trailer
{
/*%%%*/
$$ = arg_append($1, NEW_HASH($3));
$$ = arg_append($1, new_hash($3));
/*%
$$ = arg_add_assocs($1, $3);
%*/
@ -2356,7 +2359,7 @@ aref_args : none
| assocs trailer
{
/*%%%*/
$$ = NEW_LIST(NEW_HASH($1));
$$ = NEW_LIST(new_hash($1));
/*%
$$ = arg_add_assocs(arg_new(), $1);
%*/
@ -2386,7 +2389,7 @@ opt_call_args : none
| args ',' assocs ','
{
/*%%%*/
$$ = arg_append($1, NEW_HASH($3));
$$ = arg_append($1, new_hash($3));
/*%
$$ = arg_add_assocs($1, $3);
%*/
@ -2394,7 +2397,7 @@ opt_call_args : none
| assocs ','
{
/*%%%*/
$$ = NEW_LIST(NEW_HASH($1));
$$ = NEW_LIST(new_hash($1));
/*%
$$ = arg_add_assocs(arg_new(), $1);
%*/
@ -2421,7 +2424,7 @@ call_args : command
| assocs opt_block_arg
{
/*%%%*/
$$ = NEW_LIST(NEW_HASH($1));
$$ = NEW_LIST(new_hash($1));
$$ = arg_blk_pass($$, $2);
/*%
$$ = arg_add_assocs(arg_new(), $1);
@ -2431,7 +2434,7 @@ call_args : command
| args ',' assocs opt_block_arg
{
/*%%%*/
$$ = arg_append($1, NEW_HASH($3));
$$ = arg_append($1, new_hash($3));
$$ = arg_blk_pass($$, $4);
/*%
$$ = arg_add_optblock(arg_add_assocs($1, $3), $4);
@ -2675,7 +2678,7 @@ primary : literal
| tLBRACE assoc_list '}'
{
/*%%%*/
$$ = NEW_HASH($2);
$$ = new_hash($2);
/*%
$$ = dispatch1(hash, escape_Qundef($2));
%*/
@ -9592,6 +9595,60 @@ dsym_node_gen(struct parser_params *parser, NODE *node)
}
return node;
}
static int
append_literal_keys(st_data_t k, st_data_t v, st_data_t h)
{
NODE *node = (NODE *)v;
NODE **result = (NODE **)h;
node->nd_alen = 2;
node->nd_next->nd_end = node->nd_next;
node->nd_next->nd_next = 0;
if (*result)
list_concat(*result, node);
else
*result = node;
return ST_CONTINUE;
}
static NODE *
remove_duplicate_keys(struct parser_params *parser, NODE *hash)
{
st_table *literal_keys = st_init_numtable_with_size(hash->nd_alen / 2);
NODE *result = 0;
while (hash && hash->nd_head && hash->nd_next) {
NODE *head = hash->nd_head;
VALUE key = 0;
st_data_t data;
if (nd_type(head) == NODE_LIT) {
key = head->nd_lit;
if (st_lookup(literal_keys, key, &data)) {
rb_compile_warn(ruby_sourcefile, nd_line((NODE *)data),
"duplicated key at line %d ignored: %+"PRIsVALUE,
nd_line(head), head->nd_lit);
}
}
else {
key = (VALUE)head;
}
st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
hash = hash->nd_next->nd_next;
}
st_foreach(literal_keys, append_literal_keys, (st_data_t)&result);
st_free_table(literal_keys);
if (hash) {
if (!result) result = hash;
else list_concat(result, hash);
}
return result;
}
static NODE *
new_hash_gen(struct parser_params *parser, NODE *hash)
{
if (hash) hash = remove_duplicate_keys(parser, hash);
return NEW_HASH(hash);
}
#endif /* !RIPPER */
#ifndef RIPPER