1: %%
    2: %% %CopyrightBegin%
    3: %% 
    4: %% Copyright Ericsson AB 1997-2011. All Rights Reserved.
    5: %% 
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %% 
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %% 
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: -module(exception_SUITE).
   21: 
   22: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 
   23: 	 init_per_group/2,end_per_group/2, 
   24: 	 badmatch/1, pending_errors/1, nil_arith/1,
   25:          stacktrace/1, nested_stacktrace/1, raise/1, gunilla/1, per/1,
   26: 	 exception_with_heap_frag/1, line_numbers/1]).
   27: 
   28: -export([bad_guy/2]).
   29: -export([crash/1]).
   30: 
   31: -include_lib("test_server/include/test_server.hrl").
   32: -import(lists, [foreach/2]).
   33: 
   34: suite() -> [{ct_hooks,[ts_install_cth]}].
   35: 
   36: all() -> 
   37:     [badmatch, pending_errors, nil_arith, stacktrace,
   38:      nested_stacktrace, raise, gunilla, per,
   39:      exception_with_heap_frag, line_numbers].
   40: 
   41: groups() -> 
   42:     [].
   43: 
   44: init_per_suite(Config) ->
   45:     Config.
   46: 
   47: end_per_suite(_Config) ->
   48:     ok.
   49: 
   50: init_per_group(_GroupName, Config) ->
   51:     Config.
   52: 
   53: end_per_group(_GroupName, Config) ->
   54:     Config.
   55: 
   56: 
   57: -define(try_match(E),
   58: 	catch ?MODULE:bar(),
   59: 	{'EXIT', {{badmatch, nomatch}, _}} = (catch E = id(nomatch))).
   60: 
   61: %% Test that deliberately bad matches are reported correctly.
   62: 
   63: badmatch(Config) when is_list(Config) ->
   64:     ?line ?try_match(a),
   65:     ?line ?try_match(42),
   66:     ?line ?try_match({a, b, c}),
   67:     ?line ?try_match([]),
   68:     ?line ?try_match(1.0),
   69:     ok.
   70: 
   71: %% Test various exceptions, in the presence of a previous error suppressed
   72: %% in a guard.
   73: pending_errors(Config) when is_list(Config) ->
   74:     ?line pending(e_badmatch, {badmatch, b}),
   75:     ?line pending(x, function_clause),
   76:     ?line pending(e_case, {case_clause, xxx}),
   77:     ?line pending(e_if, if_clause),
   78:     ?line pending(e_badarith, badarith),
   79:     ?line pending(e_undef, undef),
   80:     ?line pending(e_timeoutval, timeout_value),
   81:     ?line pending(e_badarg, badarg),
   82:     ?line pending(e_badarg_spawn, badarg),
   83:     ok.
   84: 
   85: bad_guy(pe_badarith, Other) when Other+1 == 0 -> % badarith (suppressed)
   86:     ok;
   87: bad_guy(pe_badarg, Other) when length(Other) > 0 -> % badarg (suppressed)
   88:     ok;
   89: bad_guy(_, e_case) ->
   90:     case id(xxx) of
   91: 	ok -> ok
   92:     end;					% case_clause
   93: bad_guy(_, e_if) ->
   94:     if
   95: 	a == b -> ok
   96:     end;					% if_clause
   97: bad_guy(_, e_badarith) ->
   98:     1+b;					% badarith
   99: bad_guy(_, e_undef) ->
  100:     non_existing_module:foo();			% undef
  101: bad_guy(_, e_timeoutval) ->
  102:     receive
  103: 	after arne ->				% timeout_value
  104: 		ok
  105: 	end;
  106: bad_guy(_, e_badarg) ->
  107:     node(xxx);					% badarg
  108: bad_guy(_, e_badarg_spawn) ->
  109:     spawn({}, {}, {});				% badarg
  110: bad_guy(_, e_badmatch) ->
  111:     a = id(b).					% badmatch
  112: 
  113: pending(Arg, Expected) ->
  114:     pending(pe_badarith, Arg, Expected),
  115:     pending(pe_badarg, Arg, Expected).
  116: 
  117: pending(First, Second, Expected) ->
  118:     pending_catched(First, Second, Expected),
  119:     pending_exit_message([First, Second], Expected).
  120: 
  121: pending_catched(First, Second, Expected) ->
  122:     ok = io:format("Catching bad_guy(~p, ~p)", [First, Second]),
  123:     case catch bad_guy(First, Second) of
  124: 	{'EXIT', Reason} ->
  125: 	    pending(Reason, bad_guy, [First, Second], Expected);
  126: 	Other ->
  127: 	    test_server:fail({not_exit, Other})
  128:     end.
  129: 
  130: pending_exit_message(Args, Expected) ->
  131:     ok = io:format("Trapping EXITs from spawn_link(~p, ~p, ~p)",
  132: 		   [?MODULE, bad_guy, Args]),
  133:     process_flag(trap_exit, true),
  134:     Pid = spawn_link(?MODULE, bad_guy, Args),
  135:     receive
  136: 	{'EXIT', Pid, Reason} ->
  137: 	    pending(Reason, bad_guy, Args, Expected);
  138: 	Other ->
  139: 	    test_server:fail({unexpected_message, Other})
  140:     after 10000 ->
  141: 	    test_server:fail(timeout)
  142:     end,
  143:     process_flag(trap_exit, false).
  144: 
  145: pending({badarg,[{erlang,Bif,BifArgs,Loc1},
  146: 		 {?MODULE,Func,Arity,Loc2}|_]},
  147: 	Func, Args, _Code)
  148:   when is_atom(Bif), is_list(BifArgs), length(Args) =:= Arity,
  149:        is_list(Loc1), is_list(Loc2) ->
  150:     ok;
  151: pending({undef,[{non_existing_module,foo,[],Loc}|_]}, _, _, _)
  152:   when is_list(Loc) ->
  153:     ok;
  154: pending({function_clause,[{?MODULE,Func,Args,Loc}|_]}, Func, Args, _Code)
  155:   when is_list(Loc) ->
  156:     ok;
  157: pending({Code,[{?MODULE,Func,Arity,Loc}|_]}, Func, Args, Code)
  158:   when length(Args) =:= Arity, is_list(Loc) ->
  159:     ok;
  160: pending(Reason, _Function, _Args, _Code) ->
  161:     test_server:fail({bad_exit_reason,Reason}).
  162: 
  163: %% Test that doing arithmetics on [] gives a badarith EXIT and not a crash.
  164: 
  165: nil_arith(Config) when is_list(Config) ->
  166:     ?line ba_plus_minus_times([], []),
  167: 
  168:     ?line ba_plus_minus_times([], 0),
  169:     ?line ba_plus_minus_times([], 42),
  170:     ?line ba_plus_minus_times([], 38724978123478923784),
  171:     ?line ba_plus_minus_times([], 38.72),
  172: 
  173:     ?line ba_plus_minus_times(0, []),
  174:     ?line ba_plus_minus_times(334, []),
  175:     ?line ba_plus_minus_times(387249797813478923784, []),
  176:     ?line ba_plus_minus_times(344.22, []),
  177: 
  178:     ?line ba_div_rem([], []),
  179: 
  180:     ?line ba_div_rem([], 0),
  181:     ?line ba_div_rem([], 1),
  182:     ?line ba_div_rem([], 42),
  183:     ?line ba_div_rem([], 38724978123478923784),
  184:     ?line ba_div_rem(344.22, []),
  185: 
  186:     ?line ba_div_rem(0, []),
  187:     ?line ba_div_rem(1, []),
  188:     ?line ba_div_rem(334, []),
  189:     ?line ba_div_rem(387249797813478923784, []),
  190:     ?line ba_div_rem(344.22, []),
  191: 
  192:     ?line ba_div_rem(344.22, 0.0),
  193:     ?line ba_div_rem(1, 0.0),
  194:     ?line ba_div_rem(392873498733971, 0.0),
  195:     
  196:     ?line ba_bop([], []),
  197:     ?line ba_bop(0, []),
  198:     ?line ba_bop(42, []),
  199:     ?line ba_bop(-42342742987343, []),
  200:     ?line ba_bop(238.342, []),
  201:     ?line ba_bop([], 0),
  202:     ?line ba_bop([], -243),
  203:     ?line ba_bop([], 243),
  204:     ?line ba_bop([], 2438724982478933),
  205:     ?line ba_bop([], 3987.37),
  206: 
  207:     ?line ba_bnot([]),
  208:     ?line ba_bnot(23.33),
  209: 
  210:     ?line ba_shift([], []),
  211:     ?line ba_shift([], 0),
  212:     ?line ba_shift([], 4),
  213:     ?line ba_shift([], -4),
  214:     ?line ba_shift([], 2343333333333),
  215:     ?line ba_shift([], -333333333),
  216:     ?line ba_shift([], 234.00),
  217:     ?line ba_shift(23, []),
  218:     ?line ba_shift(0, []),
  219:     ?line ba_shift(-3433443433433323, []),
  220:     ?line ba_shift(433443433433323, []),
  221:     ?line ba_shift(343.93, []),
  222:     ok.
  223: 
  224: ba_plus_minus_times(A, B) ->
  225:     io:format("~p + ~p", [A, B]),
  226:     {'EXIT', {badarith, _}} = (catch A + B),
  227:     io:format("~p - ~p", [A, B]),
  228:     {'EXIT', {badarith, _}} = (catch A - B),
  229:     io:format("~p * ~p", [A, B]),
  230:     {'EXIT', {badarith, _}} = (catch A * B).
  231: 
  232: ba_div_rem(A, B) ->
  233:     io:format("~p / ~p", [A, B]),
  234:     {'EXIT', {badarith, _}} = (catch A / B),
  235:     io:format("~p div ~p", [A, B]),
  236:     {'EXIT', {badarith, _}} = (catch A div B),
  237:     io:format("~p rem ~p", [A, B]),
  238:     {'EXIT', {badarith, _}} = (catch A rem B).
  239: 
  240: ba_bop(A, B) ->
  241:     io:format("~p band ~p", [A, B]),
  242:     {'EXIT', {badarith, _}} = (catch A band B),
  243:     io:format("~p bor ~p", [A, B]),
  244:     {'EXIT', {badarith, _}} = (catch A bor B),
  245:     io:format("~p bxor ~p", [A, B]),
  246:     {'EXIT', {badarith, _}} = (catch A bxor B).
  247: 
  248: ba_shift(A, B) ->
  249:     io:format("~p bsl ~p", [A, B]),
  250:     {'EXIT', {badarith, _}} = (catch A bsl B),
  251:     io:format("~p bsr ~p", [A, B]),
  252:     {'EXIT', {badarith, _}} = (catch A bsr B).
  253:     
  254: ba_bnot(A) ->
  255:     io:format("bnot ~p", [A]),
  256:     {'EXIT', {badarith, _}} = (catch bnot A).
  257: 
  258: 
  259: 
  260: stacktrace(Conf) when is_list(Conf) ->
  261:     Tag = make_ref(),
  262:     ?line {_,Mref} = spawn_monitor(fun() -> exit({Tag,erlang:get_stacktrace()}) end),
  263:     ?line {Tag,[]} = receive {'DOWN',Mref,_,_,Info} -> Info end,
  264:     V = [make_ref()|self()],
  265:     ?line {value2,{caught1,badarg,[{erlang,abs,[V],_}|_]=St1}} =
  266: 	stacktrace_1({'abs',V}, error, {value,V}),
  267:     ?line St1 = erase(stacktrace1),
  268:     ?line St1 = erase(stacktrace2),
  269:     ?line St1 = erlang:get_stacktrace(),
  270:     ?line {caught2,{error,badarith},[{?MODULE,my_add,2,_}|_]=St2} =
  271: 	stacktrace_1({'div',{1,0}}, error, {'add',{0,a}}),
  272:     ?line [{?MODULE,my_div,2,_}|_] = erase(stacktrace1),
  273:     ?line St2 = erase(stacktrace2),
  274:     ?line St2 = erlang:get_stacktrace(),
  275:     ?line {caught2,{error,{try_clause,V}},[{?MODULE,stacktrace_1,3,_}|_]=St3} =
  276: 	stacktrace_1({value,V}, error, {value,V}),
  277:     ?line St3 = erase(stacktrace1),
  278:     ?line St3 = erase(stacktrace2),
  279:     ?line St3 = erlang:get_stacktrace(),
  280:     ?line {caught2,{throw,V},[{?MODULE,foo,1,_}|_]=St4} =
  281: 	stacktrace_1({value,V}, error, {throw,V}),
  282:     ?line [{?MODULE,stacktrace_1,3,_}|_] = erase(stacktrace1),
  283:     ?line St4 = erase(stacktrace2),
  284:     ?line St4 = erlang:get_stacktrace(),
  285: 
  286:     try
  287: 	?line stacktrace_2()
  288:     catch
  289: 	error:{badmatch,_} ->
  290: 	    [{?MODULE,stacktrace_2,0,_},
  291: 	     {?MODULE,stacktrace,1,_}|_] =
  292: 		erlang:get_stacktrace(),
  293: 	    ok
  294:     end.
  295: 
  296: stacktrace_1(X, C1, Y) ->
  297:     erase(stacktrace1),
  298:     erase(stacktrace2),
  299:     try try foo(X) of
  300:             C1 -> value1
  301:         catch
  302:             C1:D1 -> {caught1,D1,erlang:get_stacktrace()}
  303:         after
  304:             put(stacktrace1, erlang:get_stacktrace()),
  305: 	    foo(Y)
  306:         end of
  307:         V2 -> {value2,V2}
  308:     catch
  309:         C2:D2 -> {caught2,{C2,D2},erlang:get_stacktrace()}
  310:     after
  311:         put(stacktrace2, erlang:get_stacktrace())
  312:     end.
  313: 
  314: stacktrace_2() ->
  315:     ok = erlang:process_info(self(), current_function),
  316:     ok.
  317: 
  318: 
  319: nested_stacktrace(Conf) when is_list(Conf) ->
  320:     V = [{make_ref()}|[self()]],
  321:     ?line value1 =
  322: 	nested_stacktrace_1({{value,{V,x1}},void,{V,x1}},
  323: 			    {void,void,void}),
  324:     ?line {caught1,
  325: 	   [{?MODULE,my_add,2,_}|_],
  326: 	   value2,
  327: 	   [{?MODULE,my_add,2,_}|_]} =
  328: 	nested_stacktrace_1({{'add',{V,x1}},error,badarith},
  329: 			    {{value,{V,x2}},void,{V,x2}}),
  330:     ?line {caught1,
  331: 	   [{?MODULE,my_add,2,_}|_],
  332: 	   {caught2,[{erlang,abs,[V],_}|_]},
  333: 	   [{erlang,abs,[V],_}|_]} =
  334: 	nested_stacktrace_1({{'add',{V,x1}},error,badarith},
  335: 			    {{'abs',V},error,badarg}),
  336:     ok.
  337: 
  338: nested_stacktrace_1({X1,C1,V1}, {X2,C2,V2}) ->
  339:     try foo(X1) of
  340:         V1 -> value1
  341:     catch
  342:         C1:V1 ->
  343: 	    S1 = erlang:get_stacktrace(),
  344:             T2 =
  345:                 try foo(X2) of
  346: 	            V2 -> value2
  347:                 catch
  348:                     C2:V2 -> {caught2,erlang:get_stacktrace()}
  349:                 end,
  350:             {caught1,S1,T2,erlang:get_stacktrace()}
  351:     end.
  352: 
  353: 
  354: 
  355: raise(Conf) when is_list(Conf) ->
  356:     ?line erase(raise),
  357:     ?line A = 
  358: 	try 
  359: 	    ?line try foo({'div',{1,0}}) 
  360: 		  catch
  361: 		      error:badarith ->
  362: 			  put(raise, A0 = erlang:get_stacktrace()),
  363: 			  ?line erlang:raise(error, badarith, A0)
  364: 		  end
  365: 	catch
  366: 	    error:badarith ->
  367: 		?line A1 = erlang:get_stacktrace(),
  368: 		?line A1 = get(raise)
  369: 	end,
  370:     ?line A = erlang:get_stacktrace(),
  371:     ?line A = get(raise),
  372:     ?line [{?MODULE,my_div,2,_}|_] = A,
  373:     %%
  374:     N = 8, % Must be even
  375:     ?line N = erlang:system_flag(backtrace_depth, N),
  376:     ?line B = odd_even(N, []),
  377:     ?line try even(N) 
  378: 	  catch error:function_clause -> ok
  379: 	  end,
  380:     ?line B = erlang:get_stacktrace(),
  381:     %%
  382:     ?line C0 = odd_even(N+1, []),
  383:     ?line C = lists:sublist(C0, N),
  384:     ?line try odd(N+1) 
  385: 	  catch error:function_clause -> ok
  386: 	  end,
  387:     ?line C = erlang:get_stacktrace(),
  388:     ?line try erlang:raise(error, function_clause, C0)
  389:           catch error:function_clause -> ok
  390:           end,
  391:     ?line C = erlang:get_stacktrace(),
  392:     ok.
  393: 
  394: odd_even(N, R) when is_integer(N), N > 1 ->
  395:     odd_even(N-1, 
  396: 	     [if (N rem 2) == 0 ->
  397: 		      {?MODULE,even,1,[{file,"odd_even.erl"},{line,3}]};
  398: 		 true ->
  399: 		      {?MODULE,odd,1,[{file,"odd_even.erl"},{line,6}]}
  400: 	      end|R]);
  401: odd_even(1, R) ->
  402:     [{?MODULE,odd,[1],[{file,"odd_even.erl"},{line,5}]}|R].
  403: 
  404: foo({value,Value}) -> Value;
  405: foo({'div',{A,B}}) ->
  406:     my_div(A, B);
  407: foo({'add',{A,B}}) ->
  408:     my_add(A, B);
  409: foo({'abs',X}) ->
  410:     my_abs(X);
  411: foo({error,Error}) -> 
  412:     erlang:error(Error);
  413: foo({throw,Throw}) ->
  414:     erlang:throw(Throw);
  415: foo({exit,Exit}) ->
  416:     erlang:exit(Exit);
  417: foo({raise,{Class,Reason,Stacktrace}}) ->
  418:     erlang:raise(Class, Reason, Stacktrace).
  419: %%foo(function_clause) -> % must not be defined!
  420: 
  421: my_div(A, B) ->
  422:     A div B.
  423: 
  424: my_add(A, B) ->
  425:     A + B.
  426: 
  427: my_abs(X) -> abs(X).
  428: 
  429: gunilla(Config) when is_list(Config) ->
  430:     ?line {throw,kalle} = gunilla_1(),
  431:     ?line [] = erlang:get_stacktrace(),
  432:     ok.
  433: 
  434: gunilla_1() ->
  435:     try try arne()
  436: 	after
  437: 	    pelle
  438: 	end
  439:     catch
  440: 	C:R ->
  441: 	    {C,R}
  442:     end.
  443: 
  444: arne() ->
  445:     %% Empty stack trace used to cause change the error class to 'error'.
  446:     erlang:raise(throw, kalle, []).
  447: 
  448: per(Config) when is_list(Config) ->
  449:     try 
  450: 	t1(0,pad,0),
  451: 	t2(0,pad,0)
  452:     catch
  453: 	error:badarith ->
  454: 	    ok
  455:     end.
  456: 
  457: t1(_,X,_) ->
  458:    (1 bsl X) + 1.
  459: 
  460: t2(_,X,_) ->
  461:    (X bsl 1) + 1.
  462: 
  463: %%
  464: %% Make sure that even if a BIF builds an heap fragment, then causes an exception,
  465: %% the stacktrace term will still be OK (specifically, that it does not contain
  466: %% stale pointers to the arguments).
  467: %%
  468: exception_with_heap_frag(Config) when is_list(Config) ->
  469:     Sizes = lists:seq(0, 512),
  470: 
  471:     %% Floats are only validated when the heap fragment has been allocated.
  472:     BadFloat = <<131,99,53,46,48,$X,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,101,45,48,49,0,0,0,0,0>>,
  473:     ?line do_exception_with_heap_frag(BadFloat, Sizes),
  474: 
  475:     %% {Binary,BadFloat}: When the error in float is discovered, a refc-binary
  476:     %% has been allocated and the list of refc-binaries goes through the
  477:     %% heap fragment.
  478:     BinAndFloat = 
  479: 	<<131,104,2,109,0,0,1,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
  480: 	 21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,
  481: 	 46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,
  482: 	 71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
  483: 	 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,
  484: 	 116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,
  485: 	 135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,
  486: 	 154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,
  487: 	 173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
  488: 	 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,
  489: 	 211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
  490: 	 230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,
  491: 	 249,250,251,252,253,254,255,99,51,46,49,52,$B,$l,$u,$r,$f,48,48,48,48,48,48,
  492: 	 48,48,49,50,52,51,52,101,43,48,48,0,0,0,0,0>>,
  493:     ?line do_exception_with_heap_frag(BinAndFloat, Sizes),
  494: 
  495:     %% {Fun,BadFloat}
  496:     FunAndFloat =
  497: 	<<131,104,2,112,0,0,0,66,0,238,239,135,138,137,216,89,57,22,111,52,126,16,84,
  498: 	 71,8,0,0,0,0,0,0,0,0,100,0,1,116,97,0,98,5,175,169,123,103,100,0,13,110,111,
  499: 	 110,111,100,101,64,110,111,104,111,115,116,0,0,0,41,0,0,0,0,0,99,50,46,55,48,
  500: 	 $Y,57,57,57,57,57,57,57,57,57,57,57,57,57,54,52,52,55,101,43,48,48,0,0,0,0,0>>,
  501:     ?line do_exception_with_heap_frag(FunAndFloat, Sizes),
  502: 
  503:     %% [ExternalPid|BadFloat]
  504:     ExtPidAndFloat =
  505: 	<<131,108,0,0,0,1,103,100,0,13,107,97,108,108,101,64,115,116,114,105,100,101,
  506: 	 114,0,0,0,36,0,0,0,0,2,99,48,46,$@,48,48,48,48,48,48,48,48,48,48,48,48,48,48,
  507: 	 48,48,48,48,48,101,43,48,48,0,0,0,0,0>>,
  508:     ?line do_exception_with_heap_frag(ExtPidAndFloat, Sizes),
  509:     
  510:     ok.
  511: 
  512: do_exception_with_heap_frag(Bin, [Sz|Sizes]) ->
  513:     Filler = erlang:make_tuple(Sz, a),
  514:     spawn(fun() ->
  515: 		  try
  516: 		      binary_to_term(Bin)
  517: 		  catch
  518: 		      _:_ ->
  519: 			  %% term_to_binary/1 is an easy way to traverse the
  520: 			  %% entire stacktrace term to make sure that every part
  521: 			  %% of it is OK.
  522: 			  term_to_binary(erlang:get_stacktrace())
  523: 		  end,
  524: 		      id(Filler)
  525: 		      end),
  526:     do_exception_with_heap_frag(Bin, Sizes);
  527: do_exception_with_heap_frag(_, []) -> ok.
  528: 
  529: line_numbers(Config) when is_list(Config) ->
  530:     {'EXIT',{{case_clause,bad_tag},
  531: 	     [{?MODULE,line1,2,
  532: 	       [{file,"fake_file.erl"},{line,3}]},
  533: 	      {?MODULE,line_numbers,1,_}|_]}} =
  534: 	(catch line1(bad_tag, 0)),
  535:     {'EXIT',{badarith,
  536: 	     [{?MODULE,line1,2,
  537: 	       [{file,"fake_file.erl"},{line,5}]},
  538: 	      {?MODULE,line_numbers,1,_}|_]}} =
  539: 	(catch line1(a, not_an_integer)),
  540:     {'EXIT',{{badmatch,{ok,1}},
  541: 	     [{?MODULE,line1,2,
  542: 	       [{file,"fake_file.erl"},{line,7}]},
  543: 	      {?MODULE,line_numbers,1,_}|_]}} =
  544: 	(catch line1(a, 0)),
  545:     {'EXIT',{crash,
  546: 	     [{?MODULE,crash,1,
  547: 	       [{file,"fake_file.erl"},{line,14}]},
  548: 	      {?MODULE,line_numbers,1,_}|_]}} =
  549: 	(catch line1(a, 41)),
  550: 
  551:     ModFile = ?MODULE_STRING++".erl",
  552:     [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
  553:      {?MODULE,call1,0,[{file,"call.erl"},{line,14}]},
  554:      {?MODULE,close_calls,1,[{file,"call.erl"},{line,5}]},
  555:      {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
  556: 	close_calls(call1),
  557:     [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
  558:      {?MODULE,call2,0,[{file,"call.erl"},{line,18}]},
  559:      {?MODULE,close_calls,1,[{file,"call.erl"},{line,6}]},
  560:      {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
  561: 	close_calls(call2),
  562:     [{?MODULE,maybe_crash,1,[{file,"call.erl"},{line,28}]},
  563:      {?MODULE,call3,0,[{file,"call.erl"},{line,22}]},
  564:      {?MODULE,close_calls,1,[{file,"call.erl"},{line,7}]},
  565:      {?MODULE,line_numbers,1,[{file,ModFile},{line,_}]}|_] =
  566: 	close_calls(call3),
  567:     no_crash = close_calls(other),
  568: 
  569:     <<0,0>> = build_binary1(16),
  570:     {'EXIT',{badarg,
  571: 	     [{?MODULE,build_binary1,1,
  572: 	       [{file,"bit_syntax.erl"},{line,72503}]},
  573: 	      {?MODULE,line_numbers,1,
  574: 	       [{file,ModFile},{line,_}]}|_]}} =
  575: 	(catch build_binary1(bad_size)),
  576: 
  577:     <<7,1,2,3>> = build_binary2(8, <<1,2,3>>),
  578:     {'EXIT',{badarg,
  579: 	     [{?MODULE,build_binary2,2,
  580: 	       [{file,"bit_syntax.erl"},{line,72507}]},
  581: 	      {?MODULE,line_numbers,1,
  582: 	       [{file,ModFile},{line,_}]}|_]}} =
  583: 	(catch build_binary2(bad_size, <<>>)),
  584:     {'EXIT',{badarg,
  585: 	     [{erlang,bit_size,[bad_binary],[]},
  586: 	      {?MODULE,build_binary2,2,
  587: 	       [{file,"bit_syntax.erl"},{line,72507}]},
  588: 	      {?MODULE,line_numbers,1,
  589: 	       [{file,ModFile},{line,_}]}|_]}} =
  590: 	(catch build_binary2(8, bad_binary)),
  591: 
  592:     {'EXIT',{function_clause,
  593: 	     [{?MODULE,do_call_abs,[y,y],
  594: 	       [{file,"gc_bif.erl"},{line,18}]},
  595: 	      {?MODULE,line_numbers,1,_}|_]}} =
  596: 	(catch do_call_abs(y, y)),
  597:     {'EXIT',{badarg,
  598: 	     [{erlang,abs,[[]],[]},
  599: 	      {?MODULE,do_call_abs,2,
  600: 	       [{file,"gc_bif.erl"},{line,19}]},
  601: 	      {?MODULE,line_numbers,1,_}|_]}} =
  602: 	(catch do_call_abs(x, [])),
  603: 
  604:     {'EXIT',{{badmatch,"42"},
  605: 	     [{MODULE,applied_bif_1,1,[{file,"applied_bif.erl"},{line,5}]},
  606: 	      {?MODULE,line_numbers,1,_}|_]}} =
  607: 	(catch applied_bif_1(42)),
  608: 
  609:     {'EXIT',{{badmatch,{current_location,
  610: 			{?MODULE,applied_bif_2,0,
  611: 			 [{file,"applied_bif.erl"},{line,9}]}}},
  612: 	     [{MODULE,applied_bif_2,0,[{file,"applied_bif.erl"},{line,10}]},
  613: 	      {?MODULE,line_numbers,1,_}|_]}} =
  614: 	(catch applied_bif_2()),
  615: 
  616:     ok.
  617: 
  618: id(I) -> I.
  619: 
  620: -file("odd_even.erl", 1).			%Line 1
  621: even(N) when is_integer(N), N > 1, (N rem 2) == 0 ->
  622:     odd(N-1)++[N].				%Line 3
  623: 
  624: odd(N) when is_integer(N), N > 1, (N rem 2) == 1 ->
  625:     even(N-1)++[N].				%Line 6
  626: 
  627: %%
  628: %% If the compiler removes redundant line instructions (any
  629: %% line instruction with the same location as the previous),
  630: %% and the loader also removes line instructions before
  631: %% tail-recursive calls to external functions, then the
  632: %% badmatch exception in line 7 below will be reported as
  633: %% occurring in line 6.
  634: %%
  635: %% That means that any removal of redundant line instructions
  636: %% must all be done in the compiler OR in the loader.
  637: %%
  638: -file("fake_file.erl", 1).			%Line 1
  639: line1(Tag, X) ->				%Line 2
  640:     case Tag of					%Line 3
  641: 	a ->
  642: 	    Y = X + 1,				%Line 5
  643: 	    Res = id({ok,Y}),			%Line 6
  644: 	    ?MODULE:crash({ok,42} = Res);	%Line 7
  645: 	b ->
  646: 	    x = id(x),				%Line 9
  647: 	    ok					%Line 10
  648:     end.					%Line 11
  649: 
  650: crash(_) ->					%Line 13
  651:     erlang:error(crash).			%Line 14
  652: 
  653: -file("call.erl", 1).				%Line 1
  654: close_calls(Where) ->				%Line 2
  655:     put(where_to_crash, Where),			%Line 3
  656:     try
  657: 	call1(),				%Line 5
  658: 	call2(),				%Line 6
  659: 	call3(),				%Line 7
  660: 	no_crash				%Line 8
  661:     catch error:crash ->
  662: 	    erlang:get_stacktrace()		%Line 10
  663:     end.					%Line 11
  664: 
  665: call1() ->					%Line 13
  666:     maybe_crash(call1),				%Line 14
  667:     ok.						%Line 15
  668: 
  669: call2() ->					%Line 17
  670:     maybe_crash(call2),				%Line 18
  671:     ok.						%Line 19
  672: 
  673: call3() ->					%Line 21
  674:     maybe_crash(call3),				%Line 22
  675:     ok.						%Line 23
  676: 
  677: maybe_crash(Name) ->				%Line 25
  678:     case get(where_to_crash) of			%Line 26
  679: 	Name ->
  680: 	    erlang:error(crash);		%Line 28
  681: 	_ ->
  682: 	    ok					%Line 30
  683:     end.
  684: 
  685: -file("bit_syntax.erl", 72500).			%Line 72500
  686: build_binary1(Size) ->				%Line 72501
  687:     id(42),					%Line 72502
  688:     <<0:Size>>.					%Line 72503
  689: 
  690: build_binary2(Size, Bin) ->			%Line 72505
  691:     id(0),					%Line 72506
  692:     <<7:Size,Bin/binary>>.			%Line 72507
  693: 
  694: -file("gc_bif.erl", 17).
  695: do_call_abs(x, Arg) ->				%Line 18
  696:     abs(Arg).					%Line 19
  697: 
  698: %% Make sure a BIF that is applied does not leave the p->cp
  699: %% set (and thus generating an extra entry on the stack).
  700: 
  701: -file("applied_bif.erl", 1).
  702: %% Explicit apply.
  703: applied_bif_1(I) ->				%Line 3
  704:     L = apply(erlang, integer_to_list, [I]),	%Line 4
  705:     fail = L,					%Line 5
  706:     ok.						%Line 6
  707: %% Implicit apply.
  708: applied_bif_2() ->				%Line 8
  709:     R = process_info(self(), current_location),	%Line 9
  710:     fail = R,					%Line 10
  711:     ok.						%Line 11