File 0533-Teach-ssalint-to-catch-badly-formed-annotations.patch of Package erlang
From bb6b256bc7f7ae38e87884ae46eaa13cff9ac5e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Thu, 2 Nov 2023 15:59:18 +0100
Subject: [PATCH 3/3] Teach ssalint to catch badly formed annotations
---
lib/compiler/src/beam_ssa_lint.erl | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/lib/compiler/src/beam_ssa_lint.erl b/lib/compiler/src/beam_ssa_lint.erl
index 7f50c42d2f..fd8ca3f5c0 100644
--- a/lib/compiler/src/beam_ssa_lint.erl
+++ b/lib/compiler/src/beam_ssa_lint.erl
@@ -117,7 +117,8 @@ vvars_assert_unique(Blocks, Args) ->
-spec vvars_assert_unique_1(Is, Defined) -> ok when
Is :: list(beam_ssa:b_set()),
Defined :: #{ beam_ssa:b_var() => beam_ssa:b_set() }.
-vvars_assert_unique_1([#b_set{dst=Dst}=I|Is], Defined) ->
+vvars_assert_unique_1([#b_set{dst=Dst,anno=Anno}=I|Is], Defined) ->
+ check_anno(Anno),
case Defined of
#{Dst:=Old} -> throw({redefined_variable, Dst, Old, I});
_ -> vvars_assert_unique_1(Is, Defined#{Dst=>I})
@@ -288,7 +289,8 @@ vvars_block_1([], _Terminator, State) ->
Terminator :: beam_ssa:terminator(),
From :: beam_ssa:label(),
State :: #vvars{}.
-vvars_terminator(#b_ret{ arg = Arg }=I, From, State) ->
+vvars_terminator(#b_ret{arg=Arg,anno=Anno}=I, From, State) ->
+ check_anno(Anno),
ok = vvars_assert_args([Arg], I, State),
TryTags = State#vvars.try_tags,
case {gb_sets:is_empty(TryTags),From} of
@@ -302,17 +304,20 @@ vvars_terminator(#b_ret{ arg = Arg }=I, From, State) ->
{true,_} ->
State
end;
-vvars_terminator(#b_switch{arg=Arg,fail=Fail,list=Switch}=I, From, State) ->
+vvars_terminator(#b_switch{arg=Arg,fail=Fail,list=Switch,anno=Anno}=I, From, State) ->
+ check_anno(Anno),
ok = vvars_assert_args([Arg], I, State),
ok = vvars_assert_args([A || {A,_Lbl} <- Switch], I, State),
Labels = [Fail | [Lbl || {_Arg, Lbl} <- Switch]],
ok = vvars_assert_labels(Labels, I, State),
vvars_terminator_1(Labels, From, State);
-vvars_terminator(#b_br{bool=#b_literal{val=true},succ=Succ}=I, From, State) ->
+vvars_terminator(#b_br{bool=#b_literal{val=true},succ=Succ,anno=Anno}=I, From, State) ->
+ check_anno(Anno),
Labels = [Succ],
ok = vvars_assert_labels(Labels, I, State),
vvars_terminator_1(Labels, From, State);
-vvars_terminator(#b_br{ bool = Arg, succ = Succ, fail = Fail }=I, From, State) ->
+vvars_terminator(#b_br{bool=Arg,succ=Succ,fail=Fail,anno=Anno}=I, From, State) ->
+ check_anno(Anno),
ok = vvars_assert_args([Arg], I, State),
Labels = [Fail, Succ],
ok = vvars_assert_labels(Labels, I, State),
@@ -430,6 +435,9 @@ vvars_kill_try_tag(Var, State0) ->
TryTags = gb_sets:delete(Var, State0#vvars.try_tags),
State0#vvars{ try_tags = TryTags }.
+check_anno(#{}) -> ok;
+check_anno(BadAnno) -> throw({bad_annotation,BadAnno}).
+
format_error_1({redefined_variable, Name, Old, I}) ->
io_lib:format("Variable ~ts (~ts) redefined by ~ts",
[format_var(Name), format_instr(Old), format_instr(I)]);
@@ -472,4 +480,6 @@ format_error_1({succeeded_not_followed_by_two_way_br, I}) ->
format_error_1({active_try_tags_on_return, TryTags0, I}) ->
TryTags = format_vars(gb_sets:to_list(TryTags0)),
io_lib:format("Try tags ~ts are still active on ~ts",
- [TryTags, format_instr(I)]).
+ [TryTags, format_instr(I)]);
+format_error_1({bad_annotation, BadAnno}) ->
+ io_lib:format("Badly formed annotation: ~p", [BadAnno]).
--
2.35.3