summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.y9
-rw-r--r--symbol.c2
-rw-r--r--symbol.h2
-rw-r--r--test/ruby/test_regexp.rb6
4 files changed, 14 insertions, 5 deletions
diff --git a/parse.y b/parse.y
index 278c5b0296..09afa6bedd 100644
--- a/parse.y
+++ b/parse.y
@@ -10669,11 +10669,12 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
ID var;
NODE *node, *succ;
- if (!len || (*name != '_' && ISASCII(*name) && !rb_enc_islower(*name, enc)) ||
- (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) ||
- !rb_enc_symname2_p(s, len, enc)) {
+ if (!len) return ST_CONTINUE;
+ if (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len))
return ST_CONTINUE;
- }
+ if (rb_enc_symname_type(s, len, enc, (1U<<ID_LOCAL)) != ID_LOCAL)
+ return ST_CONTINUE;
+
var = intern_cstr(s, len, enc);
node = node_assign(p, assignable(p, var, 0, arg->loc), NEW_LIT(ID2SYM(var), arg->loc), arg->loc);
succ = arg->succ_block;
diff --git a/symbol.c b/symbol.c
index d7fedf5b38..ae6003ef15 100644
--- a/symbol.c
+++ b/symbol.c
@@ -238,7 +238,7 @@ rb_sym_constant_char_p(const char *name, long nlen, rb_encoding *enc)
#define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST))
#define IDSET_ATTRSET_FOR_INTERN (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET))
-static int
+int
rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
{
const char *m = name;
diff --git a/symbol.h b/symbol.h
index 7d147a4bd1..56568a91fc 100644
--- a/symbol.h
+++ b/symbol.h
@@ -98,6 +98,8 @@ is_global_name_punct(const int c)
return (ruby_global_name_punct_bits[(c - 0x20) / 32] >> (c % 32)) & 1;
}
+int rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset);
+
RUBY_SYMBOL_EXPORT_BEGIN
size_t rb_sym_immortal_count(void);
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 9a00888846..f8800468b3 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -216,6 +216,12 @@ class TestRegexp < Test::Unit::TestCase
assert_not_include(local_variables, :nil, "[ruby-dev:32675]")
end
+ def test_assign_named_capture_to_const
+ %W[C \u{1d402}].each do |name|
+ assert_equal(:ok, Class.new.class_eval("#{name} = :ok; /(?<#{name}>.*)/ =~ 'ng'; #{name}"))
+ end
+ end
+
def test_assign_named_capture_trace
bug = '[ruby-core:79940] [Bug #13287]'
assert_normal_exit("#{<<-"begin;"}\n#{<<-"end;"}", bug)