aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compile.c14
-rw-r--r--insns.def6
-rw-r--r--test/ruby/test_const.rb6
-rw-r--r--vm_insnhelper.c6
4 files changed, 19 insertions, 13 deletions
diff --git a/compile.c b/compile.c
index 7f2fd17f1f..eea013befd 100644
--- a/compile.c
+++ b/compile.c
@@ -4404,18 +4404,18 @@ compile_const_prefix(rb_iseq_t *iseq, const NODE *const node,
switch (nd_type(node)) {
case NODE_CONST:
debugi("compile_const_prefix - colon", node->nd_vid);
- ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid));
+ ADD_INSN2(body, nd_line(node), getconstant, ID2SYM(node->nd_vid), 1);
break;
case NODE_COLON3:
debugi("compile_const_prefix - colon3", node->nd_mid);
ADD_INSN(body, nd_line(node), pop);
ADD_INSN1(body, nd_line(node), putobject, rb_cObject);
- ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
+ ADD_INSN2(body, nd_line(node), getconstant, ID2SYM(node->nd_mid), 1);
break;
case NODE_COLON2:
CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
debugi("compile_const_prefix - colon2", node->nd_mid);
- ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
+ ADD_INSN2(body, nd_line(node), getconstant, ID2SYM(node->nd_mid), 0);
break;
default:
CHECK(COMPILE(pref, "const colon2 prefix", node));
@@ -7154,7 +7154,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
ADD_INSNL(ret, line, branchunless, lassign); /* cref */
}
ADD_INSN(ret, line, dup); /* cref cref */
- ADD_INSN1(ret, line, getconstant, ID2SYM(mid)); /* cref obj */
+ ADD_INSN2(ret, line, getconstant, ID2SYM(mid), 1); /* cref obj */
if (node->nd_aid == idOROP || node->nd_aid == idANDOP) {
lfin = NEW_LABEL(line);
@@ -7500,13 +7500,13 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
int ic_index = body->is_size++;
ADD_INSN2(ret, line, opt_getinlinecache, lend, INT2FIX(ic_index));
- ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
+ ADD_INSN2(ret, line, getconstant, ID2SYM(node->nd_vid), 1);
ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index));
ADD_LABEL(ret, lend);
}
else {
ADD_INSN(ret, line, putnil);
- ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_vid));
+ ADD_INSN2(ret, line, getconstant, ID2SYM(node->nd_vid), 1);
}
if (popped) {
@@ -7893,7 +7893,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
}
ADD_INSN1(ret, line, putobject, rb_cObject);
- ADD_INSN1(ret, line, getconstant, ID2SYM(node->nd_mid));
+ ADD_INSN2(ret, line, getconstant, ID2SYM(node->nd_mid), 1);
if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
ADD_INSN1(ret, line, opt_setinlinecache, INT2FIX(ic_index));
diff --git a/insns.def b/insns.def
index 6cfb3b121f..e84fcecfe7 100644
--- a/insns.def
+++ b/insns.def
@@ -252,19 +252,19 @@ setclassvariable
rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id, val);
}
-/* Get constant variable id. If klass is Qnil, constants
+/* Get constant variable id. If klass is Qnil and allow_nil is true, constants
are searched in the current scope. Otherwise, get constant under klass
class or module.
*/
DEFINE_INSN
getconstant
-(ID id)
+(ID id, VALUE allow_nil)
(VALUE klass)
(VALUE val)
/* getconstant can kick autoload */
// attr bool leaf = false; /* has rb_autoload_load() */
{
- val = vm_get_ev_const(ec, klass, id, 0);
+ val = vm_get_ev_const(ec, klass, id, allow_nil, 0);
}
/* Set constant variable id under cbase class or module.
diff --git a/test/ruby/test_const.rb b/test/ruby/test_const.rb
index 8784e0e988..6284434db0 100644
--- a/test/ruby/test_const.rb
+++ b/test/ruby/test_const.rb
@@ -48,6 +48,12 @@ class TestConst < Test::Unit::TestCase
assert_equal 8, TEST4
end
+ def test_const_access_from_nil
+ assert_raise(TypeError) { eval("nil::Object") }
+ assert_raise(TypeError) { eval("c = nil; c::Object") }
+ assert_raise(TypeError) { eval("sc = Class.new; sc::C = nil; sc::C::Object") }
+ end
+
def test_redefinition
c = Class.new
name = "X\u{5b9a 6570}"
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index cc38a0dc4b..1b985f4e8d 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -890,12 +890,12 @@ vm_get_iclass(rb_control_frame_t *cfp, VALUE klass)
}
static inline VALUE
-vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, int is_defined)
+vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, int allow_nil, int is_defined)
{
void rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id);
VALUE val;
- if (orig_klass == Qnil) {
+ if (orig_klass == Qnil && allow_nil) {
/* in current lexical scope */
const rb_cref_t *root_cref = vm_get_cref(ec->cfp->ep);
const rb_cref_t *cref;
@@ -3146,7 +3146,7 @@ vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_
}
case DEFINED_CONST:
klass = v;
- if (vm_get_ev_const(ec, klass, SYM2ID(obj), 1)) {
+ if (vm_get_ev_const(ec, klass, SYM2ID(obj), 1, 1)) {
expr_type = DEFINED_CONST;
}
break;