summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--error.c67
-rw-r--r--internal.h2
-rw-r--r--iseq.c4
-rw-r--r--load.c9
-rw-r--r--parse.y41
-rw-r--r--ruby.c8
-rw-r--r--test/ruby/test_iseq.rb21
-rw-r--r--vm_core.h6
-rw-r--r--vm_eval.c5
10 files changed, 103 insertions, 73 deletions
diff --git a/ChangeLog b/ChangeLog
index 1bd399a2ba..bf4075e5d4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Sat Mar 19 14:46:18 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * iseq.c (rb_iseq_compile_with_option): make the parser in mild
+ error.
+
+ * load.c (rb_load_internal0): ditto.
+
+ * parse.y (yycompile0): return the error message within the error
+ to be raised. [Feature #11951]
+
+ * parse.y (parser_compile_error): accumulate error messages in the
+ error_buffer.
+
Sat Mar 19 03:57:13 2016 NARUSE, Yui <naruse@ruby-lang.org>
* time.c (LOCALTIME): organize #ifdefs.
diff --git a/error.c b/error.c
index 93cb6f03d6..6bd45bd021 100644
--- a/error.c
+++ b/error.c
@@ -94,88 +94,53 @@ compile_snprintf(rb_encoding *enc, const char *pre, const char *file, int line,
return str;
}
-static void
-compile_err_append(VALUE mesg)
+VALUE
+rb_compile_err_append(VALUE buffer, VALUE mesg)
{
rb_thread_t *th = GET_THREAD();
- VALUE err = th->errinfo;
rb_block_t *prev_base_block = th->base_block;
th->base_block = 0;
/* base_block should be zero while normal Ruby execution */
/* after this line, any Ruby code *can* run */
- if (th->mild_compile_error) {
- if (RTEST(err)) {
- VALUE str = rb_obj_as_string(err);
-
- rb_str_cat2(str, "\n");
- rb_str_append(str, mesg);
- mesg = str;
- }
- err = rb_exc_new3(rb_eSyntaxError, mesg);
- th->errinfo = err;
- }
- else {
- if (!RTEST(err)) {
- err = rb_exc_new2(rb_eSyntaxError, "compile error");
- th->errinfo = err;
- }
+ if (!buffer) {
rb_str_cat2(mesg, "\n");
rb_write_error_str(mesg);
}
+ else if (NIL_P(buffer)) {
+ buffer = mesg;
+ }
+ else {
+ rb_str_cat2(buffer, "\n");
+ rb_str_append(buffer, mesg);
+ }
/* returned to the parser world */
th->base_block = prev_base_block;
+ return buffer;
}
void
rb_compile_error_with_enc(const char *file, int line, void *enc, const char *fmt, ...)
{
- va_list args;
- VALUE str;
-
- va_start(args, fmt);
- str = compile_snprintf(enc, NULL, file, line, fmt, args);
- va_end(args);
- compile_err_append(str);
}
void
rb_compile_error(const char *file, int line, const char *fmt, ...)
{
- va_list args;
- VALUE str;
-
- va_start(args, fmt);
- str = compile_snprintf(NULL, NULL, file, line, fmt, args);
- va_end(args);
- compile_err_append(str);
}
-void
-rb_compile_error_str(VALUE file, int line, void *enc, const char *fmt, ...)
+VALUE
+rb_error_vsprintf(VALUE file, int line, void *enc, const char *fmt, va_list args)
{
- va_list args;
- VALUE str;
-
- va_start(args, fmt);
- str = compile_snprintf(enc, NULL,
- NIL_P(file) ? NULL : RSTRING_PTR(file), line,
- fmt, args);
- va_end(args);
- compile_err_append(str);
+ return compile_snprintf(enc, NULL,
+ NIL_P(file) ? NULL : RSTRING_PTR(file), line,
+ fmt, args);
}
void
rb_compile_error_append(const char *fmt, ...)
{
- va_list args;
- VALUE str;
-
- va_start(args, fmt);
- str = rb_vsprintf(fmt, args);
- va_end(args);
- compile_err_append(str);
}
static void
diff --git a/internal.h b/internal.h
index a65a59ee03..fcdab106cc 100644
--- a/internal.h
+++ b/internal.h
@@ -1074,6 +1074,8 @@ struct RBasicRaw {
#endif
VALUE rb_parser_get_yydebug(VALUE);
VALUE rb_parser_set_yydebug(VALUE, VALUE);
+VALUE rb_parser_mild_error(VALUE parser);
+void *rb_parser_load_file(VALUE parser, VALUE name);
int rb_is_const_name(VALUE name);
int rb_is_class_name(VALUE name);
int rb_is_global_name(VALUE name);
diff --git a/iseq.c b/iseq.c
index 01e6d44add..7f187b84a1 100644
--- a/iseq.c
+++ b/iseq.c
@@ -627,11 +627,13 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE li
const INITIALIZED VALUE label = parent ?
parent->body->location.label :
rb_fstring_cstr("<compiled>");
+ VALUE parser = rb_parser_new();
+ rb_parser_mild_error(parser);
th->base_block = base_block;
TH_PUSH_TAG(th);
if ((state = EXEC_TAG()) == 0) {
- NODE *node = (*parse)(rb_parser_new(), file, src, ln);
+ NODE *node = (*parse)(parser, file, src, ln);
if (node) { /* TODO: check err */
iseq = rb_iseq_new_with_opt(node, label, file, absolute_path, line,
parent, type, &option);
diff --git a/load.c b/load.c
index 4558e2c6fd..f00cceb696 100644
--- a/load.c
+++ b/load.c
@@ -583,7 +583,6 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
int state;
volatile VALUE wrapper = th->top_wrapper;
volatile VALUE self = th->top_self;
- volatile int mild_compile_error;
#if !defined __GNUC__
rb_thread_t *volatile th0 = th;
#endif
@@ -600,7 +599,6 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
rb_extend_object(th->top_self, th->top_wrapper);
}
- mild_compile_error = th->mild_compile_error;
TH_PUSH_TAG(th);
state = EXEC_TAG();
if (state == 0) {
@@ -611,10 +609,10 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
/* OK */
}
else {
- th->mild_compile_error++;
- node = (NODE *)rb_load_file_str(fname);
+ VALUE parser = rb_parser_new();
+ rb_parser_mild_error(parser);
+ node = (NODE *)rb_parser_load_file(parser, fname);
iseq = rb_iseq_new_top(node, rb_str_new2("<top (required)>"), fname, rb_realpath_internal(Qnil, fname, 1), NULL);
- th->mild_compile_error--;
}
rb_iseq_eval(iseq);
}
@@ -624,7 +622,6 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap)
th = th0;
fname = RB_GC_GUARD(fname);
#endif
- th->mild_compile_error = mild_compile_error;
th->top_self = self;
th->top_wrapper = wrapper;
diff --git a/parse.y b/parse.y
index f3319d18e1..57ee29782c 100644
--- a/parse.y
+++ b/parse.y
@@ -312,6 +312,7 @@ struct parser_params {
NODE *eval_tree_begin;
NODE *eval_tree;
+ VALUE error_buffer;
VALUE debug_lines;
VALUE coverage;
#else
@@ -740,7 +741,6 @@ static ID id_warn, id_warning;
# define WARNING_ARGS_L(l, fmt,n) WARNING_ARGS(fmt,n)
# define WARNING_CALL rb_funcall
static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
-# define rb_compile_error ripper_compile_error
# define compile_error ripper_compile_error
# define PARSER_ARG parser,
#else
@@ -753,9 +753,9 @@ static void ripper_compile_error(struct parser_params*, const char *fmt, ...);
# define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n)
# define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n)
# define WARNING_CALL rb_compile_warning
-# define rb_compile_error rb_compile_error_str
-# define compile_error (parser->error_p = 1),rb_compile_error_str
-# define PARSER_ARG ruby_sourcefile_string, ruby_sourceline, (void *)current_enc,
+static void parser_compile_error(struct parser_params*, const char *fmt, ...);
+# define compile_error parser_compile_error
+# define PARSER_ARG parser,
#endif
/* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
@@ -5559,6 +5559,9 @@ yycompile0(VALUE arg)
lex_p = lex_pbeg = lex_pend = 0;
lex_lastline = lex_nextline = 0;
if (parser->error_p) {
+ VALUE mesg = parser->error_buffer;
+ if (!mesg) mesg = rb_fstring_cstr("compile error");
+ rb_set_errinfo(rb_exc_new_str(rb_eSyntaxError, mesg));
return 0;
}
tree = ruby_eval_tree;
@@ -10792,6 +10795,8 @@ parser_initialize(struct parser_params *parser)
parser->delayed = Qnil;
parser->result = Qnil;
parser->parsing_thread = Qnil;
+#else
+ parser->error_buffer = Qfalse;
#endif
parser->debug_buffer = Qnil;
parser->enc = rb_utf8_encoding();
@@ -10818,6 +10823,7 @@ parser_mark(void *ptr)
rb_gc_mark((VALUE)ruby_eval_tree);
rb_gc_mark(ruby_debug_lines);
rb_gc_mark(parser->compile_option);
+ rb_gc_mark(parser->error_buffer);
#else
rb_gc_mark(parser->delayed);
rb_gc_mark(parser->value);
@@ -10901,6 +10907,16 @@ rb_parser_new(void)
parser_initialize(p);
return parser;
}
+
+VALUE
+rb_parser_mild_error(VALUE vparser)
+{
+ struct parser_params *parser;
+
+ TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, parser);
+ parser->error_buffer = Qnil;
+ return vparser;
+}
#endif
#ifdef RIPPER
@@ -11069,6 +11085,23 @@ rb_parser_printf(struct parser_params *parser, const char *fmt, ...)
parser->debug_buffer = Qnil;
}
}
+
+extern VALUE rb_error_vsprintf(VALUE, int, void *, const char *, va_list);
+extern VALUE rb_compile_err_append(VALUE buffer, VALUE mesg);
+
+static void
+parser_compile_error(struct parser_params *parser, const char *fmt, ...)
+{
+ VALUE str;
+ va_list ap;
+
+ parser->error_p = 1;
+ va_start(ap, fmt);
+ str = rb_error_vsprintf(ruby_sourcefile_string, ruby_sourceline,
+ (void *)current_enc, fmt, ap);
+ va_end(ap);
+ parser->error_buffer = rb_compile_err_append(parser->error_buffer, str);
+}
#endif
#ifdef RIPPER
diff --git a/ruby.c b/ruby.c
index f96202e217..d163f40dc5 100644
--- a/ruby.c
+++ b/ruby.c
@@ -1948,6 +1948,14 @@ rb_load_file_str(VALUE fname_v)
return load_file(rb_parser_new(), fname_v, 0, cmdline_options_init(&opt));
}
+void *
+rb_parser_load_file(VALUE parser, VALUE fname_v)
+{
+ struct cmdline_options opt;
+
+ return load_file(parser, fname_v, 0, cmdline_options_init(&opt));
+}
+
/*
* call-seq:
* Process.argv0 -> frozen_string
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index f9123109f7..e0c5329edc 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -214,4 +214,25 @@ class TestISeq < Test::Unit::TestCase
at_exit { assert_equal([:n, :x], Segfault.new.segfault.sort) }
end;
end
+
+ def test_syntax_error_message
+ feature11951 = '[Feature #11951]'
+
+ src, line = <<-'end;', __LINE__+1
+ def x@;end
+ def y@;end
+ end;
+ e1 = e2 = nil
+ m1 = EnvUtil.verbose_warning do
+ e1 = assert_raise(SyntaxError) do
+ eval(src, nil, __FILE__, line)
+ end
+ end
+ m2 = EnvUtil.verbose_warning do
+ e2 = assert_raise(SyntaxError) do
+ ISeq.new(src, __FILE__, __FILE__, line)
+ end
+ end
+ assert_equal([m1, e1.message], [m2, e2.message], feature11951)
+ end
end
diff --git a/vm_core.h b/vm_core.h
index ae6fd614c1..92277f17db 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -750,12 +750,6 @@ typedef struct rb_thread_struct {
*/
int parse_in_eval;
- /*! Thread-local state of compiling context.
- *
- * If non-zero, the parser does not automatically print error messages to
- * stderr. */
- int mild_compile_error;
-
/* storage */
st_table *local_storage;
VALUE local_storage_recursive_hash;
diff --git a/vm_eval.c b/vm_eval.c
index 686b7e030c..9f2762fc1a 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1284,7 +1284,6 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
rb_env_t *env = NULL;
rb_block_t block, *base_block;
volatile int parse_in_eval;
- volatile int mild_compile_error;
volatile VALUE file;
volatile int line;
@@ -1292,7 +1291,6 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
line = lineno;
parse_in_eval = th->parse_in_eval;
- mild_compile_error = th->mild_compile_error;
TH_PUSH_TAG(th);
if ((state = TH_EXEC_TAG()) == 0) {
rb_cref_t *cref = cref_arg;
@@ -1343,9 +1341,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
/* make eval iseq */
th->parse_in_eval++;
- th->mild_compile_error++;
iseq = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil);
- th->mild_compile_error--;
th->parse_in_eval--;
if (!cref && base_block->iseq) {
@@ -1373,7 +1369,6 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
result = vm_exec(th);
}
TH_POP_TAG();
- th->mild_compile_error = mild_compile_error;
th->parse_in_eval = parse_in_eval;
if (state) {