File 3331-Pass-Anno-to-ExternalFunctionHandler-in-erl_eval.patch of Package erlang

From 1499ec5ad07906ab892424dfd93180834e2b4bd1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@dashbit.co>
Date: Fri, 14 Jan 2022 18:08:42 +0100
Subject: [PATCH] Pass Anno to ExternalFunctionHandler in erl_eval

This allows code using `erl_eval` to provide better
stacktraces if desired. For this purpose, we also
make sure all errors raised from `erl_eval` pass
through the ExternalFunctionHandler.
---
 lib/debugger/src/dbg_ieval.erl                |   9 +-
 .../src/big_external_type.erl                 |   2 +-
 .../opaque_SUITE_data/src/big_local_type.erl  |   2 +-
 .../src/big_external_type.erl                 |   2 +-
 .../small_SUITE_data/src/big_local_type.erl   |   2 +-
 lib/stdlib/doc/src/erl_eval.xml               |  11 +-
 lib/stdlib/doc/src/shell.xml                  |   8 +
 lib/stdlib/src/erl_eval.erl                   | 484 +++++++++---------
 lib/stdlib/src/erl_parse.yrl                  |   2 +-
 lib/stdlib/src/eval_bits.erl                  | 132 ++---
 lib/stdlib/src/ms_transform.erl               |   2 +-
 lib/stdlib/test/erl_eval_SUITE.erl            | 197 ++++++-
 lib/stdlib/test/shell_SUITE.erl               |   2 +
 lib/syntax_tools/src/erl_syntax.erl           |   2 +-
 14 files changed, 509 insertions(+), 348 deletions(-)

diff --git a/lib/debugger/src/dbg_ieval.erl b/lib/debugger/src/dbg_ieval.erl
index e03ca7fa11..18f226967d 100644
--- a/lib/debugger/src/dbg_ieval.erl
+++ b/lib/debugger/src/dbg_ieval.erl
@@ -1043,9 +1043,7 @@ expr({bin,Line,Fs}, Bs0, Ieval0) ->
     Ieval = Ieval0#ieval{line=Line,top=false},
     try
 	eval_bits:expr_grp(Fs, Bs0,
-			   fun (E, B) -> expr(E, B, Ieval) end,
-			   [],
-			   false)
+			   fun (E, B) -> expr(E, B, Ieval) end)
     catch
 	Class:Reason ->
 	    exception(Class, Reason, Bs0, Ieval)
@@ -1504,7 +1502,7 @@ guard_expr({bin,_,Flds}, Bs) ->
 			   fun(E,B) ->
 				   {value,V} = guard_expr(E,B),
 				   {value,V,B}
-			   end, [], false),
+			   end),
     {value,V}.
 
 %% guard_case_clauses(Value, Clauses, Bindings, Error, Ieval)
 %%   Error = try_clause | case_clause
@@ -1583,8 +1581,7 @@ match1({map,_,Fields}, Map, Bs, BBs) when is_map(Map) ->
 match1({bin,_,Fs}, B, Bs0, BBs) when is_bitstring(B) ->
     try eval_bits:match_bits(Fs, B, Bs0, BBs,
 			     match_fun(BBs),
-			     fun(E, Bs) -> expr(E, Bs, #ieval{}) end,
-			     false)
+			     fun(E, Bs) -> expr(E, Bs, #ieval{}) end)
     catch
 	_:_ -> throw(nomatch)
     end;
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl
index d286a378ed..7ad3f9366b 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/big_external_type.erl
@@ -409,7 +409,7 @@ normalise({bin,_,Fs}) ->
 	eval_bits:expr_grp(Fs, [],
 			   fun(E, _) ->
 				   {value, normalise(E), []}
-			   end, [], true),
+			   end),
     B;
 normalise({cons,_,Head,Tail}) ->
     [normalise(Head)|normalise(Tail)];
diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl
index 7daceb5260..958ebeff93 100644
--- a/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl
+++ b/lib/dialyzer/test/opaque_SUITE_data/src/big_local_type.erl
@@ -406,7 +406,7 @@ normalise({bin,_,Fs}) ->
 	eval_bits:expr_grp(Fs, [],
 			   fun(E, _) ->
 				   {value, normalise(E), []}
-			   end, [], true),
+			   end),
     B;
 normalise({cons,_,Head,Tail}) ->
     [normalise(Head)|normalise(Tail)];
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
index 9ad4810a5e..3fa55dcc9c 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_external_type.erl
@@ -412,7 +412,7 @@ normalise({bin,_,Fs}) ->
 	eval_bits:expr_grp(Fs, [],
 			   fun(E, _) ->
 				   {value, normalise(E), []}
-			   end, [], true),
+			   end),
     B;
 normalise({cons,_,Head,Tail}) ->
     [normalise(Head)|normalise(Tail)];
diff --git a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
index fe567ff10d..89e0942ab5 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/big_local_type.erl
@@ -409,7 +409,7 @@ normalise({bin,_,Fs}) ->
 	eval_bits:expr_grp(Fs, [],
 			   fun(E, _) ->
 				   {value, normalise(E), []}
-			   end, [], true),
+			   end),
     B;
 normalise({cons,_,Head,Tail}) ->
     [normalise(Head)|normalise(Tail)];
diff --git a/lib/stdlib/doc/src/erl_eval.xml b/lib/stdlib/doc/src/erl_eval.xml
index 41566d9aec..71347b4319 100644
--- a/lib/stdlib/doc/src/erl_eval.xml
+++ b/lib/stdlib/doc/src/erl_eval.xml
@@ -273,10 +273,13 @@ Func(Name, Arguments, Bindings)</code>
     <taglist>
       <tag><c>{value,Func}</c></tag>
       <item>
-        <p>This defines a non-local function handler that is called with:</p>
-        <code type="none">
-Func(FuncSpec, Arguments)</code>
-        <p><c>FuncSpec</c> is the name of the function on the form
+        <p>This defines a non-local function handler. The function
+          may be called with two arguments:</p>
+        <code type="none">Func(FuncSpec, Arguments)</code>
+        <p>or three arguments:</p>
+        <code type="none">Func(Anno, FuncSpec, Arguments)</code>
+        <p><c>Anno</c> is the <c>erl_anno:anno()</c> of the node,
+          <c>FuncSpec</c> is the name of the function on the form
           <c>{Module,Function}</c> or a fun, and <c>Arguments</c> is a
           list of the <em>evaluated</em> arguments. The function
           handler returns the value of the function. To
diff --git a/lib/stdlib/doc/src/shell.xml b/lib/stdlib/doc/src/shell.xml
index dc68af4328..39912a4bcf 100644
--- a/lib/stdlib/doc/src/shell.xml
+++ b/lib/stdlib/doc/src/shell.xml
@@ -789,6 +789,14 @@ q                 - quit erlang
       manual page. (Arguments in <c>ArgList</c> are evaluated before the
       callback functions are called.)</p>
 
+    <p>From OTP 25.0, if there are errors evaluating Erlang constructs,
+      such as <c>badmatch</c> during pattern matching or <c>bad_generator</c>
+      in a comprehension, the evaluator will dispatch to
+      <c>erlang:raise(error, Reason, Stacktrace)</c>. This call will be
+      checked against the <c>non_local_allowed/3</c> callback function.
+      You can either forbid it, allow it, or redirect to another call of
+      your choice.</p>
+
     <p>Argument <c>State</c> is a tuple
       <c>{ShellState,ExprState}</c>. The return value <c>NewState</c>
       has the same form. This can be used to carry a state between calls
diff --git a/lib/stdlib/src/erl_eval.erl b/lib/stdlib/src/erl_eval.erl
index 7a809c4402..fc2e2a4194 100644
--- a/lib/stdlib/src/erl_eval.erl
+++ b/lib/stdlib/src/erl_eval.erl
@@ -61,8 +61,9 @@
 
 -type(func_spec() :: {Module :: module(), Function :: atom()} | function()).
 -type(nlfun_handler() :: fun((FuncSpec :: func_spec(),
-                              Arguments :: [term()]) ->
-                                    term())).
+                              Arguments :: [term()]) -> term())
+                       | fun((Anno :: erl_anno:anno(), FuncSpec :: func_spec(),
+                              Arguments :: [term()]) -> term())).
 -type(non_local_function_handler() :: {value, nlfun_handler()}
                                     | none).
 
@@ -197,9 +198,9 @@ fun_data(F) when is_function(F) ->
     case erlang:fun_info(F, module) of
         {module,?MODULE} ->
             case erlang:fun_info(F, env) of
-                {env,[{FBs,_FLf,_FEf,_FUVs,FCs}]} ->
+                {env,[{_FAnno,FBs,_FLf,_FEf,_FUVs,FCs}]} ->
                     {fun_data,FBs,FCs};
-                {env,[{FBs,_FLf,_FEf,_FUVs,FCs,FName}]} ->
+                {env,[{_FAnno,FBs,_FLf,_FEf,_FUVs,FCs,FName}]} ->
                     {named_fun_data,FBs,FName,FCs}
             end;
         _ ->
@@ -232,12 +233,12 @@ expr(Expr, Bs, Lf, Ef, Rbs) ->
       FunUsedVars :: erl_lint:fun_used_vars(),
       Value :: value(),
       NewBindings :: binding_struct()).
-expr({var,_,V}, Bs, _Lf, _Ef, RBs, _FUVs) ->
+expr({var,Anno,V}, Bs, _Lf, Ef, RBs, _FUVs) ->
     case binding(V, Bs) of
 	{value,Val} ->
             ret_expr(Val, Bs, RBs);
 	unbound -> % Cannot not happen if checked by erl_lint
-	    erlang:raise(error, {unbound,V}, ?STACKTRACE)
+            apply_error({unbound,V}, ?STACKTRACE, Anno, Bs, Ef, RBs)
     end;
 expr({char,_,C}, Bs, _Lf, _Ef, RBs, _FUVs) ->
     ret_expr(C, Bs, RBs);
@@ -251,10 +252,10 @@ expr({string,_,S}, Bs, _Lf, _Ef, RBs, _FUVs) ->
     ret_expr(S, Bs, RBs);
 expr({nil, _}, Bs, _Lf, _Ef, RBs, _FUVs) ->
     ret_expr([], Bs, RBs);
