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