diff options
Diffstat (limited to 'lib/dialyzer/src/dialyzer_races.erl')
-rw-r--r-- | lib/dialyzer/src/dialyzer_races.erl | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl index 2aa8343bce..2a8aba5d8f 100644 --- a/lib/dialyzer/src/dialyzer_races.erl +++ b/lib/dialyzer/src/dialyzer_races.erl @@ -2,7 +2,7 @@ %%----------------------------------------------------------------------- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2012. All Rights Reserved. +%% Copyright Ericsson AB 2008-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -85,6 +85,12 @@ -type race_tag() :: 'whereis_register' | 'whereis_unregister' | 'ets_lookup_insert' | 'mnesia_dirty_read_write'. +%% The following type is similar to the dial_warning() type but has a +%% tag which is local to this module and is not propagated to outside +-type dial_race_warning() :: {race_warn_tag(), file_line(), {atom(), [term()]}}. +-type race_warn_tag() :: ?WARN_WHEREIS_REGISTER | ?WARN_WHEREIS_UNREGISTER + | ?WARN_ETS_LOOKUP_INSERT | ?WARN_MNESIA_DIRTY_READ_WRITE. + -record(beg_clause, {arg :: var_to_map1(), pats :: var_to_map1(), guard :: cerl:cerl()}). @@ -98,14 +104,14 @@ def_vars :: [core_vars()], arg_types :: [erl_types:erl_type()], call_vars :: [core_vars()], - var_map :: dict()}). + var_map :: dict:dict()}). -record(dep_call, {call_name :: dep_calls(), args :: args(), arg_types :: [erl_types:erl_type()], vars :: [core_vars()], - state :: _, %% XXX: recursive + state :: dialyzer_dataflow:state(), file_line :: file_line(), - var_map :: dict()}). + var_map :: dict:dict()}). -record(fun_call, {caller :: dialyzer_callgraph:mfa_or_funlbl(), callee :: dialyzer_callgraph:mfa_or_funlbl(), arg_types :: [erl_types:erl_type()], @@ -114,7 +120,7 @@ arg :: var_to_map1()}). -record(warn_call, {call_name :: warn_calls(), args :: args(), - var_map :: dict()}). + var_map :: dict:dict()}). -type case_tags() :: 'beg_case' | #beg_clause{} | #end_clause{} | #end_case{}. -type code() :: [#dep_call{} | #fun_call{} | #warn_call{} | @@ -141,7 +147,7 @@ race_tags = [] :: [#race_fun{}], %% true for fun types and warning mode race_analysis = false :: boolean(), - race_warnings = [] :: [dial_warning()]}). + race_warnings = [] :: [dial_race_warning()]}). %%% =========================================================================== %%% @@ -984,8 +990,7 @@ fixup_race_forward_helper(CurrFun, CurrFunLabel, Fun, FunLabel, NewRaceVarMap, Args, NewFunArgs, NewFunTypes, NestingLevel}; {CurrFun, Fun} -> NewCallsToAnalyze = lists:delete(Head, CallsToAnalyze), - NewRaceVarMap = - race_var_map(Args, NewFunArgs, RaceVarMap, bind), + NewRaceVarMap = race_var_map(Args, NewFunArgs, RaceVarMap, bind), RetC = case Fun of InitFun -> @@ -1012,8 +1017,7 @@ fixup_race_forward_helper(CurrFun, CurrFunLabel, Fun, FunLabel, label = FunLabel, var_map = NewRaceVarMap, def_vars = Args, call_vars = NewFunArgs, arg_types = NewFunTypes}| - lists:reverse(StateRaceList)] ++ - RetC; + lists:reverse(StateRaceList)] ++ RetC; _ -> [#curr_fun{status = in, mfa = Fun, label = FunLabel, var_map = NewRaceVarMap, @@ -1048,13 +1052,9 @@ fixup_race_backward(CurrFun, Calls, CallsToAnalyze, Parents, Height) -> false -> [CurrFun|Parents] end; [Head|Tail] -> - MorePaths = - case Head of - {Parent, CurrFun} -> true; - {Parent, _TupleB} -> false - end, - case MorePaths of - true -> + {Parent, TupleB} = Head, + case TupleB =:= CurrFun of + true -> % more paths are needed NewCallsToAnalyze = lists:delete(Head, CallsToAnalyze), NewParents = fixup_race_backward(Parent, NewCallsToAnalyze, @@ -1565,7 +1565,7 @@ any_args(StrList) -> end end. --spec bind_dict_vars(label(), label(), dict()) -> dict(). +-spec bind_dict_vars(label(), label(), dict:dict()) -> dict:dict(). bind_dict_vars(Key, Label, RaceVarMap) -> case Key =:= Label of @@ -1751,7 +1751,7 @@ compare_vars(Var1, Var2, RaceVarMap) when is_integer(Var1), is_integer(Var2) -> compare_vars(_Var1, _Var2, _RaceVarMap) -> false. --spec compare_var_list(label_type(), [label_type()], dict()) -> boolean(). +-spec compare_var_list(label_type(), [label_type()], dict:dict()) -> boolean(). compare_var_list(Var, VarList, RaceVarMap) -> lists:any(fun (V) -> compare_vars(Var, V, RaceVarMap) end, VarList). @@ -1763,7 +1763,7 @@ ets_list_args(MaybeList) -> catch _:_ -> [?no_label] end; false -> [ets_tuple_args(MaybeList)] - end. + end. ets_list_argtypes(ListStr) -> ListStr1 = string:strip(ListStr, left, $[), @@ -1848,7 +1848,8 @@ ets_tuple_argtypes1(Str, Tuple, TupleList, NestingLevel) -> end. format_arg(?bypassed) -> ?no_label; -format_arg(Arg) -> +format_arg(Arg0) -> + Arg = cerl:fold_literal(Arg0), case cerl:type(Arg) of var -> cerl_trees:get_label(Arg); tuple -> list_to_tuple([format_arg(A) || A <- cerl:tuple_es(Arg)]); @@ -1878,7 +1879,7 @@ format_args_1([Arg|Args], [Type|Types], CleanState) -> case Arg =:= ?bypassed of true -> [?no_label, format_type(Type, CleanState)]; false -> - case cerl:is_literal(Arg) of + case cerl:is_literal(cerl:fold_literal(Arg)) of true -> [?no_label, format_cerl(Arg)]; false -> [format_arg(Arg), format_type(Type, CleanState)] end @@ -1956,7 +1957,8 @@ mnesia_tuple_argtypes(TupleStr) -> [TupleStr2|_T] = string:tokens(TupleStr1, " ,"), lists:flatten(string:tokens(TupleStr2, " |")). --spec race_var_map(var_to_map1(), var_to_map2(), dict(), op()) -> dict(). +-spec race_var_map(var_to_map1(), var_to_map2(), dict:dict(), op()) -> + dict:dict(). race_var_map(Vars1, Vars2, RaceVarMap, Op) -> case Vars1 =:= ?no_arg orelse Vars1 =:= ?bypassed @@ -2147,7 +2149,8 @@ race_var_map_guard_helper1(Arg, Pats, RaceVarMap, Op) -> end end. -race_var_map_guard_helper2(Arg, Pat, Bool, RaceVarMap, Op) -> +race_var_map_guard_helper2(Arg, Pat0, Bool, RaceVarMap, Op) -> + Pat = cerl:fold_literal(Pat0), case cerl:type(Pat) of literal -> [Arg1, Arg2] = cerl:call_args(Arg), |