-expr({cons,_,H0,T0}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({cons,Anno,H0,T0}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,H,Bs1} = expr(H0, Bs0, Lf, Ef, none, FUVs),
     {value,T,Bs2} = expr(T0, Bs0, Lf, Ef, none, FUVs),
-    ret_expr([H|T], merge_bindings(Bs1, Bs2), RBs);
+    ret_expr([H|T], merge_bindings(Bs1, Bs2, Anno, Ef), RBs);
 expr({lc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) ->
     eval_lc(E, Qs, Bs, Lf, Ef, RBs, FUVs);
 expr({bc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) ->
@@ -262,17 +263,17 @@ expr({bc,_,E,Qs}, Bs, Lf, Ef, RBs, FUVs) ->
 expr({tuple,_,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
     {Vs,Bs} = expr_list(Es, Bs0, Lf, Ef, FUVs),
     ret_expr(list_to_tuple(Vs), Bs, RBs);
-expr({record_field,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
-expr({record_index,_,Name,_}, _Bs, _Lf, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
-expr({record,_,Name,_}, _Bs, _Lf, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
-expr({record,_,_,Name,_}, _Bs, _Lf, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, {undef_record,Name}, ?STACKTRACE);
+expr({record_field,Anno,_,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+    apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
+expr({record_index,Anno,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+    apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
+expr({record,Anno,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+    apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
+expr({record,Anno,_,Name,_}, Bs, _Lf, Ef, RBs, _FUVs) ->
+    apply_error({undef_record,Name}, ?STACKTRACE, Anno, Bs, Ef, RBs);
 
 %% map
-expr({map,_,Binding,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({map,Anno,Binding,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value, Map0, Bs1} = expr(Binding, Bs0, Lf, Ef, none, FUVs),
     {Vs,Bs2} = eval_map_fields(Es, Bs0, Lf, Ef, FUVs),
     _ = maps:put(k, v, Map0),			%Validate map.
@@ -281,7 +282,7 @@ expr({map,_,Binding,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
 			   ({map_exact,K,V}, Mi) ->
 			       maps:update(K, V, Mi)
 		       end, Map0, Vs),
-    ret_expr(Map1, merge_bindings(Bs2, Bs1), RBs);
+    ret_expr(Map1, merge_bindings(Bs2, Bs1, Anno, Ef), RBs);
 expr({map,_,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
     {Vs,Bs} = eval_map_fields(Es, Bs0, Lf, Ef, FUVs),
     ret_expr(lists:foldl(fun
@@ -290,13 +291,13 @@ expr({map,_,Es}, Bs0, Lf, Ef, RBs, FUVs) ->
 
 expr({block,_,Es}, Bs, Lf, Ef, RBs, FUVs) ->
     exprs(Es, Bs, Lf, Ef, RBs, FUVs);
-expr({'if',_,Cs}, Bs, Lf, Ef, RBs, FUVs) ->
-    if_clauses(Cs, Bs, Lf, Ef, RBs, FUVs);
-expr({'case',_,E,Cs}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({'if',Anno,Cs}, Bs, Lf, Ef, RBs, FUVs) ->
+    if_clauses(Cs, Anno, Bs, Lf, Ef, RBs, FUVs);
+expr({'case',Anno,E,Cs}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,Val,Bs} = expr(E, Bs0, Lf, Ef, none, FUVs),
-    case_clauses(Val, Cs, Bs, Lf, Ef, RBs, FUVs);
-expr({'try',_,B,Cases,Catches,AB}, Bs, Lf, Ef, RBs, FUVs) ->
-    try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs, FUVs);
+    case_clauses(Val, Cs, Anno, Bs, Lf, Ef, RBs, FUVs);
+expr({'try',Anno,B,Cases,Catches,AB}, Bs, Lf, Ef, RBs, FUVs) ->
+    try_clauses(B, Cases, Catches, AB, Anno, Bs, Lf, Ef, RBs, FUVs);
 expr({'receive',_,Cs}, Bs, Lf, Ef, RBs, FUVs) ->
     receive_clauses(Cs, Bs, Lf, Ef, RBs, FUVs);
 expr({'receive',_, Cs, E, TB}, Bs0, Lf, Ef, RBs, FUVs) ->
@@ -306,12 +307,12 @@ expr({'fun',_Anno,{function,Mod0,Name0,Arity0}}, Bs0, Lf, Ef, RBs, FUVs) ->
     {[Mod,Name,Arity],Bs} = expr_list([Mod0,Name0,Arity0], Bs0, Lf, Ef, FUVs),
     F = erlang:make_fun(Mod, Name, Arity),
     ret_expr(F, Bs, RBs);
-expr({'fun',_Anno,{function,Name,Arity}}, _Bs0, _Lf, _Ef, _RBs, _FUVs) -> % R8
+expr({'fun',Anno,{function,Name,Arity}}, Bs0, _Lf, Ef, RBs, _FUVs) -> % R8
     %% Don't know what to do...
-    erlang:raise(error, undef, [{?MODULE,Name,Arity}|?STACKTRACE]);
+    apply_error(undef, [{?MODULE,Name,Arity}|?STACKTRACE], Anno, Bs0, Ef, RBs);
 expr({'fun',Anno,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs, FUVs) ->
     {En,NewFUVs} = fun_used_bindings(Ex, Cs, Bs, FUVs),
-    Info = {En,Lf,Ef,NewFUVs,Cs},
+    Info = {Anno,En,Lf,Ef,NewFUVs,Cs},
 
     %% This is a really ugly hack!
     F =
@@ -350,13 +351,13 @@ expr({'fun',Anno,{clauses,Cs}} = Ex, Bs, Lf, Ef, RBs, FUVs) ->
            eval_fun([A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T], Info) end;
 	_Other ->
             L = erl_anno:location(Anno),
-	    erlang:raise(error, {'argument_limit',{'fun',L,to_terms(Cs)}},
-			 ?STACKTRACE)
+            Reason = {'argument_limit',{'fun',L,to_terms(Cs)}},
+            apply_error(Reason, ?STACKTRACE, Anno, Bs, Ef, RBs)
     end,
     ret_expr(F, Bs, RBs);
 expr({named_fun,Anno,Name,Cs} = Ex, Bs, Lf, Ef, RBs, FUVs) ->
     {En,NewFUVs} = fun_used_bindings(Ex, Cs, Bs, FUVs),
-    Info = {En,Lf,Ef,NewFUVs,Cs,Name},
+    Info = {Anno,En,Lf,Ef,NewFUVs,Cs,Name},
 
     %% This is a really ugly hack!
     F =
@@ -400,9 +401,8 @@ expr({named_fun,Anno,Name,Cs} = Ex, Bs, Lf, Ef, RBs, FUVs) ->
                           RF, Info) end;
         _Other ->
             L = erl_anno:location(Anno),
-            erlang:raise(error, {'argument_limit',
-                                 {named_fun,L,Name,to_terms(Cs)}},
-                         ?STACKTRACE)
+            Reason = {'argument_limit',{named_fun,L,Name,to_terms(Cs)}},
+            apply_error(Reason, ?STACKTRACE, Anno, Bs, Ef, RBs)
     end,
     ret_expr(F, Bs, RBs);
 expr({call,_,{remote,_,{atom,_,qlc},{atom,_,q}},[{lc,_,_E,_Qs}=LC | As0]},
@@ -422,33 +422,33 @@ expr({call,A1,{remote,A2,{record_field,_,{atom,_,''},{atom,_,qlc}=Mod},
       [{lc,_,_E,_Qs} | As0]=As},
      Bs, Lf, Ef, RBs, FUVs) when length(As0) =< 1 ->
     expr({call,A1,{remote,A2,Mod,Func},As}, Bs, Lf, Ef, RBs, FUVs);
-expr({call,_,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({call,Anno,{remote,_,Mod,Func},As0}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,M,Bs1} = expr(Mod, Bs0, Lf, Ef, none, FUVs),
     {value,F,Bs2} = expr(Func, Bs0, Lf, Ef, none, FUVs),
-    {As,Bs3} = expr_list(As0, merge_bindings(Bs1, Bs2), Lf, Ef, FUVs),
+    {As,Bs3} = expr_list(As0, merge_bindings(Bs1, Bs2, Anno, Ef), Lf, Ef, FUVs),
     %% M could be a parameterized module (not an atom).
     case is_atom(M) andalso erl_internal:bif(M, F, length(As)) of
         true ->
-            bif(F, As, Bs3, Ef, RBs);
+            bif(F, As, Anno, Bs3, Ef, RBs);
         false ->
-            do_apply(M, F, As, Bs3, Ef, RBs)
+            do_apply(M, F, As, Anno, Bs3, Ef, RBs)
     end;
-expr({call,_,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({call,Anno,{atom,_,Func},As0}, Bs0, Lf, Ef, RBs, FUVs) ->
     case erl_internal:bif(Func, length(As0)) of
         true ->
             {As,Bs} = expr_list(As0, Bs0, Lf, Ef),
-            bif(Func, As, Bs, Ef, RBs);
+            bif(Func, As, Anno, Bs, Ef, RBs);
         false ->
-            local_func(Func, As0, Bs0, Lf, Ef, RBs, FUVs)
+            local_func(Func, As0, Anno, Bs0, Lf, Ef, RBs, FUVs)
     end;
-expr({call,_,Func0,As0}, Bs0, Lf, Ef, RBs, FUVs) -> % function or {Mod,Fun}
+expr({call,Anno,Func0,As0}, Bs0, Lf, Ef, RBs, FUVs) -> % function or {Mod,Fun}
     {value,Func,Bs1} = expr(Func0, Bs0, Lf, Ef, none, FUVs),
     {As,Bs2} = expr_list(As0, Bs1, Lf, Ef, FUVs),
     case Func of
 	{M,F} when is_atom(M), is_atom(F) ->
-	    erlang:raise(error, {badfun,Func}, ?STACKTRACE);
+            apply_error({badfun,Func}, ?STACKTRACE, Anno, Bs0, Ef, RBs);
 	_ ->
-	    do_apply(Func, As, Bs2, Ef, RBs)
+	    do_apply(Func, As, Anno, Bs2, Ef, RBs)
     end;
 expr({'catch',_,Expr}, Bs0, Lf, Ef, RBs, FUVs) ->
     try expr(Expr, Bs0, Lf, Ef, none, FUVs) of
@@ -462,46 +462,50 @@ expr({'catch',_,Expr}, Bs0, Lf, Ef, RBs, FUVs) ->
         error:Reason:Stacktrace ->
             ret_expr({'EXIT',{Reason,Stacktrace}}, Bs0, RBs)
     end;
-expr({match,_,Lhs,Rhs0}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({match,Anno,Lhs,Rhs0}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,Rhs,Bs1} = expr(Rhs0, Bs0, Lf, Ef, none, FUVs),
-    case match(Lhs, Rhs, Bs1) of
+    case match(Lhs, Rhs, Anno, Bs1, Bs1, Ef) of
 	{match,Bs} ->
             ret_expr(Rhs, Bs, RBs);
-	nomatch -> erlang:raise(error, {badmatch,Rhs}, ?STACKTRACE)
+	nomatch -> apply_error({badmatch,Rhs}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
     end;
-expr({op,_,Op,A0}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({op,Anno,Op,A0}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,A,Bs} = expr(A0, Bs0, Lf, Ef, none, FUVs),
-    eval_op(Op, A, Bs, Ef, RBs);
-expr({op,_,'andalso',L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
+    eval_op(Op, A, Anno, Bs, Ef, RBs);
+expr({op,Anno,'andalso',L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
     V = case L of
 	    true ->
 		{value,R,_} = expr(R0, Bs1, Lf, Ef, none, FUVs),
 		R;
 	    false -> false;
-	    _ -> erlang:raise(error, {badarg,L}, ?STACKTRACE)
+	    _ -> apply_error({badarg,L}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
 	end,
     ret_expr(V, Bs1, RBs);
-expr({op,_,'orelse',L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({op,Anno,'orelse',L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
     V = case L of
 	    true -> true;
 	    false ->
 		{value,R,_} = expr(R0, Bs1, Lf, Ef, none, FUVs),
 		R;
-	    _ -> erlang:raise(error, {badarg,L}, ?STACKTRACE)
+	    _ -> apply_error({badarg,L}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
 	end,
     ret_expr(V, Bs1, RBs);
-expr({op,_,Op,L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
+expr({op,Anno,Op,L0,R0}, Bs0, Lf, Ef, RBs, FUVs) ->
     {value,L,Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
     {value,R,Bs2} = expr(R0, Bs0, Lf, Ef, none, FUVs),
-    eval_op(Op, L, R, merge_bindings(Bs1, Bs2), Ef, RBs);
+    eval_op(Op, L, R, Anno, merge_bindings(Bs1, Bs2, Anno, Ef), Ef, RBs);
 expr({bin,_,Fs}, Bs0, Lf, Ef, RBs, FUVs) ->
     EvalFun = fun(E, B) -> expr(E, B, Lf, Ef, none, FUVs) end,
-    {value,V,Bs} = eval_bits:expr_grp(Fs, Bs0, EvalFun),
+    ErrorFun = fun(A, R, S) -> apply_error(R, S, A, Bs0, Ef, RBs) end,
+    {value,V,Bs} = eval_bits:expr_grp(Fs, Bs0, EvalFun, ErrorFun),
     ret_expr(V, Bs, RBs);
-expr({remote,_,_,_}, _Bs, _Lf, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, {badexpr,':'}, ?STACKTRACE).
+expr({remote,Anno,_,_}, Bs0, _Lf, Ef, RBs, _FUVs) ->
+    apply_error({badexpr,':'}, ?STACKTRACE, Anno, Bs0, Ef, RBs).
+
+apply_error(Reason, Stack, Anno, Bs0, Ef, RBs) ->
+    do_apply(erlang, raise, [error, Reason, Stack], Anno, Bs0, Ef, RBs).
 
 find_maxline(LC) ->
     put('$erl_eval_max_line', 0),
@@ -584,62 +588,62 @@ unhide_calls([E | Es], MaxLine, D) ->
 unhide_calls(E, _MaxLine, _D) ->
     E.
 
-%% local_func(Function, Arguments, Bindings, LocalFuncHandler,
+%% local_func(Function, Arguments, Anno, Bindings, LocalFuncHandler,
 %%            ExternalFuncHandler, RBs, FunUsedVars) ->
 %%	{value,Value,Bindings} | Value when
 %%	LocalFuncHandler = {value,F} | {value,F,Eas} |
 %%                         {eval,F}  | {eval,F,Eas}  | none.
 
-local_func(Func, As0, Bs0, {value,F}, Ef, value, FUVs) ->
+local_func(Func, As0, _Anno, Bs0, {value,F}, Ef, value, FUVs) ->
     {As1,_Bs1} = expr_list(As0, Bs0, {value,F}, Ef, FUVs),
     %% Make tail recursive calls when possible.
     F(Func, As1);
-local_func(Func, As0, Bs0, {value,F}, Ef, RBs, FUVs) ->
+local_func(Func, As0, _Anno, Bs0, {value,F}, Ef, RBs, FUVs) ->
     {As1,Bs1} = expr_list(As0, Bs0, {value,F}, Ef, FUVs),
     ret_expr(F(Func, As1), Bs1, RBs);
-local_func(Func, As0, Bs0, {value,F,Eas}, Ef, RBs, FUVs) ->
+local_func(Func, As0, Anno, Bs0, {value,F,Eas}, Ef, RBs, FUVs) ->
     Fun = fun(Name, Args) -> apply(F, [Name,Args|Eas]) end,
-    local_func(Func, As0, Bs0, {value, Fun}, Ef, RBs, FUVs);
-local_func(Func, As, Bs, {eval,F}, _Ef, RBs, _FUVs) ->
-    local_func2(F(Func, As, Bs), RBs);
-local_func(Func, As, Bs, {eval,F,Eas}, _Ef, RBs, _FUVs) ->
-    local_func2(apply(F, [Func,As,Bs|Eas]), RBs);
+    local_func(Func, As0, Anno, Bs0, {value, Fun}, Ef, RBs, FUVs);
+local_func(Func, As, Anno, Bs, {eval,F}, _Ef, RBs, _FUVs) ->
+    local_func2(F(Func, As, Bs), Anno, RBs);
+local_func(Func, As, Anno, Bs, {eval,F,Eas}, _Ef, RBs, _FUVs) ->
+    local_func2(apply(F, [Func,As,Bs|Eas]), Anno, RBs);
 %% These two clauses are for backwards compatibility.
-local_func(Func, As0, Bs0, {M,F}, Ef, RBs, FUVs) ->
+local_func(Func, As0, _Anno, Bs0, {M,F}, Ef, RBs, FUVs) ->
     {As1,Bs1} = expr_list(As0, Bs0, {M,F}, Ef, FUVs),
     ret_expr(M:F(Func,As1), Bs1, RBs);
-local_func(Func, As, _Bs, {M,F,Eas}, _Ef, RBs, _FUVs) ->
-    local_func2(apply(M, F, [Func,As|Eas]), RBs);
+local_func(Func, As, Anno, _Bs, {M,F,Eas}, _Ef, RBs, _FUVs) ->
+    local_func2(apply(M, F, [Func,As|Eas]), Anno, RBs);
 %% Default unknown function handler to undefined function.
-local_func(Func, As0, _Bs0, none, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, undef, [{?MODULE,Func,length(As0)}|?STACKTRACE]).
+local_func(Func, As0, Anno, Bs0, none, Ef, RBs, _FUVs) ->
+    apply_error(undef, [{?MODULE,Func,length(As0)}|?STACKTRACE], Anno, Bs0, Ef, RBs).
 
-local_func2({value,V,Bs}, RBs) ->
+local_func2({value,V,Bs}, _Anno, RBs) ->
     ret_expr(V, Bs, RBs);
-local_func2({eval,F,As,Bs}, RBs) -> % This reply is not documented.
+local_func2({eval,F,As,Bs}, Anno, RBs) -> % This reply is not documented.
     %% The shell found F. erl_eval tries to do a tail recursive call,
     %% something the shell cannot do. Do not use Ef here.
-    do_apply(F, As, Bs, none, RBs).
+    do_apply(F, As, Anno, Bs, none, RBs).
 
 %% bif(Name, Arguments, RBs)
 %%  Evaluate the Erlang auto-imported function Name. erlang:apply/2,3
 %%  are "hidden" from the external function handler.
 
-bif(apply, [erlang,apply,As], Bs, Ef, RBs) ->
-    bif(apply, As, Bs, Ef, RBs);
-bif(apply, [M,F,As], Bs, Ef, RBs) ->
-    do_apply(M, F, As, Bs, Ef, RBs);
-bif(apply, [F,As], Bs, Ef, RBs) ->
-    do_apply(F, As, Bs, Ef, RBs);
-bif(Name, As, Bs, Ef, RBs) ->
-    do_apply(erlang, Name, As, Bs, Ef, RBs).
+bif(apply, [erlang,apply,As], Anno, Bs, Ef, RBs) ->
+    bif(apply, As, Anno, Bs, Ef, RBs);
+bif(apply, [M,F,As], Anno, Bs, Ef, RBs) ->
+    do_apply(M, F, As, Anno, Bs, Ef, RBs);
+bif(apply, [F,As], Anno, Bs, Ef, RBs) ->
+    do_apply(F, As, Anno, Bs, Ef, RBs);
+bif(Name, As, Anno, Bs, Ef, RBs) ->
+    do_apply(erlang, Name, As, Anno, Bs, Ef, RBs).
 
 %% do_apply(Func, Arguments, Bindings, ExternalFuncHandler, RBs) ->
 %%	{value,Value,Bindings} | Value when
 %%	ExternalFuncHandler = {value,F} | none,
 %%  Func = fun()
 
-do_apply(Func, As, Bs0, Ef, RBs) ->
+do_apply(Func, As, Anno, Bs0, Ef, RBs) ->
     Env = if
               is_function(Func) ->
                   case {erlang:fun_info(Func, module),
@@ -653,7 +657,7 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
                   no_env
           end,
     case {Env,Ef} of
-        {{env,[{FBs,FLf,FEf,FFUVs,FCs}]},_} ->
+        {{env,[{FAnno,FBs,FLf,FEf,FFUVs,FCs}]},_} ->
             %% If we are evaluting within another function body
             %% (RBs =/= none), we return RBs when this function body
             %% has been evalutated, otherwise we return Bs0, the
@@ -664,20 +668,20 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
                    end,
             case {erlang:fun_info(Func, arity), length(As)} of
                 {{arity, Arity}, Arity} ->
-                    eval_fun(FCs, As, FBs, FLf, FEf, NRBs, FFUVs);
+                    eval_fun(FCs, As, FAnno, FBs, FLf, FEf, NRBs, FFUVs);
                 _ ->
-                    erlang:raise(error, {badarity,{Func,As}},?STACKTRACE)
+                    apply_error({badarity,{Func,As}}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
             end;
-        {{env,[{FBs,FLf,FEf,FFUVs,FCs,FName}]},_} ->
+        {{env,[{FAnno,FBs,FLf,FEf,FFUVs,FCs,FName}]},_} ->
             NRBs = if
                        RBs =:= none -> Bs0;
                        true -> RBs
                    end,
             case {erlang:fun_info(Func, arity), length(As)} of
                 {{arity, Arity}, Arity} ->
-                    eval_named_fun(FCs, As, FBs, FLf, FEf, FName, Func, NRBs, FFUVs);
+                    eval_named_fun(FCs, As, FAnno, FBs, FLf, FEf, FName, Func, NRBs, FFUVs);
                 _ ->
-                    erlang:raise(error, {badarity,{Func,As}},?STACKTRACE)
+                    apply_error({badarity,{Func,As}}, ?STACKTRACE, Anno, Bs0, Ef, RBs)
             end;
         {no_env,none} when RBs =:= value ->
             %% Make tail recursive calls when possible.
@@ -685,12 +689,12 @@ do_apply(Func, As, Bs0, Ef, RBs) ->
         {no_env,none} ->
             ret_expr(apply(Func, As), Bs0, RBs);
         {no_env,{value,F}} when RBs =:= value ->
-            F(Func,As);
+            do_apply(F, Anno, Func, As);
         {no_env,{value,F}} ->
-            ret_expr(F(Func, As), Bs0, RBs)
+            ret_expr(do_apply(F, Anno, Func, As), Bs0, RBs)
     end.
 
-do_apply(Mod, Func, As, Bs0, Ef, RBs) ->
+do_apply(Mod, Func, As, Anno, Bs0, Ef, RBs) ->
     case Ef of
         none when RBs =:= value ->
             %% Make tail recursive calls when possible.
@@ -698,11 +702,16 @@ do_apply(Mod, Func, As, Bs0, Ef, RBs) ->
         none ->
             ret_expr(apply(Mod, Func, As), Bs0, RBs);
         {value,F} when RBs =:= value ->
-            F({Mod,Func}, As);
+            do_apply(F, Anno, {Mod,Func}, As);
         {value,F} ->
-            ret_expr(F({Mod,Func}, As), Bs0, RBs)
+            ret_expr(do_apply(F, Anno, {Mod,Func}, As), Bs0, RBs)
     end.
 
+do_apply(F, Anno, FunOrModFun, Args) when is_function(F, 3) ->
+    F(Anno, FunOrModFun, Args);
+do_apply(F, _Anno, FunOrModFun, Args) when is_function(F, 2) ->
+    F(FunOrModFun, Args).
+
 %% eval_lc(Expr, [Qualifier], Bindings, LocalFunctionHandler,
 %%         ExternalFuncHandler, RetBindings) ->
 %%	{value,Value,Bindings} | Value
@@ -710,14 +719,14 @@ do_apply(Mod, Func, As, Bs0, Ef, RBs) ->
 eval_lc(E, Qs, Bs, Lf, Ef, RBs, FUVs) ->
     ret_expr(lists:reverse(eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, [])), Bs, RBs).
 
-eval_lc1(E, [{generate,_,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+eval_lc1(E, [{generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
     {value,L1,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
     CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
-    eval_generate(L1, P, Bs0, Lf, Ef, CompFun, Acc0);
-eval_lc1(E, [{b_generate,_,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+    eval_generate(L1, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
+eval_lc1(E, [{b_generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
     {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
     CompFun = fun(Bs, Acc) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
-    eval_b_generate(Bin, P, Bs0, Lf, Ef, CompFun, Acc0);
+    eval_b_generate(Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
 eval_lc1(E, [F|Qs], Bs0, Lf, Ef, FUVs, Acc) ->
     CompFun = fun(Bs) -> eval_lc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
     eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc);
@@ -732,14 +741,14 @@ eval_lc1(E, [], Bs, Lf, Ef, FUVs, Acc) ->
 eval_bc(E, Qs, Bs, Lf, Ef, RBs, FUVs) ->
     ret_expr(eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, <<>>), Bs, RBs).
 
-eval_bc1(E, [{b_generate,_,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+eval_bc1(E, [{b_generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
     {value,Bin,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
     CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
-    eval_b_generate(Bin, P, Bs0, Lf, Ef, CompFun, Acc0);
-eval_bc1(E, [{generate,_,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
+    eval_b_generate(Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
+eval_bc1(E, [{generate,Anno,P,L0}|Qs], Bs0, Lf, Ef, FUVs, Acc0) ->
     {value,List,_Bs1} = expr(L0, Bs0, Lf, Ef, none, FUVs),
     CompFun = fun(Bs, Acc) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
-    eval_generate(List, P, Bs0, Lf, Ef, CompFun, Acc0);
+    eval_generate(List, P, Anno, Bs0, Lf, Ef, CompFun, Acc0);
 eval_bc1(E, [F|Qs], Bs0, Lf, Ef, FUVs, Acc) ->
     CompFun = fun(Bs) -> eval_bc1(E, Qs, Bs, Lf, Ef, FUVs, Acc) end,
     eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc);
@@ -747,35 +756,36 @@ eval_bc1(E, [], Bs, Lf, Ef, FUVs, Acc) ->
     {value,V,_} = expr(E, Bs, Lf, Ef, none, FUVs),
     <<Acc/bitstring,V/bitstring>>.
 
-eval_generate([V|Rest], P, Bs0, Lf, Ef, CompFun, Acc) ->
-    case match(P, V, new_bindings(Bs0), Bs0) of
+eval_generate([V|Rest], P, Anno, Bs0, Lf, Ef, CompFun, Acc) ->
+    case match(P, V, Anno, new_bindings(Bs0), Bs0, Ef) of
 	{match,Bsn} ->
 	    Bs2 = add_bindings(Bsn, Bs0),
 	    NewAcc = CompFun(Bs2, Acc),
-	    eval_generate(Rest, P, Bs0, Lf, Ef, CompFun, NewAcc);
+	    eval_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, NewAcc);
 	nomatch ->
-	    eval_generate(Rest, P, Bs0, Lf, Ef, CompFun, Acc)
+	    eval_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, Acc)
 	end;
-eval_generate([], _P, _Bs0, _Lf, _Ef, _CompFun, Acc) ->
+eval_generate([], _P, _Anno, _Bs0, _Lf, _Ef, _CompFun, Acc) ->
     Acc;
-eval_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
-    erlang:raise(error, {bad_generator,Term}, ?STACKTRACE).
+eval_generate(Term, _P, Anno, Bs0, _Lf, Ef, _CompFun, _Acc) ->
+    apply_error({bad_generator,Term}, ?STACKTRACE, Anno, Bs0, Ef, none).
 
-eval_b_generate(<<_/bitstring>>=Bin, P, Bs0, Lf, Ef, CompFun, Acc) ->
-    Mfun = match_fun(Bs0),
+eval_b_generate(<<_/bitstring>>=Bin, P, Anno, Bs0, Lf, Ef, CompFun, Acc) ->
+    Mfun = match_fun(Bs0, Ef),
     Efun = fun(Exp, Bs) -> expr(Exp, Bs, Lf, Ef, none) end,
-    case eval_bits:bin_gen(P, Bin, new_bindings(Bs0), Bs0, Mfun, Efun) of
+    ErrorFun = fun(A, R, S) -> apply_error(R, S, A, Bs0, Ef, none) end,
+    case eval_bits:bin_gen(P, Bin, new_bindings(Bs0), Bs0, Mfun, Efun, ErrorFun) of
 	{match, Rest, Bs1} ->
 	    Bs2 = add_bindings(Bs1, Bs0),
 	    NewAcc = CompFun(Bs2, Acc),
-	    eval_b_generate(Rest, P, Bs0, Lf, Ef, CompFun, NewAcc);
+	    eval_b_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, NewAcc);
 	{nomatch, Rest} ->
-	    eval_b_generate(Rest, P, Bs0, Lf, Ef, CompFun, Acc);
+	    eval_b_generate(Rest, P, Anno, Bs0, Lf, Ef, CompFun, Acc);
 	done ->
 	    Acc
     end;
-eval_b_generate(Term, _P, _Bs0, _Lf, _Ef, _CompFun, _Acc) ->
-    erlang:raise(error, {bad_generator,Term}, ?STACKTRACE).
+eval_b_generate(Term, _P, Anno, Bs0, _Lf, Ef, _CompFun, _Acc) ->
+    apply_error({bad_generator,Term}, ?STACKTRACE, Anno, Bs0, Ef, none).
 
 eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc) ->
     case erl_lint:is_guard_test(F) of
@@ -789,7 +799,7 @@ eval_filter(F, Bs0, Lf, Ef, CompFun, FUVs, Acc) ->
 		{value,true,Bs1} -> CompFun(Bs1);
 		{value,false,_} -> Acc;
 		{value,V,_} ->
-                    erlang:raise(error, {bad_filter,V}, ?STACKTRACE)
+                    apply_error({bad_filter,V}, ?STACKTRACE, element(2, F), Bs0, Ef, none)
 	    end
     end.
 
@@ -824,48 +834,48 @@ ret_expr(V, Bs, none) ->
 ret_expr(V, _Bs, RBs) when is_list(RBs); is_map(RBs) ->
     {value,V,RBs}.
 
-%% eval_fun(Arguments, {Bindings,LocalFunctionHandler,
+%% eval_fun(Arguments, {Anno,Bindings,LocalFunctionHandler,
 %%                      ExternalFunctionHandler,FunUsedVars,Clauses}) -> Value
 %% This function is called when the fun is called from compiled code
 %% or from apply.
 
-eval_fun(As, {Bs0,Lf,Ef,FUVs,Cs}) ->
-    eval_fun(Cs, As, Bs0, Lf, Ef, value, FUVs).
+eval_fun(As, {Anno,Bs0,Lf,Ef,FUVs,Cs}) ->
+    eval_fun(Cs, As, Anno, Bs0, Lf, Ef, value, FUVs).
 
-eval_fun([{clause,_,H,G,B}|Cs], As, Bs0, Lf, Ef, RBs, FUVs) ->
-    case match_list(H, As, new_bindings(Bs0), Bs0) of
+eval_fun([{clause,_,H,G,B}|Cs], As, Anno, Bs0, Lf, Ef, RBs, FUVs) ->
+    case match_list(H, As, Anno, new_bindings(Bs0), Bs0, Ef) of
 	{match,Bsn} ->                      % The new bindings for the head
 	    Bs1 = add_bindings(Bsn, Bs0),   % which then shadow!
 	    case guard(G, Bs1, Lf, Ef) of
 		true -> exprs(B, Bs1, Lf, Ef, RBs, FUVs);
-		false -> eval_fun(Cs, As, Bs0, Lf, Ef, RBs, FUVs)
+		false -> eval_fun(Cs, As, Anno, Bs0, Lf, Ef, RBs, FUVs)
 	    end;
 	nomatch ->
-	    eval_fun(Cs, As, Bs0, Lf, Ef, RBs, FUVs)
+	    eval_fun(Cs, As, Anno, Bs0, Lf, Ef, RBs, FUVs)
     end;
-eval_fun([], As, _Bs, _Lf, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, function_clause,
-		 [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE]).
+eval_fun([], As, Anno, Bs, _Lf, Ef, RBs, _FUVs) ->
+    Stack = [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE],
+    apply_error(function_clause, Stack, Anno, Bs, Ef, RBs).
 
 
-eval_named_fun(As, Fun, {Bs0,Lf,Ef,FUVs,Cs,Name}) ->
-    eval_named_fun(Cs, As, Bs0, Lf, Ef, Name, Fun, value, FUVs).
+eval_named_fun(As, Fun, {Anno,Bs0,Lf,Ef,FUVs,Cs,Name}) ->
+    eval_named_fun(Cs, As, Anno, Bs0, Lf, Ef, Name, Fun, value, FUVs).
 
-eval_named_fun([{clause,_,H,G,B}|Cs], As, Bs0, Lf, Ef, Name, Fun, RBs, FUVs) ->
+eval_named_fun([{clause,_,H,G,B}|Cs], As, Anno, Bs0, Lf, Ef, Name, Fun, RBs, FUVs) ->
     Bs1 = add_binding(Name, Fun, Bs0),
-    case match_list(H, As, new_bindings(Bs0), Bs1) of
+    case match_list(H, As, Anno, new_bindings(Bs0), Bs1, Ef) of
         {match,Bsn} ->                      % The new bindings for the head
             Bs2 = add_bindings(Bsn, Bs1),   % which then shadow!
             case guard(G, Bs2, Lf, Ef) of
                 true -> exprs(B, Bs2, Lf, Ef, RBs, FUVs);
-                false -> eval_named_fun(Cs, As, Bs0, Lf, Ef, Name, Fun, RBs, FUVs)
+                false -> eval_named_fun(Cs, As, Anno, Bs0, Lf, Ef, Name, Fun, RBs, FUVs)
             end;
         nomatch ->
-            eval_named_fun(Cs, As, Bs0, Lf, Ef, Name, Fun, RBs, FUVs)
+            eval_named_fun(Cs, As, Anno, Bs0, Lf, Ef, Name, Fun, RBs, FUVs)
     end;
-eval_named_fun([], As, _Bs, _Lf, _Ef, _Name, _Fun, _RBs, _FUVs) ->
-    erlang:raise(error, function_clause,
-                 [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE]).
+eval_named_fun([], As, Anno, Bs, _Lf, Ef, _Name, _Fun, RBs, _FUVs) ->
+    Stack = [{?MODULE,'-inside-an-interpreted-fun-',As}|?STACKTRACE],
+    apply_error(function_clause, Stack, Anno, Bs, Ef, RBs).
 
 
 %% expr_list(ExpressionList, Bindings)
@@ -908,31 +918,31 @@ expr_list(Es, Bs, Lf, Ef, FUVs) ->
 
 expr_list([E|Es], Vs, BsOrig, Bs0, Lf, Ef, FUVs) ->
     {value,V,Bs1} = expr(E, BsOrig, Lf, Ef, none, FUVs),
-    expr_list(Es, [V|Vs], BsOrig, merge_bindings(Bs1, Bs0), Lf, Ef, FUVs);
+    expr_list(Es, [V|Vs], BsOrig, merge_bindings(Bs1, Bs0, element(2, E), Ef), Lf, Ef, FUVs);
 expr_list([], Vs, _, Bs, _Lf, _Ef, _FUVs) ->
     {reverse(Vs),Bs}.
 
-eval_op(Op, Arg1, Arg2, Bs, Ef, RBs) ->
-    do_apply(erlang, Op, [Arg1,Arg2], Bs, Ef, RBs).
+eval_op(Op, Arg1, Arg2, Anno, Bs, Ef, RBs) ->
+    do_apply(erlang, Op, [Arg1,Arg2], Anno, Bs, Ef, RBs).
 
-eval_op(Op, Arg, Bs, Ef, RBs) ->
-    do_apply(erlang, Op, [Arg], Bs, Ef, RBs).
+eval_op(Op, Arg, Anno, Bs, Ef, RBs) ->
+    do_apply(erlang, Op, [Arg], Anno, Bs, Ef, RBs).
 
-%% if_clauses(Clauses, Bindings, LocalFuncHandler, ExtFuncHandler, RBs)
+%% if_clauses(Clauses, Anno, Bindings, LocalFuncHandler, ExtFuncHandler, RBs)
 
-if_clauses([{clause,_,[],G,B}|Cs], Bs, Lf, Ef, RBs, FUVs) ->
+if_clauses([{clause,_,[],G,B}|Cs], Anno, Bs, Lf, Ef, RBs, FUVs) ->
     case guard(G, Bs, Lf, Ef) of
 	true -> exprs(B, Bs, Lf, Ef, RBs, FUVs);
-	false -> if_clauses(Cs, Bs, Lf, Ef, RBs, FUVs)
+	false -> if_clauses(Cs, Anno, Bs, Lf, Ef, RBs, FUVs)
     end;
-if_clauses([], _Bs, _Lf, _Ef, _RBs, _FUVs) ->
-    erlang:raise(error, if_clause, ?STACKTRACE).
+if_clauses([], Anno, Bs, _Lf, Ef, RBs, _FUVs) ->
+    apply_error(if_clause, ?STACKTRACE, Anno, Bs, Ef, RBs).
 
-%% try_clauses(Body, CaseClauses, CatchClauses, AfterBody, Bindings,
+%% try_clauses(Body, CaseClauses, CatchClauses, AfterBody, Anno, Bindings,
 %%             LocalFuncHandler, ExtFuncHandler, RBs)
 
-try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs, FUVs) ->
-    check_stacktrace_vars(Catches, Bs),
+try_clauses(B, Cases, Catches, AB, Anno, Bs, Lf, Ef, RBs, FUVs) ->
+    check_stacktrace_vars(Catches, Anno, Bs, Ef, RBs),
     try exprs(B, Bs, Lf, Ef, none, FUVs) of
 	{value,V,Bs1} when Cases =:= [] ->
 	    ret_expr(V, Bs1, RBs);
@@ -941,7 +951,7 @@ try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs, FUVs) ->
 		{B2,Bs2} ->
 		    exprs(B2, Bs2, Lf, Ef, RBs, FUVs);
 		nomatch ->
-		    erlang:raise(error, {try_clause,V}, ?STACKTRACE)
+                    apply_error({try_clause, V}, ?STACKTRACE, Anno, Bs, Ef, RBs)
 	    end
     catch
 	Class:Reason:Stacktrace when Catches =:= [] ->
@@ -962,36 +972,36 @@ try_clauses(B, Cases, Catches, AB, Bs, Lf, Ef, RBs, FUVs) ->
 	end
     end.
 
-check_stacktrace_vars([{clause,_,[{tuple,_,[_,_,STV]}],_,_}|Cs], Bs) ->
+
+check_stacktrace_vars([{clause,_,[{tuple,_,[_,_,STV]}],_,_}|Cs], Anno, Bs, Ef, RBs) ->
     case STV of
         {var,_,V} ->
             case binding(V, Bs) of
                 {value, _} ->
-                    erlang:raise(error, stacktrace_bound, ?STACKTRACE);
+                    apply_error(stacktrace_bound, ?STACKTRACE, Anno, Bs, Ef, RBs);
                 unbound ->
-                    check_stacktrace_vars(Cs, Bs)
+                    check_stacktrace_vars(Cs, Anno, Bs, Ef, RBs)
             end;
         _ ->
-            erlang:raise(error,
-                         {illegal_stacktrace_variable,STV},
-                         ?STACKTRACE)
+            Reason = {illegal_stacktrace_variable,STV},
+            apply_error(Reason, ?STACKTRACE, Anno, Bs, Ef, RBs)
     end;
-check_stacktrace_vars([], _Bs) ->
+check_stacktrace_vars([], _Anno, _Bs, _Ef, _RBs) ->
     ok.
 
-%% case_clauses(Value, Clauses, Bindings, LocalFuncHandler, ExtFuncHandler,
-%%              RBs)
+%% case_clauses(Value, Clauses, Anno, Bindings, LocalFuncHandler,
+%%              ExtFuncHandler, RBs)
 
-case_clauses(Val, Cs, Bs, Lf, Ef, RBs, FUVs) ->
+case_clauses(Val, Cs, Anno, Bs, Lf, Ef, RBs, FUVs) ->
     case match_clause(Cs, [Val], Bs, Lf, Ef) of
 	{B, Bs1} ->
 	    exprs(B, Bs1, Lf, Ef, RBs, FUVs);
 	nomatch ->
-	    erlang:raise(error, {case_clause,Val}, ?STACKTRACE)
+	    apply_error({case_clause,Val}, ?STACKTRACE, Anno, Bs, Ef, RBs)
     end.
 
 %%
-%% receive_clauses(Clauses, Bindings, LocalFuncHnd,ExtFuncHnd, RBs)
+%% receive_clauses(Clauses, Bindings, LocalFuncHnd, ExtFuncHnd, RBs)
 %%
 receive_clauses(Cs, Bs, Lf, Ef, RBs, FUVs) ->
     receive_clauses(infinity, Cs, unused, Bs, Lf, Ef, RBs, FUVs).
@@ -1023,8 +1033,8 @@ receive_clauses(T, Cs, TB, Bs, Lf, Ef, RBs, FUVs) ->
 match_clause(Cs, Vs, Bs, Lf) ->
     match_clause(Cs, Vs, Bs, Lf, none).
 
-match_clause([{clause,_,H,G,B}|Cs], Vals, Bs, Lf, Ef) ->
-    case match_list(H, Vals, Bs) of
+match_clause([{clause,Anno,H,G,B}|Cs], Vals, Bs, Lf, Ef) ->
+    case match_list(H, Vals, Anno, Bs, Bs, Ef) of
 	{match, Bs1} ->
 	    case guard(G, Bs1, Lf, Ef) of
 		true -> {B, Bs1};
@@ -1062,7 +1072,7 @@ guard0([G|Gs], Bs0, Lf, Ef) ->
                 {value,false,_} -> false
 	    end;
 	false ->
-	    erlang:raise(error, guard_expr, ?STACKTRACE)
+            apply_error(guard_expr, ?STACKTRACE, element(2, G), Bs0, Ef, none)
     end;
 guard0([], _Bs, _Lf, _Ef) -> true.
 
@@ -1101,23 +1111,19 @@ type_test(record) -> is_record;
 type_test(map) -> is_map;
 type_test(Test) -> Test.
 
-
-%% match(Pattern, Term, Bindings) ->
-%%	{match,NewBindings} | nomatch
+%% match(Pattern, Term, Anno, NewBindings, Bindings, ExternalFunHnd) ->
+%%      {match,NewBindings} | nomatch
 %%      or erlang:error({illegal_pattern, Pattern}).
-%%  Try to match Pattern against Term with the current bindings.
-
-match(Pat, Term, Bs) ->
-    match(Pat, Term, Bs, Bs).
-
+%%
+%% Try to match Pattern against Term with the current bindings.
 %% Bs are the bindings that are augmented with new bindings. BBs are
 %% the bindings used for "binsize" variables (in <<X:Y>>, Y is a
 %% binsize variable).
 
-match(Pat, Term, Bs, BBs) ->
-    case catch match1(Pat, Term, Bs, BBs) of
+match(Pat, Term, Anno, Bs, BBs, Ef) ->
+    case catch match1(Pat, Term, Bs, BBs, Ef) of
 	invalid ->
-	    erlang:raise(error, {illegal_pattern,to_term(Pat)}, ?STACKTRACE);
+            apply_error({illegal_pattern,to_term(Pat)}, ?STACKTRACE, Anno, Bs, Ef, none);
 	Other ->
 	    Other
     end.
@@ -1126,29 +1132,29 @@ string_to_conses([], _, Tail) -> Tail;
 string_to_conses([E|Rest], Anno, Tail) ->
     {cons, Anno, {integer, Anno, E}, string_to_conses(Rest, Anno, Tail)}.
 
-match1({atom,_,A0}, A, Bs, _BBs) ->
+match1({atom,_,A0}, A, Bs, _BBs, _Ef) ->
     case A of
 	A0 -> {match,Bs};
 	_ -> throw(nomatch)
     end;
-match1({integer,_,I0}, I, Bs, _BBs) ->
+match1({integer,_,I0}, I, Bs, _BBs, _Ef) ->
     case I of
 	I0 -> {match,Bs};
 	_ -> throw(nomatch)
     end;
-match1({float,_,F0}, F, Bs, _BBs) ->
+match1({float,_,F0}, F, Bs, _BBs, _Ef) ->
     case F of
 	F0 -> {match,Bs};
 	_ -> throw(nomatch)
     end;
-match1({char,_,C0}, C, Bs, _BBs) ->
+match1({char,_,C0}, C, Bs, _BBs, _Ef) ->
     case C of
 	C0 -> {match,Bs};
 	_ -> throw(nomatch)
     end;
-match1({var,_,'_'}, _, Bs, _BBs) ->		%Anonymous variable matches
+match1({var,_,'_'}, _, Bs, _BBs, _Ef) ->		%Anonymous variable matches
     {match,Bs};					% everything, no new bindings
-match1({var,_,Name}, Term, Bs, _BBs) ->
+match1({var,_,Name}, Term, Bs, _BBs, _Ef) ->
     case binding(Name, Bs) of
 	{value,Term} ->
 	    {match,Bs};
@@ -1157,34 +1163,34 @@ match1({var,_,Name}, Term, Bs, _BBs) ->
 	unbound ->
 	    {match,add_binding(Name, Term, Bs)}
     end;
-match1({match,_,Pat1,Pat2}, Term, Bs0, BBs) ->
-    {match, Bs1} = match1(Pat1, Term, Bs0, BBs),
-    match1(Pat2, Term, Bs1, BBs);
-match1({string,_,S0}, S, Bs, _BBs) ->
+match1({match,_,Pat1,Pat2}, Term, Bs0, BBs, Ef) ->
+    {match, Bs1} = match1(Pat1, Term, Bs0, BBs, Ef),
+    match1(Pat2, Term, Bs1, BBs, Ef);
+match1({string,_,S0}, S, Bs, _BBs, _Ef) ->
     case S of
 	S0 -> {match,Bs};
 	_ -> throw(nomatch)
     end;
-match1({nil,_}, Nil, Bs, _BBs) ->
+match1({nil,_}, Nil, Bs, _BBs, _Ef) ->
     case Nil of
 	[] -> {match,Bs};
 	_ -> throw(nomatch)
     end;
-match1({cons,_,H,T}, [H1|T1], Bs0, BBs) ->
-    {match,Bs} = match1(H, H1, Bs0, BBs),
-    match1(T, T1, Bs, BBs);
-match1({cons,_,_,_}, _, _Bs, _BBs) ->
+match1({cons,_,H,T}, [H1|T1], Bs0, BBs, Ef) ->
+    {match,Bs} = match1(H, H1, Bs0, BBs, Ef),
+    match1(T, T1, Bs, BBs, Ef);
+match1({cons,_,_,_}, _, _Bs, _BBs, _Ef) ->
     throw(nomatch);
-match1({tuple,_,Elts}, Tuple, Bs, BBs)
+match1({tuple,_,Elts}, Tuple, Bs, BBs, Ef)
          when length(Elts) =:= tuple_size(Tuple) ->
-    match_tuple(Elts, Tuple, 1, Bs, BBs);
-match1({tuple,_,_}, _, _Bs, _BBs) ->
+    match_tuple(Elts, Tuple, 1, Bs, BBs, Ef);
+match1({tuple,_,_}, _, _Bs, _BBs, _Ef) ->
     throw(nomatch);
-match1({map,_,Fs}, #{}=Map, Bs, BBs) ->
-    match_map(Fs, Map, Bs, BBs);
-match1({map,_,_}, _, _Bs, _BBs) ->
+match1({map,_,Fs}, #{}=Map, Bs, BBs, Ef) ->
+    match_map(Fs, Map, Bs, BBs, Ef);
+match1({map,_,_}, _, _Bs, _BBs, _Ef) ->
     throw(nomatch);
-match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) ->
+match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs, Ef) ->
     EvalFun = fun(E, Bs) ->
                       case erl_lint:is_guard_expr(E) of
                           true -> ok;
@@ -1197,74 +1203,72 @@ match1({bin, _, Fs}, <<_/bitstring>>=B, Bs0, BBs) ->
                               throw(invalid)
                       end
               end,
-    eval_bits:match_bits(Fs, B, Bs0, BBs, match_fun(BBs), EvalFun);
-match1({bin,_,_}, _, _Bs, _BBs) ->
+    ErrorFun = fun(A, R, S) -> apply_error(R, S, A, Bs0, Ef, none) end,
+    eval_bits:match_bits(Fs, B, Bs0, BBs, match_fun(BBs, Ef), EvalFun, ErrorFun);
+match1({bin,_,_}, _, _Bs, _BBs, _Ef) ->
     throw(nomatch);
-match1({op,_,'++',{nil,_},R}, Term, Bs, BBs) ->
-    match1(R, Term, Bs, BBs);
-match1({op,_,'++',{cons,Ai,{integer,A2,I},T},R}, Term, Bs, BBs) ->
-    match1({cons,Ai,{integer,A2,I},{op,Ai,'++',T,R}}, Term, Bs, BBs);
-match1({op,_,'++',{cons,Ai,{char,A2,C},T},R}, Term, Bs, BBs) ->
-    match1({cons,Ai,{char,A2,C},{op,Ai,'++',T,R}}, Term, Bs, BBs);
-match1({op,_,'++',{string,Ai,L},R}, Term, Bs, BBs) ->
-    match1(string_to_conses(L, Ai, R), Term, Bs, BBs);
-match1({op,Anno,Op,A}, Term, Bs, BBs) ->
+match1({op,_,'++',{nil,_},R}, Term, Bs, BBs, Ef) ->
+    match1(R, Term, Bs, BBs, Ef);
+match1({op,_,'++',{cons,Ai,{integer,A2,I},T},R}, Term, Bs, BBs, Ef) ->
+    match1({cons,Ai,{integer,A2,I},{op,Ai,'++',T,R}}, Term, Bs, BBs, Ef);
+match1({op,_,'++',{cons,Ai,{char,A2,C},T},R}, Term, Bs, BBs, Ef) ->
+    match1({cons,Ai,{char,A2,C},{op,Ai,'++',T,R}}, Term, Bs, BBs, Ef);
+match1({op,_,'++',{string,Ai,L},R}, Term, Bs, BBs, Ef) ->
+    match1(string_to_conses(L, Ai, R), Term, Bs, BBs, Ef);
+match1({op,Anno,Op,A}, Term, Bs, BBs, Ef) ->
     case partial_eval({op,Anno,Op,A}) of
 	{op,Anno,Op,A} ->
 	    throw(invalid);
 	X ->
-	    match1(X, Term, Bs, BBs)
+	    match1(X, Term, Bs, BBs, Ef)
     end;
-match1({op,Anno,Op,L,R}, Term, Bs, BBs) ->
+match1({op,Anno,Op,L,R}, Term, Bs, BBs, Ef) ->
     case partial_eval({op,Anno,Op,L,R}) of
 	{op,Anno,Op,L,R} ->
 	    throw(invalid);
 	X ->
-	    match1(X, Term, Bs, BBs)
+	    match1(X, Term, Bs, BBs, Ef)
     end;
-match1(_, _, _Bs, _BBs) ->
+match1(_, _, _Bs, _BBs, _Ef) ->
     throw(invalid).
 
-match_fun(BBs) ->
-    fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs);
+match_fun(BBs, Ef) ->
+    fun(match, {L,R,Bs}) -> match1(L, R, Bs, BBs, Ef);
        (binding, {Name,Bs}) -> binding(Name, Bs);
        (add_binding, {Name,Val,Bs}) -> add_binding(Name, Val, Bs)
     end.
 
-match_tuple([E|Es], Tuple, I, Bs0, BBs) ->
-    {match,Bs} = match1(E, element(I, Tuple), Bs0, BBs),
-    match_tuple(Es, Tuple, I+1, Bs, BBs);
-match_tuple([], _, _, Bs, _BBs) ->
+match_tuple([E|Es], Tuple, I, Bs0, BBs, Ef) ->
+    {match,Bs} = match1(E, element(I, Tuple), Bs0, BBs, Ef),
+    match_tuple(Es, Tuple, I+1, Bs, BBs, Ef);
+match_tuple([], _, _, Bs, _BBs, _Ef) ->
     {match,Bs}.
 
-match_map([{map_field_exact, _, K, V}|Fs], Map, Bs0, BBs) ->
+match_map([{map_field_exact, _, K, V}|Fs], Map, Bs0, BBs, Ef) ->
     Vm = try
 	{value, Ke, _} = expr(K, BBs),
 	maps:get(Ke,Map)
     catch error:_ ->
 	throw(nomatch)
     end,
-    {match, Bs} = match1(V, Vm, Bs0, BBs),
-    match_map(Fs, Map, Bs, BBs);
-match_map([], _, Bs, _) ->
+    {match, Bs} = match1(V, Vm, Bs0, BBs, Ef),
+    match_map(Fs, Map, Bs, BBs, Ef);
+match_map([], _, Bs, _, _) ->
     {match, Bs}.
 
-%% match_list(PatternList, TermList, Bindings) ->
+%% match_list(PatternList, TermList, Anno, NewBindings, Bindings, ExternalFunHnd) ->
 %%	{match,NewBindings} | nomatch
 %%  Try to match a list of patterns against a list of terms with the
 %%  current bindings.
 
-match_list(Ps, Ts, Bs) ->
-    match_list(Ps, Ts, Bs, Bs).
-
-match_list([P|Ps], [T|Ts], Bs0, BBs) ->
-    case match(P, T, Bs0, BBs) of
-	{match,Bs1} -> match_list(Ps, Ts, Bs1, BBs);
+match_list([P|Ps], [T|Ts], Anno, Bs0, BBs, Ef) ->
+    case match(P, T, Anno, Bs0, BBs, Ef) of
+	{match,Bs1} -> match_list(Ps, Ts, Anno, Bs1, BBs, Ef);
 	nomatch -> nomatch
     end;
-match_list([], [], Bs, _BBs) ->
+match_list([], [], _Anno, Bs, _BBs, _Ef) ->
     {match,Bs};
-match_list(_, _, _Bs, _BBs) ->
+match_list(_, _, _Anno, _Bs, _BBs, _Ef) ->
     nomatch.
 
 %% new_bindings()
@@ -1313,17 +1317,17 @@ add_bindings(Bs1, Bs2) ->
     foldl(fun ({Name,Val}, Bs) -> orddict:store(Name, Val, Bs) end,
 	  Bs2, orddict:to_list(Bs1)).
 
-merge_bindings(Bs1, Bs2) when is_map(Bs1), is_map(Bs2) ->
+merge_bindings(Bs1, Bs2, Anno, Ef) when is_map(Bs1), is_map(Bs2) ->
     maps:merge_with(fun
 	(_K, V, V) -> V;
-	(_K, _, V) -> erlang:raise(error, {badmatch,V}, ?STACKTRACE)
+	(_K, _, V) -> apply_error({badmatch,V}, ?STACKTRACE, Anno, Bs1, Ef, none)
     end, Bs2, Bs1);
-merge_bindings(Bs1, Bs2) ->
+merge_bindings(Bs1, Bs2, Anno, Ef) ->
     foldl(fun ({Name,Val}, Bs) ->
 		  case orddict:find(Name, Bs) of
 		      {ok,Val} -> Bs;		%Already with SAME value
 		      {ok,V1} ->
-			  erlang:raise(error, {badmatch,V1}, ?STACKTRACE);
+			  apply_error({badmatch,V1}, ?STACKTRACE, Anno, Bs1, Ef, none);
 		      error -> orddict:store(Name, Val, Bs)
 		  end end,
 	  Bs2, orddict:to_list(Bs1)).
@@ -1413,10 +1417,10 @@ expr_fixup([E0|Es0]) ->
 expr_fixup(T) ->
     T.
 
-string_fixup(Ann, String, Token) ->
-    Text = erl_anno:text(Ann),
+string_fixup(Anno, String, Token) ->
+    Text = erl_anno:text(Anno),
     FixupTag = fixup_tag(Text, String),
-    fixup_ast(FixupTag, Ann, String, Token).
+    fixup_ast(FixupTag, Anno, String, Token).
 
 reset_token_anno(Tokens) ->
     [setelement(2, T, (reset_anno())(element(2, T))) || T <- Tokens].
@@ -1503,7 +1507,7 @@ normalise({bin,_,Fs}) ->
 	eval_bits:expr_grp(Fs, [],
 			   fun(E, _) ->
 				   {value, normalise(E), []}
-			   end, [], true),
+			   end),
     B;
 normalise({cons,_,Head,Tail}) ->
     [normalise(Head)|normalise(Tail)];
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index 33569d4a8d..f562c6d50a 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -1397,7 +1397,7 @@ normalise({bin,_,Fs}) ->
 	eval_bits:expr_grp(Fs, [],
 			   fun(E, _) ->
 				   {value, normalise(E), []}
-			   end, [], true),
+			   end),
     B;
 normalise({cons,_,Head,Tail}) ->
     [normalise(Head)|normalise(Tail)];
diff --git a/lib/stdlib/src/eval_bits.erl b/lib/stdlib/src/eval_bits.erl
index 966bc65902..09ec175dc4 100644
--- a/lib/stdlib/src/eval_bits.erl
+++ b/lib/stdlib/src/eval_bits.erl
@@ -22,8 +22,8 @@
 
 %% Avoid warning for local function error/1 clashing with autoimported BIF.
 -compile({no_auto_import,[error/1]}).
--export([expr_grp/3,expr_grp/5,match_bits/6, 
-	 match_bits/7,bin_gen/6]).
+-export([expr_grp/3,expr_grp/4,match_bits/6,
+	 match_bits/7,bin_gen/6,bin_gen/7]).
 
 -define(STACKTRACE,
         element(2, erlang:process_info(self(), current_stacktrace))).
@@ -40,11 +40,13 @@
 %% lookup a variable in the bindings, or add a new binding
 %%
 %% @type field(). Represents a field in a "bin".
+%%
+%% @type errorfun(). A closure invoked in case of errors.
 
 %%% Part 1: expression evaluation (binary construction)
 
 %% @spec expr_grp(Fields::[field()], Bindings::bindings(), 
-%%                EvalFun::evalfun(), term(), term()) ->
+%%                EvalFun::evalfun(), ErrorFun::errorfun()) ->
 %%                  {value, binary(), bindings()}
 %%
 %% @doc Returns a tuple with {value,Bin,Bs} where Bin is the binary
@@ -52,29 +54,23 @@
 %% contains the present bindings. This function can also throw an
 %% exception if the construction fails.
 
-expr_grp(Fields, Bindings, EvalFun, [], _) ->
-    expr_grp(Fields, Bindings, EvalFun, <<>>);
-expr_grp(Fields, Bindings, EvalFun, ListOfBits, _) ->
-    Bin = convert_list(ListOfBits),
-    expr_grp(Fields, Bindings, EvalFun, Bin).
-
-convert_list(List) ->
-    << <<X:1>> || X <- List >>.
+expr_grp(Fields, Bindings, EvalFun, ErrorFun) ->
+    expr_grp(Fields, Bindings, EvalFun, ErrorFun, <<>>).
 
 expr_grp(Fields, Bindings, EvalFun) ->
-    expr_grp(Fields, Bindings, EvalFun, <<>>).
+    expr_grp(Fields, Bindings, EvalFun, fun default_error/3, <<>>).
 
-expr_grp(FS, Bs0, Ef, Acc) ->
+expr_grp(FS, Bs0, EvalFun, ErrorFun, Acc) ->
     %% Separate the evaluation of values, sizes, and TLS:s from the
     %% creation of the binary in order to mimic compiled code when it
     %% comes to loops and failures.
-    {ListOfEvalField,Bs1} = expr_grp1(FS, Bs0, Ef, []),
+    {ListOfEvalField,Bs1} = expr_grp1(FS, Bs0, EvalFun, ErrorFun, []),
     {value,create_binary(ListOfEvalField, Acc),Bs1}.
 
-expr_grp1([Field | FS], Bs0, Ef, ListOfEvalField) ->
-    {EvalField,Bs} = eval_field(Field, Bs0, Ef),
-    expr_grp1(FS, Bs, Ef, [EvalField|ListOfEvalField]);
-expr_grp1([], Bs, _Ef, ListOfFieldData) ->
+expr_grp1([Field | FS], Bs0, EvalFun, ErrorFun, ListOfEvalField) ->
+    {EvalField,Bs} = eval_field(Field, Bs0, EvalFun, ErrorFun),
+    expr_grp1(FS, Bs, EvalFun, ErrorFun, [EvalField|ListOfEvalField]);
+expr_grp1([], Bs, _EvalFun, _ErrorFun, ListOfFieldData) ->
     {lists:reverse(ListOfFieldData),Bs}.
 
 create_binary([EvalField|ListOfEvalField], Acc) ->
@@ -83,44 +79,44 @@ create_binary([EvalField|ListOfEvalField], Acc) ->
 create_binary([], Acc) ->
     Acc.
 
-eval_field({bin_element, _, {string, _, S}, {integer,_,8}, [integer,{unit,1},unsigned,big]}, Bs0, _Fun) ->
+eval_field({bin_element, _, {string, _, S}, {integer,_,8}, [integer,{unit,1},unsigned,big]}, Bs0, _Fun, _ErrorFun) ->
     Latin1 = [C band 16#FF || C <- S],
     {fun() -> list_to_binary(Latin1) end,Bs0};
-eval_field({bin_element, _, {string, _, S}, default, default}, Bs0, _Fun) ->
+eval_field({bin_element, _, {string, _, S}, default, default}, Bs0, _Fun, _ErrorFun) ->
     Latin1 = [C band 16#FF || C <- S],
     {fun() ->list_to_binary(Latin1) end,Bs0};
-eval_field({bin_element, Anno, {string, _, S}, Size0, Options0}, Bs0, Fun) ->
+eval_field({bin_element, Anno, {string, _, S}, Size0, Options0}, Bs0, Fun, ErrorFun) ->
     {Size1,[Type,{unit,Unit},Sign,Endian]} =
-        make_bit_type(Anno, Size0, Options0),
+        make_bit_type(Anno, Size0, Options0, ErrorFun),
     {value,Size,Bs1} = Fun(Size1, Bs0),
     {fun() ->
-             Res = << <<(eval_exp_field1(C, Size, Unit,
-                                         Type, Endian, Sign))/bitstring>> ||
+             Res = << <<(eval_exp_field1(Anno, C, Size, Unit,
+                                         Type, Endian, Sign, ErrorFun))/bitstring>> ||
                        C <- S >>,
              case S of
                  "" -> % find errors also when the string is empty
-                     _ = eval_exp_field1(0, Size, Unit, Type, Endian, Sign),
+                     _ = eval_exp_field1(Anno, 0, Size, Unit, Type, Endian, Sign, ErrorFun),
                      ok;
                  _ ->
                      ok
              end,
              Res
      end,Bs1};
-eval_field({bin_element,Anno,E,Size0,Options0}, Bs0, Fun) ->
+eval_field({bin_element,Anno,E,Size0,Options0}, Bs0, Fun, ErrorFun) ->
     {value,V,Bs1} = Fun(E, Bs0),
     {Size1,[Type,{unit,Unit},Sign,Endian]} = 
-        make_bit_type(Anno, Size0, Options0),
+        make_bit_type(Anno, Size0, Options0, ErrorFun),
     {value,Size,Bs} = Fun(Size1, Bs1),
-    {fun() -> eval_exp_field1(V, Size, Unit, Type, Endian, Sign) end,Bs}.
+    {fun() -> eval_exp_field1(Anno, V, Size, Unit, Type, Endian, Sign, ErrorFun) end,Bs}.
 
-eval_exp_field1(V, Size, Unit, Type, Endian, Sign) ->
+eval_exp_field1(Anno, V, Size, Unit, Type, Endian, Sign, ErrorFun) ->
     try
 	eval_exp_field(V, Size, Unit, Type, Endian, Sign)
     catch
 	error:system_limit ->
-	    erlang:raise(error, system_limit, ?STACKTRACE);
+        ErrorFun(Anno, system_limit, ?STACKTRACE);
 	error:_ ->
-	    erlang:raise(error, badarg, ?STACKTRACE)
+        ErrorFun(Anno, badarg, ?STACKTRACE)
     end.
 
 eval_exp_field(Val, Size, Unit, integer, little, signed) ->
@@ -169,7 +165,8 @@ eval_exp_field(Val, Size, Unit, binary, _, _) ->
 %%% Part 2: matching in binary comprehensions
 %% @spec bin_gen(BinPattern::{bin,integer(),[field()]}, Bin::binary(),
 %%               GlobalEnv::bindings(), LocalEnv::bindings(),  
-%%               MatchFun::matchfun(), EvalFun::evalfun()) -> 
+%%               MatchFun::matchfun(), EvalFun::evalfun(),
+%%               ErrorFun::errorfun()) ->
 %%                 {match, binary(), bindings()} | {nomatch, binary()} | done
 %%
 %% @doc Used to perform matching in a comprehension. If the match
@@ -178,25 +175,28 @@ eval_exp_field(Val, Size, Unit, binary, _, _) ->
 %% If nothing remains of the binary the atom 'done' is returned.
 
 bin_gen({bin,_,Fs}, Bin, Bs0, BBs0, Mfun, Efun) ->
-    bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, true).
+    bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, fun default_error/3, true).
 
-bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, Flag)
+bin_gen({bin,_,Fs}, Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
+    bin_gen(Fs, Bin, Bs0, BBs0, Mfun, Efun, ErrorFun, true).
+
+bin_gen([F|Fs], Bin, Bs0, BBs0, Mfun, Efun, ErrorFun, Flag)
   when is_function(Mfun, 2), is_function(Efun, 2) ->
-    case bin_gen_field(F, Bin, Bs0, BBs0, Mfun, Efun) of
+    case bin_gen_field(F, Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) of
         {match,Bs,BBs,Rest} ->
-            bin_gen(Fs, Rest, Bs, BBs, Mfun, Efun, Flag);
+            bin_gen(Fs, Rest, Bs, BBs, Mfun, Efun, ErrorFun, Flag);
         {nomatch,Rest} ->
-            bin_gen(Fs, Rest, Bs0, BBs0, Mfun, Efun, false);
+            bin_gen(Fs, Rest, Bs0, BBs0, Mfun, Efun, ErrorFun, false);
         done ->
             done
     end;
-bin_gen([], Bin, Bs0, _BBs0, _Mfun, _Efun, true) ->
+bin_gen([], Bin, Bs0, _BBs0, _Mfun, _Efun, _ErrorFun, true) ->
     {match, Bin, Bs0};
-bin_gen([], Bin, _Bs0, _BBs0, _Mfun, _Efun, false) ->
+bin_gen([], Bin, _Bs0, _BBs0, _Mfun, _Efun, _ErrorFun, false) ->
     {nomatch, Bin}.
   
 bin_gen_field({bin_element,_,{string,_,S},default,default},
-              Bin, Bs, BBs, _Mfun, _Efun) ->
+              Bin, Bs, BBs, _Mfun, _Efun, _ErrorFun) ->
     Bits = try list_to_binary(S)
            catch _:_ -> <<>>
            end,
@@ -210,9 +210,9 @@ bin_gen_field({bin_element,_,{string,_,S},default,default},
             done
     end;
 bin_gen_field({bin_element,Anno,{string,SAnno,S},Size0,Options0},
-              Bin0, Bs0, BBs0, Mfun, Efun) ->
+              Bin0, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
     {Size1, [Type,{unit,Unit},Sign,Endian]} =
-        make_bit_type(Anno, Size0, Options0),
+        make_bit_type(Anno, Size0, Options0, ErrorFun),
     case catch Efun(Size1, BBs0) of
         {value, Size, _BBs} -> % 
             F = fun(C, Bin, Bs, BBs) ->
@@ -222,9 +222,9 @@ bin_gen_field({bin_element,Anno,{string,SAnno,S},Size0,Options0},
             bin_gen_field_string(S, Bin0, Bs0, BBs0, F)
     end;
 bin_gen_field({bin_element,Anno,VE,Size0,Options0},
-              Bin, Bs0, BBs0, Mfun, Efun) ->
+              Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
     {Size1, [Type,{unit,Unit},Sign,Endian]} = 
-        make_bit_type(Anno, Size0, Options0),
+        make_bit_type(Anno, Size0, Options0, ErrorFun),
     V = erl_eval:partial_eval(VE),
     NewV = coerce_to_float(V, Type),
     case catch Efun(Size1, BBs0) of
@@ -264,41 +264,42 @@ bin_gen_field1(Bin, Type, Size, Unit, Sign, Endian, NewV, Bs0, BBs0, Mfun) ->
 %%% Part 3: binary pattern matching 
 %% @spec match_bits(Fields::[field()], Bin::binary(),
 %%                  GlobalEnv::bindings(), LocalEnv::bindings(),  
-%%                  MatchFun::matchfun(),EvalFun::evalfun(), term()) ->
-%%                  {match, bindings()} 
+%%                  MatchFun::matchfun(),EvalFun::evalfun(),
+%%                  ErrorFun::errorfun()) ->
+%%                  {match, bindings()}
 %% @doc Used to perform matching. If the match succeeds a new
 %% environment is returned. If the match have some syntactic or
 %% semantic problem which would have been caught at compile time this
 %% function throws 'invalid', if the matching fails for other reasons
 %% the function throws 'nomatch'
 
-match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, _) ->
-    match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun).
+match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun) ->
+    match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, fun default_error/3).
 
-match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun)
-  when is_function(Mfun, 2), is_function(Efun, 2) ->
-    case catch match_bits_1(Fs, Bin, Bs0, BBs, Mfun, Efun) of
+match_bits(Fs, Bin, Bs0, BBs, Mfun, Efun, ErrorFun)
+  when is_function(Mfun, 2), is_function(Efun, 2), is_function(ErrorFun, 3) ->
+    case catch match_bits_1(Fs, Bin, Bs0, BBs, Mfun, Efun, ErrorFun) of
         {match,Bs} -> {match,Bs};
         invalid -> throw(invalid);
         _Error -> throw(nomatch)
     end.
 
-match_bits_1([], <<>>,  Bs, _BBs, _Mfun, _Efun) -> 
+match_bits_1([], <<>>,  Bs, _BBs, _Mfun, _Efun, _ErrorFun) ->
     {match,Bs};
-match_bits_1([F|Fs], Bits0, Bs0, BBs0, Mfun, Efun) ->
-    {Bs,BBs,Bits} = match_field_1(F, Bits0, Bs0, BBs0, Mfun, Efun),
-    match_bits_1(Fs, Bits, Bs, BBs, Mfun, Efun).
+match_bits_1([F|Fs], Bits0, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
+    {Bs,BBs,Bits} = match_field_1(F, Bits0, Bs0, BBs0, Mfun, Efun, ErrorFun),
+    match_bits_1(Fs, Bits, Bs, BBs, Mfun, Efun, ErrorFun).
 
 match_field_1({bin_element,_,{string,_,S},default,default},
-              Bin, Bs, BBs, _Mfun, _Efun) ->
+              Bin, Bs, BBs, _Mfun, _Efun, _ErrorFun) ->
     Bits = list_to_binary(S), % fails if there are characters > 255
     Size = byte_size(Bits),
     <<Bits:Size/binary,Rest/binary-unit:1>> = Bin,
     {Bs,BBs,Rest};
 match_field_1({bin_element,Anno,{string,SAnno,S},Size0,Options0},
-              Bin0, Bs0, BBs0, Mfun, Efun) ->
+              Bin0, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
     {Size1, [Type,{unit,Unit},Sign,Endian]} =
-        make_bit_type(Anno, Size0, Options0),
+        make_bit_type(Anno, Size0, Options0, ErrorFun),
     Size2 = erl_eval:partial_eval(Size1),
     {value, Size, _BBs} = Efun(Size2, BBs0),
     F = fun(C, Bin, Bs, BBs) ->
@@ -307,9 +308,9 @@ match_field_1({bin_element,Anno,{string,SAnno,S},Size0,Options0},
         end,
     match_field_string(S, Bin0, Bs0, BBs0, F);
 match_field_1({bin_element,Anno,VE,Size0,Options0},
-              Bin, Bs0, BBs0, Mfun, Efun) ->
+              Bin, Bs0, BBs0, Mfun, Efun, ErrorFun) ->
     {Size1, [Type,{unit,Unit},Sign,Endian]} = 
-        make_bit_type(Anno, Size0, Options0),
+        make_bit_type(Anno, Size0, Options0, ErrorFun),
     V = erl_eval:partial_eval(VE),
     NewV = coerce_to_float(V, Type),
     Size2 = erl_eval:partial_eval(Size1),
@@ -410,15 +411,18 @@ get_float(Bin, Size, big) ->
     {Val,Rest}.
 
 %% Identical to the one in sys_pre_expand.
-make_bit_type(Anno, default, Type0) ->
+make_bit_type(Anno, default, Type0, ErrorFun) ->
     case erl_bits:set_bit_type(default, Type0) of
         {ok,all,Bt} -> {{atom,Anno,all},erl_bits:as_list(Bt)};
 	{ok,undefined,Bt} -> {{atom,Anno,undefined},erl_bits:as_list(Bt)};
         {ok,Size,Bt} -> {{integer,Anno,Size},erl_bits:as_list(Bt)};
-        {error,Reason} -> erlang:raise(error, Reason, ?STACKTRACE)
+        {error,Reason} -> ErrorFun(Anno, Reason, ?STACKTRACE)
     end;
-make_bit_type(_Anno, Size, Type0) -> %Size evaluates to an integer or 'all'
+make_bit_type(Anno, Size, Type0, ErrorFun) -> %Size evaluates to an integer or 'all'
     case erl_bits:set_bit_type(Size, Type0) of
         {ok,Size,Bt} -> {Size,erl_bits:as_list(Bt)};
-        {error,Reason} -> erlang:raise(error, Reason, ?STACKTRACE)
+        {error,Reason} -> ErrorFun(Anno, Reason, ?STACKTRACE)
     end.
+
+default_error(_Anno, Reason, Stacktrace) ->
+    erlang:raise(error, Reason, Stacktrace).
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index b9fa534a69..51d4600d40 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -1126,7 +1126,7 @@ normalise({bin,_,Fs}) ->
 	eval_bits:expr_grp(Fs, [],
 			   fun(E, _) ->
 				   {value, normalise(E), []}
-			   end, [], true),
+			   end),
     B;
 normalise({cons,_,Head,Tail}) ->
     [normalise(Head)|normalise(Tail)];
diff --git a/lib/stdlib/test/erl_eval_SUITE.erl b/lib/stdlib/test/erl_eval_SUITE.erl
index f4d58e61c5..16a92f7ff5 100644
--- a/lib/stdlib/test/erl_eval_SUITE.erl
+++ b/lib/stdlib/test/erl_eval_SUITE.erl
@@ -43,6 +43,7 @@
          otp_13228/1,
          otp_14826/1,
          funs/1,
+         custom_stacktrace/1,
 	 try_catch/1,
 	 eval_expr_5/1,
 	 zero_width/1,
@@ -91,7 +92,7 @@ all() ->
      simple_cases, unary_plus, apply_atom, otp_5269,
      otp_6539, otp_6543, otp_6787, otp_6977, otp_7550,
      otp_8133, otp_10622, otp_13228, otp_14826,
-     funs, try_catch, eval_expr_5, zero_width,
+     funs, custom_stacktrace, try_catch, eval_expr_5, zero_width,
      eep37, eep43, otp_15035, otp_16439, otp_14708, otp_16545, otp_16865,
      binary_skip].
 
@@ -1000,7 +1001,7 @@ otp_14826(_Config) ->
     backtrace_check("fun(P) when is_pid(P) -> true end(a).",
                     function_clause,
                     [{erl_eval,'-inside-an-interpreted-fun-',[a],[]},
-                     {erl_eval,eval_fun,7},
+                     {erl_eval,eval_fun,8},
                      ?MODULE]),
     backtrace_check("B.",
                     {unbound_var, 'B'},
@@ -1012,11 +1013,11 @@ otp_14826(_Config) ->
     backtrace_check("1/0.",
                     badarith,
                     [{erlang,'/',[1,0],[]},
-                     {erl_eval,do_apply,6}]),
+                     {erl_eval,do_apply,7}]),
     backtrace_catch("catch 1/0.",
                     badarith,
                     [{erlang,'/',[1,0],[]},
-                     {erl_eval,do_apply,6}]),
+                     {erl_eval,do_apply,7}]),
     check(fun() -> catch exit(foo) end,
           "catch exit(foo).",
           {'EXIT', foo}),
@@ -1026,33 +1027,33 @@ otp_14826(_Config) ->
     backtrace_check("try 1/0 after foo end.",
                     badarith,
                     [{erlang,'/',[1,0],[]},
-                     {erl_eval,do_apply,6}]),
+                     {erl_eval,do_apply,7}]),
     backtrace_catch("catch (try 1/0 after foo end).",
                     badarith,
                     [{erlang,'/',[1,0],[]},
-                     {erl_eval,do_apply,6}]),
+                     {erl_eval,do_apply,7}]),
     backtrace_catch("try catch 1/0 after foo end.",
                     badarith,
                     [{erlang,'/',[1,0],[]},
-                     {erl_eval,do_apply,6}]),
+                     {erl_eval,do_apply,7}]),
     backtrace_check("try a of b -> bar after foo end.",
                     {try_clause,a},
-                    [{erl_eval,try_clauses,9}]),
+                    [{erl_eval,try_clauses,10}]),
     check(fun() -> X = try foo:bar() catch A:B:C -> {A,B} end, X end,
           "try foo:bar() catch A:B:C -> {A,B} end.",
           {error, undef}),
     backtrace_check("C = 4, try foo:bar() catch A:B:C -> {A,B,C} end.",
                     stacktrace_bound,
-                    [{erl_eval,check_stacktrace_vars,2},
-                     {erl_eval,try_clauses,9}],
+                    [{erl_eval,check_stacktrace_vars,5},
+                     {erl_eval,try_clauses,10}],
                     none, none),
     backtrace_catch("catch (try a of b -> bar after foo end).",
                     {try_clause,a},
-                    [{erl_eval,try_clauses,9}]),
+                    [{erl_eval,try_clauses,10}]),
     backtrace_check("try 1/0 catch exit:a -> foo end.",
                     badarith,
                     [{erlang,'/',[1,0],[]},
-                     {erl_eval,do_apply,6}]),
+                     {erl_eval,do_apply,7}]),
     Es = [{'try',1,[{call,1,{remote,1,{atom,1,foo},{atom,1,bar}},[]}],
            [],
            [{clause,1,[{tuple,1,[{var,1,'A'},{var,1,'B'},{atom,1,'C'}]}],
@@ -1062,8 +1063,8 @@ otp_14826(_Config) ->
         ct:fail(stacktrace_variable)
     catch
         error:{illegal_stacktrace_variable,{atom,1,'C'}}:S ->
-            [{erl_eval,check_stacktrace_vars,2,_},
-             {erl_eval,try_clauses,9,_}|_] = S
+            [{erl_eval,check_stacktrace_vars,5,_},
+             {erl_eval,try_clauses,10,_}|_] = S
     end,
     backtrace_check("{1,1} = {A = 1, A = 2}.",
                     {badmatch, 1},
@@ -1073,40 +1074,40 @@ otp_14826(_Config) ->
                     [{erl_eval,guard0,4}], none, none),
     backtrace_check("case a of foo() -> ok end.",
                     {illegal_pattern,{call,1,{atom,1,foo},[]}},
-                    [{erl_eval,match,4}], none, none),
+                    [{erl_eval,match,6}], none, none),
     backtrace_check("case a of b -> ok end.",
                     {case_clause,a},
-                    [{erl_eval,case_clauses,7}, ?MODULE]),
+                    [{erl_eval,case_clauses,8}, ?MODULE]),
     backtrace_check("if a =:= b -> ok end.",
                     if_clause,
-                    [{erl_eval,if_clauses,6}, ?MODULE]),
+                    [{erl_eval,if_clauses,7}, ?MODULE]),
     backtrace_check("fun A(b) -> ok end(a).",
                     function_clause,
                     [{erl_eval,'-inside-an-interpreted-fun-',[a],[]},
-                     {erl_eval,eval_named_fun,9},
+                     {erl_eval,eval_named_fun,10},
                      ?MODULE]),
     backtrace_check("[A || A <- a].",
                     {bad_generator, a},
-                    [{erl_eval,eval_generate,7}, {erl_eval, eval_lc, 7}]),
+                    [{erl_eval,eval_generate,8}, {erl_eval, eval_lc, 7}]),
     backtrace_check("<< <<A>> || <<A>> <= a>>.",
                     {bad_generator, a},
-                    [{erl_eval,eval_b_generate,7}, {erl_eval, eval_bc, 7}]),
+                    [{erl_eval,eval_b_generate,8}, {erl_eval, eval_bc, 7}]),
     backtrace_check("[A || A <- [1], begin a end].",
                     {bad_filter, a},
-                    [{erl_eval,eval_filter,7}, {erl_eval, eval_generate, 7}]),
+                    [{erl_eval,eval_filter,7}, {erl_eval, eval_generate, 8}]),
     fun() ->
             {'EXIT', {{badarity, {_Fun, []}}, BT}} =
                 (catch parse_and_run("fun(A) -> A end().")),
-            check_backtrace([{erl_eval,do_apply,5}, ?MODULE], BT)
+            check_backtrace([{erl_eval,do_apply,6}, ?MODULE], BT)
     end(),
     fun() ->
             {'EXIT', {{badarity, {_Fun, []}}, BT}} =
                 (catch parse_and_run("fun F(A) -> A end().")),
-            check_backtrace([{erl_eval,do_apply,5}, ?MODULE], BT)
+            check_backtrace([{erl_eval,do_apply,6}, ?MODULE], BT)
     end(),
     backtrace_check("foo().",
                     undef,
-                    [{erl_eval,foo,0},{erl_eval,local_func,7}],
+                    [{erl_eval,foo,0},{erl_eval,local_func,8}],
                     none, none),
     backtrace_check("a orelse false.",
                     {badarg, a},
@@ -1141,16 +1142,16 @@ otp_14826(_Config) ->
     %% eval_bits
     backtrace_check("<<100:8/bitstring>>.",
                     badarg,
-                    [{eval_bits,eval_exp_field1,6},
+                    [{eval_bits,eval_exp_field1,8},
                      eval_bits,eval_bits,erl_eval]),
     backtrace_check("<<100:8/foo>>.",
                     {undefined_bittype,foo},
-                    [{eval_bits,make_bit_type,3},eval_bits,
+                    [{eval_bits,make_bit_type,4},eval_bits,
                      eval_bits,eval_bits],
                     none, none),
     backtrace_check("B = <<\"foo\">>, <<B/binary-unit:7>>.",
                     badarg,
-                    [{eval_bits,eval_exp_field1,6},
+                    [{eval_bits,eval_exp_field1,8},
                      eval_bits,eval_bits,erl_eval],
                     none, none),
     ok.
@@ -1172,13 +1173,143 @@ simple1() ->
         WillNeverHappen -> WillNeverHappen
     end.
 
+custom_stacktrace(Config) when is_list(Config) ->
+    EFH = {value, fun custom_stacktrace_eval_handler/3},
+
+    backtrace_check("1 + atom.", badarith,
+                    [{erlang,'+',[1,atom]}, mystack(1)], none, EFH),
+    backtrace_check("\n1 + atom.", badarith,
+                    [{erlang,'+',[1,atom]}, mystack(2)], none, EFH),
+
+    backtrace_check("lists:flatten(atom).", function_clause,
+                    [{lists,flatten,[atom]}, mystack(1)], none, EFH),
+
+    backtrace_check("invalid andalso true.", {badarg, invalid},
+                    [mystack(1)], none, EFH),
+    backtrace_check("invalid orelse true.", {badarg, invalid},
+                    [mystack(1)], none, EFH),
+
+    backtrace_check("invalid = valid.", {badmatch, valid},
+                    [erl_eval, mystack(1)], none, EFH),
+
+    backtrace_check("1:2.", {badexpr, ':'},
+                    [erl_eval, mystack(1)], none, EFH),
+
+    backtrace_check("Unknown.", {unbound, 'Unknown'},
+                    [erl_eval, mystack(1)], none, EFH),
+
+    backtrace_check("#unknown{}.", {undef_record,unknown},
+                    [erl_eval, mystack(1)], none, EFH),
+    backtrace_check("#unknown{foo=bar}.", {undef_record,unknown},
+                    [erl_eval, mystack(1)], none, EFH),
+    backtrace_check("#unknown.index.", {undef_record,unknown},
+                    [erl_eval, mystack(1)], none, EFH),
+
+    backtrace_check("fun foo/2.", undef,
+                    [{erl_eval, foo, 2}, erl_eval, mystack(1)], none, EFH),
+    backtrace_check("foo(1, 2).", undef,
+                    [{erl_eval, foo, 2}, erl_eval, mystack(1)], none, EFH),
+
+    fun() ->
+            {'EXIT', {{badarity, {_Fun, []}}, BT}} =
+                (catch parse_and_run("fun(A) -> A end().", none, EFH)),
+            check_backtrace([erl_eval, mystack(1)], BT)
+    end(),
+
+    fun() ->
+            {'EXIT', {{badarity, {_Fun, []}}, BT}} =
+                (catch parse_and_run("fun F(A) -> A end().", none, EFH)),
+            check_backtrace([erl_eval, mystack(1)], BT)
+    end(),
+
+    backtrace_check("[X || X <- 1].", {bad_generator, 1},
+                    [erl_eval, mystack(1)], none, EFH),
+    backtrace_check("[X || <<X>> <= 1].", {bad_generator, 1},
+                    [erl_eval, mystack(1)], none, EFH),
+    backtrace_check("<<X || X <- 1>>.", {bad_generator, 1},
+                    [erl_eval, mystack(1)], none, EFH),
+    backtrace_check("<<X || <<X>> <= 1>>.", {bad_generator, 1},
+                    [erl_eval, mystack(1)], none, EFH),
+
+    backtrace_check("if false -> true end.", if_clause,
+                    [erl_eval, mystack(1)], none, EFH),
+    backtrace_check("case 0 of 1 -> true end.", {case_clause, 0},
+                    [erl_eval, mystack(1)], none, EFH),
+    backtrace_check("try 0 of 1 -> true after ok end.", {try_clause, 0},
+                    [mystack(1)], none, EFH),
+
+    backtrace_check("fun(0) -> 1 end(1).", function_clause,
+                    [{erl_eval,'-inside-an-interpreted-fun-', [1]}, erl_eval, mystack(1)],
+                    none, EFH),
+    backtrace_check("fun F(0) -> 1 end(1).", function_clause,
+                    [{erl_eval,'-inside-an-interpreted-fun-', [1]}, erl_eval, mystack(1)],
+                    none, EFH),
+
+    fun() ->
+            {'EXIT', {{illegal_pattern,_}, BT}} =
+                (catch parse_and_run("make_ref() = 1.", none, EFH)),
+            check_backtrace([erl_eval, mystack(1)], BT)
+    end(),
+
+    %% eval_bits
+    backtrace_check("<<100:8/bitstring>>.",
+                    badarg,
+                    [{eval_bits,eval_exp_field1,8}, mystack(1)],
+                    none, EFH),
+    backtrace_check("<<100:8/foo>>.",
+                    {undefined_bittype,foo},
+                    [{eval_bits,make_bit_type,4}, mystack(1)],
+                    none, EFH),
+    backtrace_check("B = <<\"foo\">>, <<B/binary-unit:7>>.",
+                    badarg,
+                    [{eval_bits,eval_exp_field1,8}, mystack(1)],
+                    none, EFH),
+
+    ok.
+
+mystack(Line) ->
+    {my_module, my_function, 0, [{file, "evaluator"}, {line, Line}]}.
+
+custom_stacktrace_eval_handler(Ann, FunOrModFun, Args) ->
+    try
+        case FunOrModFun of
+            {Mod, Fun} -> apply(Mod, Fun, Args);
+            Fun -> apply(Fun, Args)
+        end
+    catch
+        Kind:Reason:Stacktrace ->
+            %% Take everything up to the evaluation function
+            Pruned =
+                lists:takewhile(fun
+                  ({erl_eval_SUITE,backtrace_check,5,_}) -> false;
+                  (_) -> true
+                end, Stacktrace),
+            %% Now we prune any shared code path from erl_eval
+            {current_stacktrace, Current} =
+                erlang:process_info(self(), current_stacktrace),
+            Reversed = drop_common(lists:reverse(Current), lists:reverse(Pruned)),
+            Location = [{file, "evaluator"}, {line, erl_anno:line(Ann)}],
+            %% Add our file+line information at the bottom
+            Custom = lists:reverse([{my_module, my_function, 0, Location} | Reversed]),
+            erlang:raise(Kind, Reason, Custom)
+    end.
+
+drop_common([H | T1], [H | T2]) -> drop_common(T1, T2);
+drop_common([H | T1], T2) -> drop_common(T1, T2);
+drop_common([], [{?MODULE, custom_stacktrace_eval_handler, _, _} | T2]) -> T2;
+drop_common([], T2) -> T2.
+
 %% Simple cases, just to cover some code.
 funs(Config) when is_list(Config) ->
     do_funs(none, none),
     do_funs(lfh(), none),
+    do_funs(none, efh()),
     do_funs(lfh(), efh()),
+    do_funs(none, ann_efh()),
+    do_funs(lfh(), ann_efh()),
 
     error_check("nix:foo().", {access_not_allowed,nix}, lfh(), efh()),
+    error_check("nix:foo().", {access_not_allowed,nix}, lfh(), ann_efh()),
     error_check("bar().", undef, none, none),
 
     check(fun() -> F1 = fun(F,N) -> ?MODULE:count_down(F, N) end,
@@ -1217,6 +1348,15 @@ funs(Config) when is_list(Config) ->
     error_check("apply(timer, sleep, [1]).", got_it, none, EFH),
     error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.",
                       got_it, none, EFH),
+
+    AnnEF = fun(1, {timer,sleep}, As) when length(As) == 1 -> exit({got_it,sleep});
+               (1, {M,F}, As) -> apply(M, F, As)
+         end,
+    AnnEFH = {value, AnnEF},
+    error_check("apply(timer, sleep, [1]).", got_it, none, AnnEFH),
+    error_check("begin F = fun(T) -> timer:sleep(T) end,F(1) end.",
+                      got_it, none, AnnEFH),
+
     error_check("fun c/1.", undef),
     error_check("fun a:b/0().", undef),
 
@@ -1398,6 +1538,9 @@ local_func_value(F, As) when is_atom(F) ->
 efh() ->
     {value, fun(F, As) -> external_func(F, As) end}.
 
+ann_efh() ->
+    {value, fun(_Ann, F, As) -> external_func(F, As) end}.
+
 external_func({M,_}, _As) when M == nix ->
     exit({{access_not_allowed,M},[mfa]});
 external_func(F, As) when is_function(F) ->
diff --git a/lib/stdlib/test/shell_SUITE.erl b/lib/stdlib/test/shell_SUITE.erl
index 56f1bb5b6f..89b745057f 100644
--- a/lib/stdlib/test/shell_SUITE.erl
+++ b/lib/stdlib/test/shell_SUITE.erl
@@ -256,6 +256,8 @@ restricted_local(Config) when is_list(Config) ->
                   local_allowed(_,_,State) ->
                       {false,State}.
 
+                  non_local_allowed({erlang,raise},[error, _, _],State) ->
+                      {true,State};
                   non_local_allowed({shell,stop_restricted},[],State) ->
                       {true,State};
                   non_local_allowed(_,_,State) ->
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 354b65c9a3..f62cfb4108 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -7310,7 +7310,7 @@ concrete(Node) ->
 		eval_bits:expr_grp(Fs, [],
 				   fun(F, _) ->
 					   {value, concrete(F), []}
-				   end, [], true),
+				   end),
 	    B;
         arity_qualifier ->
             A = erl_syntax:arity_qualifier_argument(Node),
-- 
2.34.1

openSUSE Build Service is sponsored by