# HG changeset patch # User Lachlan Andrew # Date 1448593437 -39600 # Fri Nov 27 14:03:57 2015 +1100 # Branch production # Node ID 306d72ee094c452777cc2332be21439681260ddf # Parent ecb5849b2199f8986ae725ae5ebbef58d52e1f2a Fix bug #46536: Index errors in x.foo(...) used to report x(...). Also ; -> : libinterp/parse-tree/pt-idx.cc: final_index_error checks for multiple indexing Tests added. libinterp/parse-tree/pt-idx.h: const versions of three accessor functions liboctave/util/lo-array-gripes.cc: Replaced ';' in error message by ':' libinterp/corefcn/sub2ind.cc: changed tests to expect new format test/index.tst: changed tests to expect new format diff -r ecb5849b2199 -r 306d72ee094c libinterp/corefcn/sub2ind.cc --- a/libinterp/corefcn/sub2ind.cc Thu Nov 26 14:09:51 2015 +1100 +++ b/libinterp/corefcn/sub2ind.cc Fri Nov 27 14:03:57 2015 +1100 @@ -139,17 +139,17 @@ linear_index = sub2ind ([3, 3], 2, 3)\n\ # Test high index %!assert (sub2ind ([10 10 10], 10, 10, 10), 1000) -%!error sub2ind ([10 10 10], 11, 10, 10) -%!error sub2ind ([10 10 10], 10, 11, 10) -%!error sub2ind ([10 10 10], 10, 10, 11) +%!error sub2ind ([10 10 10], 11, 10, 10) +%!error sub2ind ([10 10 10], 10, 11, 10) +%!error sub2ind ([10 10 10], 10, 10, 11) # Test high index in the trailing dimensions %!assert (sub2ind ([10, 1], 2, 1, 1), 2) -%!error sub2ind ([10, 1], 1, 2, 1) -%!error sub2ind ([10, 1], 1, 1, 2) +%!error sub2ind ([10, 1], 1, 2, 1) +%!error sub2ind ([10, 1], 1, 1, 2) %!assert (sub2ind ([10 10], 2, 2, 1), 12) -%!error sub2ind ([10 10], 2, 1, 2) -%!error sub2ind ([10 10], 1, 2, 2) +%!error sub2ind ([10 10], 2, 1, 2) +%!error sub2ind ([10 10], 1, 2, 2) # Test handling of empty arguments %!assert (sub2ind ([10 10], zeros (0,0), zeros (0,0)), zeros (0,0)) diff -r ecb5849b2199 -r 306d72ee094c libinterp/parse-tree/pt-idx.cc --- a/libinterp/parse-tree/pt-idx.cc Thu Nov 26 14:09:51 2015 +1100 +++ b/libinterp/parse-tree/pt-idx.cc Fri Nov 27 14:03:57 2015 +1100 @@ -274,16 +274,55 @@ tree_index_expression::rvalue (int nargo // be needed by pt-lvalue, which calls subsref?) static void -final_index_error (index_exception& e, const tree_expression *expr) +final_index_error (index_exception& e, const tree_index_expression *ex) { - if (expr->is_identifier () - && dynamic_cast (expr)->is_variable ()) - e.set_var (expr->name ()); + if (ex && ex->expression () && ex->expression ()->is_identifier () + && dynamic_cast (ex->expression ()) + ->is_variable ()) + { + std::string prefix = ex->expression ()->name (); + std::list::const_iterator field + = (ex->arg_names ().begin ()); + // For x.foo(-1) or x.foo(-1).bar, find the "x.foo" + // For ambiguous cases like x(1).foo(-1) or x(-1).bar(1), say x<...>(-1) + for (unsigned int i = 0; i < ex->type_tags ().length (); i++, field++) + { + if (ex->type_tags ()[i] == '.') + prefix = prefix + "." + (*field)[0]; + else + { + for (unsigned int j = i+1; j < ex->type_tags ().length (); j++) + { + if (ex->type_tags ()[j] != '.') + { + prefix = ex->expression ()->name () + "<...>"; + break; + } + } + break; + } + } + e.set_var (prefix); + } std::string msg = e.message (); error_with_id (e.err_id (), msg.c_str ()); } +/* +%!test +% a.bar = 1; +% b.foo = a; +% c.fred = b; +% error b(-1) +% error b.foo(-1) +% error b.foo(-1).bar +% error b(1).foo(-1).bar +% error b(-1).foo(2).bar +% error b(-1).foo(2) +% error c.fred.foo.bar(-1) +*/ + octave_value_list tree_index_expression::rvalue (int nargout, const std::list *lvalue_list) @@ -388,7 +427,7 @@ tree_index_expression::rvalue (int nargo } catch (index_exception& e) // problems with index range, type etc. { - final_index_error (e, expr); + final_index_error (e, this); } } } @@ -430,7 +469,7 @@ tree_index_expression::rvalue (int nargo } catch (index_exception& e) // problems with range, invalid index type etc. { - final_index_error (e, expr); + final_index_error (e, this); } octave_value val = retval.length () ? retval(0) : octave_value (); @@ -499,7 +538,7 @@ tree_index_expression::lvalue (void) } catch (index_exception& e) // problems with range, invalid type etc. { - final_index_error (e, expr); + final_index_error (e, this); } tmpidx.clear (); } diff -r ecb5849b2199 -r 306d72ee094c libinterp/parse-tree/pt-idx.h --- a/libinterp/parse-tree/pt-idx.h Thu Nov 26 14:09:51 2015 +1100 +++ b/libinterp/parse-tree/pt-idx.h Fri Nov 27 14:03:57 2015 +1100 @@ -70,12 +70,15 @@ public: std::string name (void) const; tree_expression *expression (void) { return expr; } + const tree_expression *expression (void) const { return expr; } std::list arg_lists (void) { return args; } std::string type_tags (void) { return type; } + const std::string type_tags (void) const { return type; } std::list arg_names (void) { return arg_nm; } + const std::list arg_names (void) const { return arg_nm; } bool lvalue_ok (void) const { return expr->lvalue_ok (); } diff -r ecb5849b2199 -r 306d72ee094c liboctave/util/lo-array-gripes.cc --- a/liboctave/util/lo-array-gripes.cc Thu Nov 26 14:09:51 2015 +1100 +++ b/liboctave/util/lo-array-gripes.cc Fri Nov 27 14:03:57 2015 +1100 @@ -98,7 +98,7 @@ gripe_del_index_out_of_range (bool is1d, const char *err_id = error_id_index_out_of_bounds; (*current_liboctave_error_with_id_handler) - (err_id, "A(%s) = []: index out of bounds; value %d out of bound %d", + (err_id, "A(%s) = []: index out of bounds: value %d out of bound %d", is1d ? "I" : "..,I,..", idx, ext); } @@ -111,7 +111,7 @@ gripe_del_index_out_of_range (bool is1d, std::string index_exception::message (void) const { - std::string msg = expression () + "; " + details (); + std::string msg = expression () + ": " + details (); return msg.c_str (); } diff -r ecb5849b2199 -r 306d72ee094c test/index.tst --- a/test/index.tst Thu Nov 26 14:09:51 2015 +1100 +++ b/test/index.tst Fri Nov 27 14:03:57 2015 +1100 @@ -498,81 +498,81 @@ ## Test indexing of unnamed constants -%!error 1(0) -%!error 1(-1) -%!error {}(1,0.5) -%!error 1(NaN,1) -%!error [](1,1,{},1,1,1,1,1,1,1,1) -%!error 1(1,1,1,1,1,1,1,1,1,-1,1) -%!error 1(2) -%!error [](1) -%!error zeros(5,0)(3,1) -%!error zeros(0,5)(3,1) -%!error 1(1)(-1)(1) +%!error 1(0) +%!error 1(-1) +%!error {}(1,0.5) +%!error 1(NaN,1) +%!error [](1,1,{},1,1,1,1,1,1,1,1) +%!error 1(1,1,1,1,1,1,1,1,1,-1,1) +%!error 1(2) +%!error [](1) +%!error zeros(5,0)(3,1) +%!error zeros(0,5)(3,1) +%!error 1(1)(-1)(1) %! %!shared abc %! abc = [1, 2]; %! ## Test full matrices in variables -%!error abc([false, true, true]) -%!error abc(-1)(1)(1) -%! ## xerror abc(1)(-1)(1) ## why no 'xerror' test? +%!error abc([false, true, true]) +%!error abc(-1)(1)(1) +%!error abc(1)(-1)(1) %!shared abc %! abc = [1 2; 3 4]; -%!error abc(5) -%!error abc(2,3) -%!error exp (abc(2,3,0.5)) +%!error abc(5) +%!error abc(2,3) +%!error exp (abc(2,3,0.5)) %!shared abc %! abc = [1 2; 3 4]; abc(1,1,2) = 1; -%!error abc(2,5) -%!error abc(2,3,2) +%!error abc(2,5) +%!error abc(2,3,2) %!error abc(3,:) = [] %!error abc(3:50) = [] %!error abc(3,5) = [] %!error <=: nonconformant arguments \(op1 is 1x1, op2 is 1x5\)> abc(3,5) = 1:5 %! ## Test diagonal matrices, and access of function results -%!error eye(3)(2,3,5) -%!error eye(4)(-2,3) +%!error eye(3)(2,3,5) +%!error eye(4)(-2,3) %! ## Test cells %!shared abc %! abc = {1, 2; 3, 4}; -%!error abc(2,0.3,5) -%!error abc{2,0.3,5} -%!error abc{-2,1,1,1} -%!error abc(0,1,1,1) = 1 +%!error abc(2,0.3,5) +%!error abc{2,0.3,5} +%!error abc{-2,1,1,1} +%!error abc(0,1,1,1) = 1 %! ## Test permutation matrices %!shared abc %! abc = eye(3)([3 1 2],:); -%!error abc(NA) -%!error abc(1,1,1,Inf,1) +%!error abc(NA) +%!error abc(1,1,1,Inf,1) %! ## Test sparse matrices %!shared abc %! abc = sparse(3,3); -%!error abc(-1) -%!error abc(-1) = 1 -%!error abc(-1,1) -%!error abc(-1,1) = 1 +%!error abc(-1) +%!error abc(-1) = 1 +%!error abc(-1,1) +%!error abc(-1,1) = 1 %!error abc(0,0,0,0) -%!error abc(4,1) +%!error abc(4,1) %! ## Test ranges %!shared abc %! abc = 1:10; -%!error abc(-1) -%!error abc(-1,1) -%!error abc(4,1) +%!error abc(-1) +%!error abc(-1,1) +%!error abc(4,1) %! ## Test complex %!shared abc, z %! abc = [1 2]; -%!error abc(i) +%!error abc(i) %! abc = [1 2; 3 4]; -%!error abc(complex(1)) -%!error abc(1+0.5*i,3) -%!error abc(2,0-2*i) +%!error abc(complex(1)) +%!error abc(1+0.5*i,3) +%!error abc(2,0-2*i)