1%%% -*- erlang-indent-level: 4 -*- 2%% 3%% %CopyrightBegin% 4%% 5%% Copyright Ericsson AB 1996-2020. All Rights Reserved. 6%% 7%% Licensed under the Apache License, Version 2.0 (the "License"); 8%% you may not use this file except in compliance with the License. 9%% You may obtain a copy of the License at 10%% 11%% http://www.apache.org/licenses/LICENSE-2.0 12%% 13%% Unless required by applicable law or agreed to in writing, software 14%% distributed under the License is distributed on an "AS IS" BASIS, 15%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16%% See the License for the specific language governing permissions and 17%% limitations under the License. 18%% 19%% %CopyrightEnd% 20%% 21%% Do necessary checking of Erlang code. 22 23-module(erl_lint). 24 25-export([module/1,module/2,module/3,format_error/1]). 26-export([exprs/2,exprs_opt/3,used_vars/2]). % Used from erl_eval.erl. 27-export([is_pattern_expr/1,is_guard_test/1,is_guard_test/2,is_guard_test/3]). 28-export([is_guard_expr/1]). 29-export([bool_option/4,value_option/3,value_option/7]). 30 31-import(lists, [all/2,any/2, 32 foldl/3,foldr/3, 33 map/2,mapfoldl/3,member/2, 34 reverse/1]). 35 36%% Removed functions 37 38-removed([{modify_line,2,"use erl_parse:map_anno/2 instead"}]). 39 40%% bool_option(OnOpt, OffOpt, Default, Options) -> boolean(). 41%% value_option(Flag, Default, Options) -> Value. 42%% value_option(Flag, Default, OnOpt, OnVal, OffOpt, OffVal, Options) -> 43%% Value. 44%% The option handling functions. 45 46-spec bool_option(atom(), atom(), boolean(), [compile:option()]) -> boolean(). 47 48bool_option(On, Off, Default, Opts) -> 49 foldl(fun (Opt, _Def) when Opt =:= On -> true; 50 (Opt, _Def) when Opt =:= Off -> false; 51 (_Opt, Def) -> Def 52 end, Default, Opts). 53 54value_option(Flag, Default, Opts) -> 55 foldl(fun ({Opt,Val}, _Def) when Opt =:= Flag -> Val; 56 (_Opt, Def) -> Def 57 end, Default, Opts). 58 59value_option(Flag, Default, On, OnVal, Off, OffVal, Opts) -> 60 foldl(fun ({Opt,Val}, _Def) when Opt =:= Flag -> Val; 61 (Opt, _Def) when Opt =:= On -> OnVal; 62 (Opt, _Def) when Opt =:= Off -> OffVal; 63 (_Opt, Def) -> Def 64 end, Default, Opts). 65 66%% The maximum number of arguments allowed for a function. 67 68-define(MAX_ARGUMENTS, 255). 69 70%% The error and warning info structures, {Line,Module,Descriptor}, 71%% are kept in their seperate fields in the lint state record together 72%% with the name of the file (when a new file is entered, marked by 73%% the 'file' attribute, then the field 'file' of the lint record is 74%% set). At the end of the run these lists are packed into a list of 75%% {FileName,ErrorDescList} pairs which are returned. 76 77-include_lib("stdlib/include/erl_bits.hrl"). 78 79%%-define(DEBUGF(X,Y), io:format(X, Y)). 80-define(DEBUGF(X,Y), void). 81 82-type line() :: erl_anno:anno(). % a convenient alias 83-type fa() :: {atom(), arity()}. % function+arity 84-type ta() :: {atom(), arity()}. % type+arity 85 86-type module_or_mfa() :: module() | mfa(). 87 88-type gexpr_context() :: 'guard' | 'bin_seg_size' | 'map_key'. 89 90-record(typeinfo, {attr, line}). 91 92%% Usage of records, functions, and imports. The variable table, which 93%% is passed on as an argument, holds the usage of variables. 94-record(usage, { 95 calls = maps:new(), %Who calls who 96 imported = [], %Actually imported functions 97 used_records = gb_sets:new() %Used record definitions 98 :: gb_sets:set(atom()), 99 used_types = maps:new() %Used type definitions 100 :: #{ta() := line()} 101 }). 102 103 104%% Define the lint state record. 105%% 'called' and 'exports' contain {Line, {Function, Arity}}, 106%% the other function collections contain {Function, Arity}. 107-record(lint, {state=start :: 'start' | 'attribute' | 'function', 108 module='', %Module 109 behaviour=[], %Behaviour 110 exports=gb_sets:empty() :: gb_sets:set(fa()),%Exports 111 imports=[] :: orddict:orddict(fa(), module()),%Imports 112 compile=[], %Compile flags 113 records=maps:new() %Record definitions 114 :: #{atom() => {line(),Fields :: term()}}, 115 locals=gb_sets:empty() %All defined functions (prescanned) 116 :: gb_sets:set(fa()), 117 no_auto=gb_sets:empty() %Functions explicitly not autoimported 118 :: gb_sets:set(fa()) | 'all', 119 defined=gb_sets:empty() %Defined fuctions 120 :: gb_sets:set(fa()), 121 on_load=[] :: [fa()], %On-load function 122 on_load_line=erl_anno:new(0) %Line for on_load 123 :: erl_anno:anno(), 124 clashes=[], %Exported functions named as BIFs 125 not_deprecated=[], %Not considered deprecated 126 not_removed=gb_sets:empty() %Not considered removed 127 :: gb_sets:set(module_or_mfa()), 128 func=[], %Current function 129 warn_format=0, %Warn format calls 130 enabled_warnings=[], %All enabled warnings (ordset). 131 nowarn_bif_clash=[], %All no warn bif clashes (ordset). 132 errors=[], %Current errors 133 warnings=[], %Current warnings 134 file = "" :: string(), %From last file attribute 135 recdef_top=false :: boolean(), %true in record initialisation 136 %outside any fun or lc 137 xqlc= false :: boolean(), %true if qlc.hrl included 138 called= [] :: [{fa(),line()}], %Called functions 139 usage = #usage{} :: #usage{}, 140 specs = maps:new() %Type specifications 141 :: #{mfa() => line()}, 142 callbacks = maps:new() %Callback types 143 :: #{mfa() => line()}, 144 optional_callbacks = maps:new() %Optional callbacks 145 :: #{mfa() => line()}, 146 types = maps:new() %Type definitions 147 :: #{ta() => #typeinfo{}}, 148 exp_types=gb_sets:empty() %Exported types 149 :: gb_sets:set(ta()), 150 in_try_head=false :: boolean(), %In a try head. 151 bvt = none :: 'none' | [any()], %Variables in binary pattern 152 gexpr_context = guard %Context of guard expression 153 :: gexpr_context() 154 }). 155 156-type lint_state() :: #lint{}. 157-type error_description() :: term(). 158-type error_info() :: {erl_anno:line(), module(), error_description()}. 159 160%% format_error(Error) 161%% Return a string describing the error. 162 163-spec format_error(ErrorDescriptor) -> io_lib:chars() when 164 ErrorDescriptor :: error_description(). 165 166format_error(undefined_module) -> 167 "no module definition"; 168format_error(redefine_module) -> 169 "redefining module"; 170format_error(pmod_unsupported) -> 171 "parameterized modules are no longer supported"; 172%% format_error({redefine_mod_import, M, P}) -> 173%% io_lib:format("module '~s' already imported from package '~s'", [M, P]); 174format_error(non_latin1_module_unsupported) -> 175 "module names with non-latin1 characters are not supported"; 176 177format_error(invalid_call) -> 178 "invalid function call"; 179format_error(invalid_record) -> 180 "invalid record expression"; 181 182format_error({attribute,A}) -> 183 io_lib:format("attribute ~tw after function definitions", [A]); 184format_error({missing_qlc_hrl,A}) -> 185 io_lib:format("qlc:q/~w called, but \"qlc.hrl\" not included", [A]); 186format_error({redefine_import,{{F,A},M}}) -> 187 io_lib:format("function ~tw/~w already imported from ~w", [F,A,M]); 188format_error({bad_inline,{F,A}}) -> 189 io_lib:format("inlined function ~tw/~w undefined", [F,A]); 190format_error({invalid_deprecated,D}) -> 191 io_lib:format("badly formed deprecated attribute ~tw", [D]); 192format_error({bad_deprecated,{F,A}}) -> 193 io_lib:format("deprecated function ~tw/~w undefined or not exported", 194 [F,A]); 195format_error({invalid_removed,D}) -> 196 io_lib:format("badly formed removed attribute ~tw", [D]); 197format_error({bad_removed,{F,A}}) when F =:= '_'; A =:= '_' -> 198 io_lib:format("at least one function matching ~tw/~w is still exported", 199 [F,A]); 200format_error({bad_removed,{F,A}}) -> 201 io_lib:format("removed function ~tw/~w is still exported", 202 [F,A]); 203format_error({bad_nowarn_unused_function,{F,A}}) -> 204 io_lib:format("function ~tw/~w undefined", [F,A]); 205format_error({bad_nowarn_bif_clash,{F,A}}) -> 206 io_lib:format("function ~tw/~w undefined", [F,A]); 207format_error(disallowed_nowarn_bif_clash) -> 208 io_lib:format("compile directive nowarn_bif_clash is no longer allowed,~n" 209 " - use explicit module names or -compile({no_auto_import, [F/A]})", []); 210format_error({bad_on_load,Term}) -> 211 io_lib:format("badly formed on_load attribute: ~tw", [Term]); 212format_error(multiple_on_loads) -> 213 "more than one on_load attribute"; 214format_error({bad_on_load_arity,{F,A}}) -> 215 io_lib:format("function ~tw/~w has wrong arity (must be 0)", [F,A]); 216format_error({undefined_on_load,{F,A}}) -> 217 io_lib:format("function ~tw/~w undefined", [F,A]); 218format_error(nif_inline) -> 219 "inlining is enabled - local calls to NIFs may call their Erlang " 220 "implementation instead"; 221 222format_error(export_all) -> 223 "export_all flag enabled - all functions will be exported"; 224format_error({duplicated_export, {F,A}}) -> 225 io_lib:format("function ~tw/~w already exported", [F,A]); 226format_error({unused_import,{{F,A},M}}) -> 227 io_lib:format("import ~w:~tw/~w is unused", [M,F,A]); 228format_error({undefined_function,{F,A}}) -> 229 io_lib:format("function ~tw/~w undefined", [F,A]); 230format_error({redefine_function,{F,A}}) -> 231 io_lib:format("function ~tw/~w already defined", [F,A]); 232format_error({define_import,{F,A}}) -> 233 io_lib:format("defining imported function ~tw/~w", [F,A]); 234format_error({unused_function,{F,A}}) -> 235 io_lib:format("function ~tw/~w is unused", [F,A]); 236format_error({call_to_redefined_bif,{F,A}}) -> 237 io_lib:format("ambiguous call of overridden auto-imported BIF ~w/~w~n" 238 " - use erlang:~w/~w or \"-compile({no_auto_import,[~w/~w]}).\" " 239 "to resolve name clash", [F,A,F,A,F,A]); 240format_error({call_to_redefined_old_bif,{F,A}}) -> 241 io_lib:format("ambiguous call of overridden pre R14 auto-imported BIF ~w/~w~n" 242 " - use erlang:~w/~w or \"-compile({no_auto_import,[~w/~w]}).\" " 243 "to resolve name clash", [F,A,F,A,F,A]); 244format_error({redefine_old_bif_import,{F,A}}) -> 245 io_lib:format("import directive overrides pre R14 auto-imported BIF ~w/~w~n" 246 " - use \"-compile({no_auto_import,[~w/~w]}).\" " 247 "to resolve name clash", [F,A,F,A]); 248format_error({redefine_bif_import,{F,A}}) -> 249 io_lib:format("import directive overrides auto-imported BIF ~w/~w~n" 250 " - use \"-compile({no_auto_import,[~w/~w]}).\" to resolve name clash", [F,A,F,A]); 251format_error({deprecated, MFA, String, Rel}) -> 252 io_lib:format("~s is deprecated and will be removed in ~s; use ~s", 253 [format_mfa(MFA), Rel, String]); 254format_error({deprecated, MFA, String}) when is_list(String) -> 255 io_lib:format("~s is deprecated; ~s", [format_mfa(MFA), String]); 256format_error({deprecated_type, {M1, F1, A1}, String}) when is_list(String) -> 257 io_lib:format("the type ~p:~p~s is deprecated; ~s", 258 [M1, F1, gen_type_paren(A1), String]); 259format_error({removed, MFA, ReplacementMFA, Rel}) -> 260 io_lib:format("call to ~s will fail, since it was removed in ~s; " 261 "use ~s", [format_mfa(MFA), Rel, format_mfa(ReplacementMFA)]); 262format_error({removed, MFA, String}) when is_list(String) -> 263 io_lib:format("~s is removed; ~s", [format_mfa(MFA), String]); 264format_error({removed_type, MNA, String}) -> 265 io_lib:format("the type ~s is removed; ~s", [format_mna(MNA), String]); 266format_error({obsolete_guard, {F, A}}) -> 267 io_lib:format("~p/~p obsolete (use is_~p/~p)", [F, A, F, A]); 268format_error({obsolete_guard_overridden,Test}) -> 269 io_lib:format("obsolete ~s/1 (meaning is_~s/1) is illegal when " 270 "there is a local/imported function named is_~p/1 ", 271 [Test,Test,Test]); 272format_error({too_many_arguments,Arity}) -> 273 io_lib:format("too many arguments (~w) - " 274 "maximum allowed is ~w", [Arity,?MAX_ARGUMENTS]); 275%% --- patterns and guards --- 276format_error(illegal_pattern) -> "illegal pattern"; 277format_error(illegal_map_key) -> "illegal map key in pattern"; 278format_error(illegal_bin_pattern) -> 279 "binary patterns cannot be matched in parallel using '='"; 280format_error(illegal_expr) -> "illegal expression"; 281format_error({illegal_guard_local_call, {F,A}}) -> 282 io_lib:format("call to local/imported function ~tw/~w is illegal in guard", 283 [F,A]); 284format_error(illegal_guard_expr) -> "illegal guard expression"; 285%% --- maps --- 286format_error(illegal_map_construction) -> 287 "only association operators '=>' are allowed in map construction"; 288%% --- records --- 289format_error({undefined_record,T}) -> 290 io_lib:format("record ~tw undefined", [T]); 291format_error({redefine_record,T}) -> 292 io_lib:format("record ~tw already defined", [T]); 293format_error({redefine_field,T,F}) -> 294 io_lib:format("field ~tw already defined in record ~tw", [F,T]); 295format_error(bad_multi_field_init) -> 296 io_lib:format("'_' initializes no omitted fields", []); 297format_error({undefined_field,T,F}) -> 298 io_lib:format("field ~tw undefined in record ~tw", [F,T]); 299format_error(illegal_record_info) -> 300 "illegal record info"; 301format_error({field_name_is_variable,T,F}) -> 302 io_lib:format("field ~tw is not an atom or _ in record ~tw", [F,T]); 303format_error({wildcard_in_update,T}) -> 304 io_lib:format("meaningless use of _ in update of record ~tw", [T]); 305format_error({unused_record,T}) -> 306 io_lib:format("record ~tw is unused", [T]); 307format_error({untyped_record,T}) -> 308 io_lib:format("record ~tw has field(s) without type information", [T]); 309%% --- variables ---- 310format_error({unbound_var,V}) -> 311 io_lib:format("variable ~w is unbound", [V]); 312format_error({unsafe_var,V,{What,Where}}) -> 313 io_lib:format("variable ~w unsafe in ~w ~s", 314 [V,What,format_where(Where)]); 315format_error({exported_var,V,{What,Where}}) -> 316 io_lib:format("variable ~w exported from ~w ~s", 317 [V,What,format_where(Where)]); 318format_error({shadowed_var,V,In}) -> 319 io_lib:format("variable ~w shadowed in ~w", [V,In]); 320format_error({unused_var, V}) -> 321 io_lib:format("variable ~w is unused", [V]); 322format_error({variable_in_record_def,V}) -> 323 io_lib:format("variable ~w in record definition", [V]); 324format_error({stacktrace_guard,V}) -> 325 io_lib:format("stacktrace variable ~w must not be used in a guard", [V]); 326format_error({stacktrace_bound,V}) -> 327 io_lib:format("stacktrace variable ~w must not be previously bound", [V]); 328%% --- binaries --- 329format_error({undefined_bittype,Type}) -> 330 io_lib:format("bit type ~tw undefined", [Type]); 331format_error({bittype_mismatch,Val1,Val2,What}) -> 332 io_lib:format("conflict in ~s specification for bit field: '~p' and '~p'", 333 [What,Val1,Val2]); 334format_error(bittype_unit) -> 335 "a bit unit size must not be specified unless a size is specified too"; 336format_error(illegal_bitsize) -> 337 "illegal bit size"; 338format_error({illegal_bitsize_local_call, {F,A}}) -> 339 io_lib:format("call to local/imported function ~tw/~w is illegal in a size " 340 "expression for a binary segment", 341 [F,A]); 342format_error(non_integer_bitsize) -> 343 "a size expression in a pattern evaluates to a non-integer value; " 344 "this pattern cannot possibly match"; 345format_error(unsized_binary_not_at_end) -> 346 "a binary field without size is only allowed at the end of a binary pattern"; 347format_error(typed_literal_string) -> 348 "a literal string in a binary pattern must not have a type or a size"; 349format_error(utf_bittype_size_or_unit) -> 350 "neither size nor unit must be given for segments of type utf8/utf16/utf32"; 351format_error({bad_bitsize,Type}) -> 352 io_lib:format("bad ~s bit size", [Type]); 353format_error(unsized_binary_in_bin_gen_pattern) -> 354 "binary fields without size are not allowed in patterns of bit string generators"; 355%% --- behaviours --- 356format_error({conflicting_behaviours,{Name,Arity},B,FirstL,FirstB}) -> 357 io_lib:format("conflicting behaviours - callback ~tw/~w required by both '~p' " 358 "and '~p' ~s", [Name,Arity,B,FirstB,format_where(FirstL)]); 359format_error({undefined_behaviour_func, {Func,Arity}, Behaviour}) -> 360 io_lib:format("undefined callback function ~tw/~w (behaviour '~w')", 361 [Func,Arity,Behaviour]); 362format_error({undefined_behaviour,Behaviour}) -> 363 io_lib:format("behaviour ~tw undefined", [Behaviour]); 364format_error({undefined_behaviour_callbacks,Behaviour}) -> 365 io_lib:format("behaviour ~w callback functions are undefined", 366 [Behaviour]); 367format_error({ill_defined_behaviour_callbacks,Behaviour}) -> 368 io_lib:format("behaviour ~w callback functions erroneously defined", 369 [Behaviour]); 370format_error({ill_defined_optional_callbacks,Behaviour}) -> 371 io_lib:format("behaviour ~w optional callback functions erroneously defined", 372 [Behaviour]); 373format_error({behaviour_info, {_M,F,A}}) -> 374 io_lib:format("cannot define callback attibute for ~tw/~w when " 375 "behaviour_info is defined",[F,A]); 376format_error({redefine_optional_callback, {F, A}}) -> 377 io_lib:format("optional callback ~tw/~w duplicated", [F, A]); 378format_error({undefined_callback, {_M, F, A}}) -> 379 io_lib:format("callback ~tw/~w is undefined", [F, A]); 380%% --- types and specs --- 381format_error({singleton_typevar, Name}) -> 382 io_lib:format("type variable ~w is only used once (is unbound)", [Name]); 383format_error({bad_export_type, _ETs}) -> 384 io_lib:format("bad export_type declaration", []); 385format_error({duplicated_export_type, {T, A}}) -> 386 io_lib:format("type ~tw/~w already exported", [T, A]); 387format_error({undefined_type, {TypeName, Arity}}) -> 388 io_lib:format("type ~tw~s undefined", [TypeName, gen_type_paren(Arity)]); 389format_error({unused_type, {TypeName, Arity}}) -> 390 io_lib:format("type ~tw~s is unused", [TypeName, gen_type_paren(Arity)]); 391format_error({new_builtin_type, {TypeName, Arity}}) -> 392 io_lib:format("type ~w~s is a new builtin type; " 393 "its (re)definition is allowed only until the next release", 394 [TypeName, gen_type_paren(Arity)]); 395format_error({builtin_type, {TypeName, Arity}}) -> 396 io_lib:format("type ~w~s is a builtin type; it cannot be redefined", 397 [TypeName, gen_type_paren(Arity)]); 398format_error({renamed_type, OldName, NewName}) -> 399 io_lib:format("type ~w() is now called ~w(); " 400 "please use the new name instead", [OldName, NewName]); 401format_error({redefine_type, {TypeName, Arity}}) -> 402 io_lib:format("type ~tw~s already defined", 403 [TypeName, gen_type_paren(Arity)]); 404format_error({type_syntax, Constr}) -> 405 io_lib:format("bad ~tw type", [Constr]); 406format_error(old_abstract_code) -> 407 io_lib:format("abstract code generated before Erlang/OTP 19.0 and " 408 "having typed record fields cannot be compiled", []); 409format_error({redefine_spec, {M, F, A}}) -> 410 io_lib:format("spec for ~tw:~tw/~w already defined", [M, F, A]); 411format_error({redefine_spec, {F, A}}) -> 412 io_lib:format("spec for ~tw/~w already defined", [F, A]); 413format_error({redefine_callback, {F, A}}) -> 414 io_lib:format("callback ~tw/~w already defined", [F, A]); 415format_error({bad_callback, {M, F, A}}) -> 416 io_lib:format("explicit module not allowed for callback ~tw:~tw/~w", 417 [M, F, A]); 418format_error({bad_module, {M, F, A}}) -> 419 io_lib:format("spec for function ~w:~tw/~w from other module", [M, F, A]); 420format_error({spec_fun_undefined, {F, A}}) -> 421 io_lib:format("spec for undefined function ~tw/~w", [F, A]); 422format_error({missing_spec, {F,A}}) -> 423 io_lib:format("missing specification for function ~tw/~w", [F, A]); 424format_error(spec_wrong_arity) -> 425 "spec has wrong arity"; 426format_error(callback_wrong_arity) -> 427 "callback has wrong arity"; 428format_error({deprecated_builtin_type, {Name, Arity}, 429 Replacement, Rel}) -> 430 UseS = case Replacement of 431 {Mod, NewName} -> 432 io_lib:format("use ~w:~w/~w", [Mod, NewName, Arity]); 433 {Mod, NewName, NewArity} -> 434 io_lib:format("use ~w:~w/~w or preferably ~w:~w/~w", 435 [Mod, NewName, Arity, 436 Mod, NewName, NewArity]) 437 end, 438 io_lib:format("type ~w/~w is deprecated and will be " 439 "removed in ~s; use ~s", 440 [Name, Arity, Rel, UseS]); 441format_error({not_exported_opaque, {TypeName, Arity}}) -> 442 io_lib:format("opaque type ~tw~s is not exported", 443 [TypeName, gen_type_paren(Arity)]); 444format_error({underspecified_opaque, {TypeName, Arity}}) -> 445 io_lib:format("opaque type ~tw~s is underspecified and therefore meaningless", 446 [TypeName, gen_type_paren(Arity)]); 447format_error({bad_dialyzer_attribute,Term}) -> 448 io_lib:format("badly formed dialyzer attribute: ~tw", [Term]); 449format_error({bad_dialyzer_option,Term}) -> 450 io_lib:format("unknown dialyzer warning option: ~tw", [Term]); 451%% --- obsolete? unused? --- 452format_error({format_error, {Fmt, Args}}) -> 453 io_lib:format(Fmt, Args). 454 455gen_type_paren(Arity) when is_integer(Arity), Arity >= 0 -> 456 gen_type_paren_1(Arity, ")"). 457 458gen_type_paren_1(0, Acc) -> "(" ++ Acc; 459gen_type_paren_1(1, Acc) -> "(_" ++ Acc; 460gen_type_paren_1(N, Acc) -> gen_type_paren_1(N - 1, ",_" ++ Acc). 461 462format_mfa({M, F, [_|_]=As}) -> 463 ","++ArityString = lists:append([[$,|integer_to_list(A)] || A <- As]), 464 format_mf(M, F, ArityString); 465format_mfa({M, F, A}) when is_integer(A) -> 466 format_mf(M, F, integer_to_list(A)). 467 468format_mf(M, F, ArityString) when is_atom(M), is_atom(F) -> 469 atom_to_list(M) ++ ":" ++ atom_to_list(F) ++ "/" ++ ArityString. 470 471format_mna({M, N, A}) when is_integer(A) -> 472 atom_to_list(M) ++ ":" ++ atom_to_list(N) ++ gen_type_paren(A). 473 474format_where(L) when is_integer(L) -> 475 io_lib:format("(line ~p)", [L]); 476format_where({L,C}) when is_integer(L), is_integer(C) -> 477 io_lib:format("(line ~p, column ~p)", [L, C]). 478 479%% Local functions that are somehow automatically generated. 480 481pseudolocals() -> 482 [{module_info,0}, {module_info,1}, {record_info,2}]. 483 484%% 485%% Used by erl_eval.erl to check commands. 486%% 487exprs(Exprs, BindingsList) -> 488 exprs_opt(Exprs, BindingsList, []). 489 490exprs_opt(Exprs, BindingsList, Opts) -> 491 {St0,Vs} = foldl(fun({{record,_SequenceNumber,_Name},Attr0}, {St1,Vs1}) -> 492 Attr = set_file(Attr0, "none"), 493 {attribute_state(Attr, St1),Vs1}; 494 ({V,_}, {St1,Vs1}) -> 495 {St1,[{V,{bound,unused,[]}} | Vs1]} 496 end, {start("nofile",Opts),[]}, BindingsList), 497 Vt = orddict:from_list(Vs), 498 {_Evt,St} = exprs(set_file(Exprs, "nofile"), Vt, St0), 499 return_status(St). 500 501used_vars(Exprs, BindingsList) -> 502 Vs = foldl(fun({{record,_SequenceNumber,_Name},_Attr}, Vs0) -> Vs0; 503 ({V,_Val}, Vs0) -> [{V,{bound,unused,[]}} | Vs0] 504 end, [], BindingsList), 505 Vt = orddict:from_list(Vs), 506 {Evt,_St} = exprs(set_file(Exprs, "nofile"), Vt, start()), 507 {ok, foldl(fun({V,{_,used,_}}, L) -> [V | L]; 508 (_, L) -> L 509 end, [], Evt)}. 510 511%% module([Form]) -> 512%% module([Form], FileName) -> 513%% module([Form], FileName, [CompileOption]) -> 514%% {ok,[Warning]} | {error,[Error],[Warning]} 515%% Start processing a module. Define predefined functions and exports and 516%% apply_lambda/2 has been called to shut lint up. N.B. these lists are 517%% really all ordsets! 518 519-spec(module(AbsForms) -> {ok, Warnings} | {error, Errors, Warnings} when 520 AbsForms :: [erl_parse:abstract_form() | erl_parse:form_info()], 521 Warnings :: [{file:filename(),[ErrorInfo]}], 522 Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}], 523 ErrorInfo :: error_info()). 524 525module(Forms) -> 526 Opts = compiler_options(Forms), 527 St = forms(Forms, start("nofile", Opts)), 528 return_status(St). 529 530-spec(module(AbsForms, FileName) -> 531 {ok, Warnings} | {error, Errors, Warnings} when 532 AbsForms :: [erl_parse:abstract_form() | erl_parse:form_info()], 533 FileName :: atom() | string(), 534 Warnings :: [{file:filename(),[ErrorInfo]}], 535 Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}], 536 ErrorInfo :: error_info()). 537 538module(Forms, FileName) -> 539 Opts = compiler_options(Forms), 540 St = forms(Forms, start(FileName, Opts)), 541 return_status(St). 542 543-spec(module(AbsForms, FileName, CompileOptions) -> 544 {ok, Warnings} | {error, Errors, Warnings} when 545 AbsForms :: [erl_parse:abstract_form() | erl_parse:form_info()], 546 FileName :: atom() | string(), 547 CompileOptions :: [compile:option()], 548 Warnings :: [{file:filename(),[ErrorInfo]}], 549 Errors :: [{FileName2 :: file:filename(),[ErrorInfo]}], 550 ErrorInfo :: error_info()). 551 552module(Forms, FileName, Opts0) -> 553 %% We want the options given on the command line to take 554 %% precedence over options in the module. 555 Opts = compiler_options(Forms) ++ Opts0, 556 St = forms(Forms, start(FileName, Opts)), 557 return_status(St). 558 559compiler_options(Forms) -> 560 lists:flatten([C || {attribute,_,compile,C} <- Forms]). 561 562%% start() -> State 563%% start(FileName, [Option]) -> State 564 565start() -> 566 start("nofile", []). 567 568start(File, Opts) -> 569 Enabled0 = 570 [{unused_vars, 571 bool_option(warn_unused_vars, nowarn_unused_vars, 572 true, Opts)}, 573 {export_all, 574 bool_option(warn_export_all, nowarn_export_all, 575 true, Opts)}, 576 {export_vars, 577 bool_option(warn_export_vars, nowarn_export_vars, 578 false, Opts)}, 579 {shadow_vars, 580 bool_option(warn_shadow_vars, nowarn_shadow_vars, 581 true, Opts)}, 582 {unused_import, 583 bool_option(warn_unused_import, nowarn_unused_import, 584 false, Opts)}, 585 {unused_function, 586 bool_option(warn_unused_function, nowarn_unused_function, 587 true, Opts)}, 588 {unused_type, 589 bool_option(warn_unused_type, nowarn_unused_type, 590 true, Opts)}, 591 {bif_clash, 592 bool_option(warn_bif_clash, nowarn_bif_clash, 593 true, Opts)}, 594 {unused_record, 595 bool_option(warn_unused_record, nowarn_unused_record, 596 true, Opts)}, 597 {deprecated_function, 598 bool_option(warn_deprecated_function, nowarn_deprecated_function, 599 true, Opts)}, 600 {deprecated_type, 601 bool_option(warn_deprecated_type, nowarn_deprecated_type, 602 true, Opts)}, 603 {obsolete_guard, 604 bool_option(warn_obsolete_guard, nowarn_obsolete_guard, 605 true, Opts)}, 606 {untyped_record, 607 bool_option(warn_untyped_record, nowarn_untyped_record, 608 false, Opts)}, 609 {missing_spec, 610 bool_option(warn_missing_spec, nowarn_missing_spec, 611 false, Opts)}, 612 {missing_spec_all, 613 bool_option(warn_missing_spec_all, nowarn_missing_spec_all, 614 false, Opts)}, 615 {removed, 616 bool_option(warn_removed, nowarn_removed, 617 true, Opts)}, 618 {nif_inline, 619 bool_option(warn_nif_inline, nowarn_nif_inline, 620 true, Opts)} 621 ], 622 Enabled1 = [Category || {Category,true} <- Enabled0], 623 Enabled = ordsets:from_list(Enabled1), 624 Calls = case ordsets:is_element(unused_function, Enabled) of 625 true -> 626 maps:from_list([{{module_info,1},pseudolocals()}]); 627 false -> 628 undefined 629 end, 630 #lint{state = start, 631 exports = gb_sets:from_list([{module_info,0},{module_info,1}]), 632 compile = Opts, 633 %% Internal pseudo-functions must appear as defined/reached. 634 defined = gb_sets:from_list(pseudolocals()), 635 called = [{F,0} || F <- pseudolocals()], 636 usage = #usage{calls=Calls}, 637 warn_format = value_option(warn_format, 1, warn_format, 1, 638 nowarn_format, 0, Opts), 639 enabled_warnings = Enabled, 640 nowarn_bif_clash = nowarn_function(nowarn_bif_clash, Opts), 641 file = File 642 }. 643 644%% is_warn_enabled(Category, St) -> boolean(). 645%% Check whether a warning of category Category is enabled. 646is_warn_enabled(Type, #lint{enabled_warnings=Enabled}) -> 647 ordsets:is_element(Type, Enabled). 648 649%% return_status(State) -> 650%% {ok,[Warning]} | {error,[Error],[Warning]} 651%% Pack errors and warnings properly and return ok | error. 652 653return_status(St) -> 654 Ws = pack_warnings(St#lint.warnings), 655 case pack_errors(St#lint.errors) of 656 [] -> {ok,Ws}; 657 Es -> {error,Es,Ws} 658 end. 659 660%% pack_errors([{File,ErrD}]) -> [{File,[ErrD]}]. 661%% Sort on (reversed) insertion order. 662 663pack_errors(Es) -> 664 {Es1,_} = mapfoldl(fun ({File,E}, I) -> {{File,{I,E}}, I-1} end, -1, Es), 665 map(fun ({File,EIs}) -> {File, map(fun ({_I,E}) -> E end, EIs)} end, 666 pack_warnings(Es1)). 667 668%% pack_warnings([{File,ErrD}]) -> [{File,[ErrD]}] 669%% Sort on line number. 670 671pack_warnings(Ws) -> 672 [{File,lists:sort([W || {F,W} <- Ws, F =:= File])} || 673 File <- lists:usort([F || {F,_} <- Ws])]. 674 675%% add_error(ErrorDescriptor, State) -> State' 676%% add_error(Line, Error, State) -> State' 677%% add_warning(ErrorDescriptor, State) -> State' 678%% add_warning(Line, Error, State) -> State' 679 680add_error(E, St) -> add_lint_error(E, St#lint.file, St). 681 682add_error(Anno, E0, #lint{gexpr_context=Context}=St) -> 683 E = case {E0,Context} of 684 {illegal_guard_expr,bin_seg_size} -> 685 illegal_bitsize; 686 {{illegal_guard_local_call,FA},bin_seg_size} -> 687 {illegal_bitsize_local_call,FA}; 688 {_,_} -> E0 689 end, 690 {File,Location} = loc(Anno, St), 691 add_lint_error({Location,erl_lint,E}, File, St). 692 693add_lint_error(E, File, St) -> 694 St#lint{errors=[{File,E}|St#lint.errors]}. 695 696add_warning(W, St) -> add_lint_warning(W, St#lint.file, St). 697 698add_warning(FileLine, W, St) -> 699 {File,Location} = loc(FileLine, St), 700 add_lint_warning({Location,erl_lint,W}, File, St). 701 702add_lint_warning(W, File, St) -> 703 St#lint{warnings=[{File,W}|St#lint.warnings]}. 704 705loc(Anno, St) -> 706 Location = erl_anno:location(Anno), 707 case erl_anno:file(Anno) of 708 undefined -> {St#lint.file,Location}; 709 File -> {File,Location} 710 end. 711 712%% forms([Form], State) -> State' 713 714forms(Forms0, St0) -> 715 Forms = eval_file_attribute(Forms0, St0), 716 %% Annotations from now on include the 'file' item. 717 Locals = local_functions(Forms), 718 AutoImportSuppressed = auto_import_suppressed(St0#lint.compile), 719 StDeprecated = disallowed_compile_flags(Forms,St0), 720 St1 = includes_qlc_hrl(Forms, StDeprecated#lint{locals = Locals, 721 no_auto = AutoImportSuppressed}), 722 St2 = bif_clashes(Forms, St1), 723 St3 = not_deprecated(Forms, St2), 724 St4 = not_removed(Forms, St3), 725 St5 = foldl(fun form/2, pre_scan(Forms, St4), Forms), 726 post_traversal_check(Forms, St5). 727 728pre_scan([{attribute,L,compile,C} | Fs], St) -> 729 case is_warn_enabled(export_all, St) andalso 730 member(export_all, lists:flatten([C])) of 731 true -> 732 pre_scan(Fs, add_warning(L, export_all, St)); 733 false -> 734 pre_scan(Fs, St) 735 end; 736pre_scan([_ | Fs], St) -> 737 pre_scan(Fs, St); 738pre_scan([], St) -> 739 St. 740 741includes_qlc_hrl(Forms, St) -> 742 %% QLC calls erl_lint several times, sometimes with the compile 743 %% attribute removed. The file attribute, however, is left as is. 744 QH = [File || {attribute,_,file,{File,_line}} <- Forms, 745 filename:basename(File) =:= "qlc.hrl"], 746 St#lint{xqlc = QH =/= []}. 747 748eval_file_attribute(Forms, St) -> 749 eval_file_attr(Forms, St#lint.file). 750 751eval_file_attr([{attribute,_L,file,{File,_Line}}=Form | Forms], _File) -> 752 [Form | eval_file_attr(Forms, File)]; 753eval_file_attr([Form0 | Forms], File) -> 754 Form = set_form_file(Form0, File), 755 [Form | eval_file_attr(Forms, File)]; 756eval_file_attr([], _File) -> 757 []. 758 759%% Sets the file only on the form. This is used on post-traversal. 760%% For the remaining of the AST we rely on #lint.file. 761 762set_form_file({attribute,L,K,V}, File) -> 763 {attribute,erl_anno:set_file(File, L),K,V}; 764set_form_file({function,L,N,A,C}, File) -> 765 {function,erl_anno:set_file(File, L),N,A,C}; 766set_form_file(Form, _File) -> 767 Form. 768 769set_file(Ts, File) when is_list(Ts) -> 770 [anno_set_file(T, File) || T <- Ts]; 771set_file(T, File) -> 772 anno_set_file(T, File). 773 774anno_set_file(T, File) -> 775 F = fun(Anno) -> erl_anno:set_file(File, Anno) end, 776 erl_parse:map_anno(F, T). 777 778%% form(Form, State) -> State' 779%% Check a form returning the updated State. Handle generic cases here. 780 781form({error,E}, St) -> add_error(E, St); 782form({warning,W}, St) -> add_warning(W, St); 783form({attribute,_L,file,{File,_Line}}, St) -> 784 St#lint{file = File}; 785form({attribute,_L,compile,_}, St) -> 786 St; 787form(Form, #lint{state=State}=St) -> 788 case State of 789 start -> start_state(Form, St); 790 attribute -> attribute_state(Form, St); 791 function -> function_state(Form, St) 792 end. 793 794%% start_state(Form, State) -> State' 795 796start_state({attribute,Line,module,{_,_}}=Form, St0) -> 797 St1 = add_error(Line, pmod_unsupported, St0), 798 attribute_state(Form, St1#lint{state=attribute}); 799start_state({attribute,Line,module,M}, St0) -> 800 St1 = St0#lint{module=M}, 801 St2 = St1#lint{state=attribute}, 802 check_module_name(M, Line, St2); 803start_state(Form, St) -> 804 Anno = case Form of 805 {eof, L} -> erl_anno:new(L); 806 %% {warning, Warning} and {error, Error} not possible here. 807 _ -> element(2, Form) 808 end, 809 St1 = add_error(Anno, undefined_module, St), 810 attribute_state(Form, St1#lint{state=attribute}). 811 812%% attribute_state(Form, State) -> 813%% State' 814 815attribute_state({attribute,_L,module,_M}, #lint{module=''}=St) -> 816 St; 817attribute_state({attribute,L,module,_M}, St) -> 818 add_error(L, redefine_module, St); 819attribute_state({attribute,L,export,Es}, St) -> 820 export(L, Es, St); 821attribute_state({attribute,L,export_type,Es}, St) -> 822 export_type(L, Es, St); 823attribute_state({attribute,L,import,Is}, St) -> 824 import(L, Is, St); 825attribute_state({attribute,L,record,{Name,Fields}}, St) -> 826 record_def(L, Name, Fields, St); 827attribute_state({attribute,La,behaviour,Behaviour}, St) -> 828 St#lint{behaviour=St#lint.behaviour ++ [{La,Behaviour}]}; 829attribute_state({attribute,La,behavior,Behaviour}, St) -> 830 St#lint{behaviour=St#lint.behaviour ++ [{La,Behaviour}]}; 831attribute_state({attribute,L,type,{TypeName,TypeDef,Args}}, St) -> 832 type_def(type, L, TypeName, TypeDef, Args, St); 833attribute_state({attribute,L,opaque,{TypeName,TypeDef,Args}}, St) -> 834 type_def(opaque, L, TypeName, TypeDef, Args, St); 835attribute_state({attribute,L,spec,{Fun,Types}}, St) -> 836 spec_decl(L, Fun, Types, St); 837attribute_state({attribute,L,callback,{Fun,Types}}, St) -> 838 callback_decl(L, Fun, Types, St); 839attribute_state({attribute,L,optional_callbacks,Es}, St) -> 840 optional_callbacks(L, Es, St); 841attribute_state({attribute,L,on_load,Val}, St) -> 842 on_load(L, Val, St); 843attribute_state({attribute,_L,_Other,_Val}, St) -> % Ignore others 844 St; 845attribute_state(Form, St) -> 846 function_state(Form, St#lint{state=function}). 847 848%% function_state(Form, State) -> 849%% State' 850%% Allow for record, type and opaque type definitions and spec 851%% declarations to be intersperced within function definitions. 852%% Dialyzer attributes are also allowed everywhere. 853 854function_state({attribute,L,record,{Name,Fields}}, St) -> 855 record_def(L, Name, Fields, St); 856function_state({attribute,L,type,{TypeName,TypeDef,Args}}, St) -> 857 type_def(type, L, TypeName, TypeDef, Args, St); 858function_state({attribute,L,opaque,{TypeName,TypeDef,Args}}, St) -> 859 type_def(opaque, L, TypeName, TypeDef, Args, St); 860function_state({attribute,L,spec,{Fun,Types}}, St) -> 861 spec_decl(L, Fun, Types, St); 862function_state({attribute,_L,dialyzer,_Val}, St) -> 863 St; 864function_state({attribute,La,Attr,_Val}, St) -> 865 add_error(La, {attribute,Attr}, St); 866function_state({function,L,N,A,Cs}, St) -> 867 function(L, N, A, Cs, St); 868function_state({eof,L}, St) -> eof(L, St). 869 870%% eof(LastLine, State) -> 871%% State' 872 873eof(_Line, St0) -> 874 St0. 875 876%% bif_clashes(Forms, State0) -> State. 877 878bif_clashes(Forms, #lint{nowarn_bif_clash=Nowarn} = St) -> 879 Clashes0 = [{Name,Arity} || {function,_L,Name,Arity,_Cs} <- Forms, 880 erl_internal:bif(Name, Arity)], 881 Clashes = ordsets:subtract(ordsets:from_list(Clashes0), Nowarn), 882 St#lint{clashes=Clashes}. 883 884%% not_deprecated(Forms, State0) -> State 885 886not_deprecated(Forms, #lint{compile=Opts}=St0) -> 887 %% There are no line numbers in St0#lint.compile. 888 MFAsL = [{MFA,L} || 889 {attribute, L, compile, Args} <- Forms, 890 {nowarn_deprecated_function, MFAs0} <- lists:flatten([Args]), 891 MFA <- lists:flatten([MFAs0])], 892 Nowarn = [MFA || 893 {nowarn_deprecated_function, MFAs0} <- Opts, 894 MFA <- lists:flatten([MFAs0])], 895 ML = [{M,L} || {{M,_F,_A},L} <- MFAsL, is_atom(M)], 896 St1 = foldl(fun ({M,L}, St2) -> 897 check_module_name(M, L, St2) 898 end, St0, ML), 899 St1#lint{not_deprecated = ordsets:from_list(Nowarn)}. 900 901%% not_removed(Forms, State0) -> State 902 903not_removed(Forms, #lint{compile=Opts}=St0) -> 904 %% There are no line numbers in St0#lint.compile. 905 MFAsL = [{MFA,L} || 906 {attribute, L, compile, Args} <- Forms, 907 {nowarn_removed, MFAs0} <- lists:flatten([Args]), 908 MFA <- lists:flatten([MFAs0])], 909 Nowarn = [MFA || 910 {nowarn_removed, MFAs0} <- Opts, 911 MFA <- lists:flatten([MFAs0])], 912 St1 = foldl(fun ({{M, _F, _A}, L}, St2) -> 913 check_module_name(M, L, St2); 914 ({M,L}, St2) -> 915 check_module_name(M, L, St2) 916 end, St0, MFAsL), 917 St1#lint{not_removed = gb_sets:from_list(Nowarn)}. 918 919%% The nowarn_bif_clash directive is not only deprecated, it's actually an error from R14A 920disallowed_compile_flags(Forms, St0) -> 921 %% There are (still) no line numbers in St0#lint.compile. 922 Errors0 = [ {St0#lint.file,{L,erl_lint,disallowed_nowarn_bif_clash}} || 923 {attribute,A,compile,nowarn_bif_clash} <- Forms, 924 {_,L} <- [loc(A, St0)] ], 925 Errors1 = [ {St0#lint.file,{L,erl_lint,disallowed_nowarn_bif_clash}} || 926 {attribute,A,compile,{nowarn_bif_clash, {_,_}}} <- Forms, 927 {_,L} <- [loc(A, St0)] ], 928 Disabled = (not is_warn_enabled(bif_clash, St0)), 929 Errors = if 930 Disabled andalso Errors0 =:= [] -> 931 [{St0#lint.file,{erl_lint,disallowed_nowarn_bif_clash}} | St0#lint.errors]; 932 Disabled -> 933 Errors0 ++ Errors1 ++ St0#lint.errors; 934 true -> 935 Errors1 ++ St0#lint.errors 936 end, 937 St0#lint{errors=Errors}. 938 939%% post_traversal_check(Forms, State0) -> State. 940%% Do some further checking after the forms have been traversed and 941%% data about calls etc. have been collected. 942 943post_traversal_check(Forms, St0) -> 944 St1 = check_behaviour(St0), 945 St2 = check_deprecated(Forms, St1), 946 St3 = check_imports(Forms, St2), 947 St4 = check_inlines(Forms, St3), 948 St5 = check_undefined_functions(St4), 949 St6 = check_unused_functions(Forms, St5), 950 St7 = check_bif_clashes(Forms, St6), 951 St8 = check_specs_without_function(St7), 952 St9 = check_functions_without_spec(Forms, St8), 953 StA = check_undefined_types(St9), 954 StB = check_unused_types(Forms, StA), 955 StC = check_untyped_records(Forms, StB), 956 StD = check_on_load(StC), 957 StE = check_unused_records(Forms, StD), 958 StF = check_local_opaque_types(StE), 959 StG = check_dialyzer_attribute(Forms, StF), 960 StH = check_callback_information(StG), 961 check_removed(Forms, StH). 962 963%% check_behaviour(State0) -> State 964%% Check that the behaviour attribute is valid. 965 966check_behaviour(St0) -> 967 behaviour_check(St0#lint.behaviour, St0). 968 969%% behaviour_check([{Line,Behaviour}], State) -> State' 970%% Check behaviours for existence and defined functions. 971 972behaviour_check(Bs, St0) -> 973 {AllBfs0, St1} = all_behaviour_callbacks(Bs, [], St0), 974 St = behaviour_missing_callbacks(AllBfs0, St1), 975 Exports = exports(St0), 976 F = fun(Bfs, OBfs) -> 977 [B || B <- Bfs, 978 not lists:member(B, OBfs) 979 orelse gb_sets:is_member(B, Exports)] 980 end, 981 %% After fixing missing callbacks new warnings may be emitted. 982 AllBfs = [{Item,F(Bfs0, OBfs0)} || {Item,Bfs0,OBfs0} <- AllBfs0], 983 behaviour_conflicting(AllBfs, St). 984 985all_behaviour_callbacks([{Line,B}|Bs], Acc, St0) -> 986 {Bfs0,OBfs0,St} = behaviour_callbacks(Line, B, St0), 987 all_behaviour_callbacks(Bs, [{{Line,B},Bfs0,OBfs0}|Acc], St); 988all_behaviour_callbacks([], Acc, St) -> {reverse(Acc),St}. 989 990behaviour_callbacks(Line, B, St0) -> 991 try B:behaviour_info(callbacks) of 992 undefined -> 993 St1 = add_warning(Line, {undefined_behaviour_callbacks, B}, St0), 994 {[], [], St1}; 995 Funcs -> 996 case is_fa_list(Funcs) of 997 true -> 998 try B:behaviour_info(optional_callbacks) of 999 undefined -> 1000 {Funcs, [], St0}; 1001 OptFuncs -> 1002 %% OptFuncs should always be OK thanks to 1003 %% sys_pre_expand. 1004 case is_fa_list(OptFuncs) of 1005 true -> 1006 {Funcs, OptFuncs, St0}; 1007 false -> 1008 W = {ill_defined_optional_callbacks, B}, 1009 St1 = add_warning(Line, W, St0), 1010 {Funcs, [], St1} 1011 end 1012 catch 1013 _:_ -> 1014 {Funcs, [], St0} 1015 end; 1016 false -> 1017 St1 = add_warning(Line, 1018 {ill_defined_behaviour_callbacks, B}, 1019 St0), 1020 {[], [], St1} 1021 end 1022 catch 1023 _:_ -> 1024 St1 = add_warning(Line, {undefined_behaviour, B}, St0), 1025 St2 = check_module_name(B, Line, St1), 1026 {[], [], St2} 1027 end. 1028 1029behaviour_missing_callbacks([{{Line,B},Bfs0,OBfs}|T], St0) -> 1030 Bfs = ordsets:subtract(ordsets:from_list(Bfs0), ordsets:from_list(OBfs)), 1031 Exports = gb_sets:to_list(exports(St0)), 1032 Missing = ordsets:subtract(Bfs, Exports), 1033 St = foldl(fun (F, S0) -> 1034 case is_fa(F) of 1035 true -> 1036 M = {undefined_behaviour_func,F,B}, 1037 add_warning(Line, M, S0); 1038 false -> 1039 S0 % ill_defined_behaviour_callbacks 1040 end 1041 end, St0, Missing), 1042 behaviour_missing_callbacks(T, St); 1043behaviour_missing_callbacks([], St) -> St. 1044 1045behaviour_conflicting(AllBfs, St) -> 1046 R0 = sofs:relation(AllBfs, [{item,[callback]}]), 1047 R1 = sofs:family_to_relation(R0), 1048 R2 = sofs:converse(R1), 1049 R3 = sofs:relation_to_family(R2), 1050 R4 = sofs:family_specification(fun(S) -> sofs:no_elements(S) > 1 end, R3), 1051 R = sofs:to_external(R4), 1052 behaviour_add_conflicts(R, St). 1053 1054behaviour_add_conflicts([{Cb,[{FirstLoc,FirstB}|Cs]}|T], St0) -> 1055 FirstL = element(2, loc(FirstLoc, St0)), 1056 St = behaviour_add_conflict(Cs, Cb, FirstL, FirstB, St0), 1057 behaviour_add_conflicts(T, St); 1058behaviour_add_conflicts([], St) -> St. 1059 1060behaviour_add_conflict([{Line,B}|Cs], Cb, FirstL, FirstB, St0) -> 1061 St = add_warning(Line, {conflicting_behaviours,Cb,B,FirstL,FirstB}, St0), 1062 behaviour_add_conflict(Cs, Cb, FirstL, FirstB, St); 1063behaviour_add_conflict([], _, _, _, St) -> St. 1064 1065%% check_deprecated(Forms, State0) -> State 1066 1067check_deprecated(Forms, St0) -> 1068 %% Get the correct list of exported functions. 1069 Exports = case member(export_all, St0#lint.compile) of 1070 true -> St0#lint.defined; 1071 false -> St0#lint.exports 1072 end, 1073 X = ignore_predefined_funcs(gb_sets:to_list(Exports)), 1074 #lint{module = Mod} = St0, 1075 Bad = [{E,L} || {attribute, L, deprecated, Depr} <- Forms, 1076 D <- lists:flatten([Depr]), 1077 E <- depr_cat(D, X, Mod)], 1078 foldl(fun ({E,L}, St1) -> 1079 add_error(L, E, St1) 1080 end, St0, Bad). 1081 1082depr_cat({F, A, Flg}=D, X, Mod) -> 1083 case deprecated_flag(Flg) of 1084 false -> [{invalid_deprecated,D}]; 1085 true -> depr_fa(F, A, X, Mod) 1086 end; 1087depr_cat({F, A}, X, Mod) -> 1088 depr_fa(F, A, X, Mod); 1089depr_cat(module, _X, _Mod) -> 1090 []; 1091depr_cat(D, _X, _Mod) -> 1092 [{invalid_deprecated,D}]. 1093 1094depr_fa('_', '_', _X, _Mod) -> 1095 []; 1096depr_fa(F, '_', X, _Mod) when is_atom(F) -> 1097 %% Don't use this syntax for built-in functions. 1098 case lists:filter(fun({F1,_}) -> F1 =:= F end, X) of 1099 [] -> [{bad_deprecated,{F,'_'}}]; 1100 _ -> [] 1101 end; 1102depr_fa(F, A, X, Mod) when is_atom(F), is_integer(A), A >= 0 -> 1103 case lists:member({F,A}, X) of 1104 true -> []; 1105 false -> 1106 case erlang:is_builtin(Mod, F, A) of 1107 true -> []; 1108 false -> [{bad_deprecated,{F,A}}] 1109 end 1110 end; 1111depr_fa(F, A, _X, _Mod) -> 1112 [{invalid_deprecated,{F,A}}]. 1113 1114deprecated_flag(next_version) -> true; 1115deprecated_flag(next_major_release) -> true; 1116deprecated_flag(eventually) -> true; 1117deprecated_flag(String) -> deprecated_desc(String). 1118 1119deprecated_desc([Char | Str]) when is_integer(Char) -> deprecated_desc(Str); 1120deprecated_desc([]) -> true; 1121deprecated_desc(_) -> false. 1122 1123%% check_removed(Forms, State0) -> State 1124 1125check_removed(Forms, St0) -> 1126 %% Get the correct list of exported functions. 1127 Exports = case member(export_all, St0#lint.compile) of 1128 true -> St0#lint.defined; 1129 false -> St0#lint.exports 1130 end, 1131 X = ignore_predefined_funcs(gb_sets:to_list(Exports)), 1132 #lint{module = Mod} = St0, 1133 Bad = [{E,L} || {attribute, L, removed, Removed} <- Forms, 1134 R <- lists:flatten([Removed]), 1135 E <- removed_cat(R, X, Mod)], 1136 foldl(fun ({E,L}, St1) -> 1137 add_error(L, E, St1) 1138 end, St0, Bad). 1139 1140removed_cat({F, A, Desc}=R, X, Mod) -> 1141 case removed_desc(Desc) of 1142 false -> [{invalid_removed,R}]; 1143 true -> removed_fa(F, A, X, Mod) 1144 end; 1145removed_cat({F, A}, X, Mod) -> 1146 removed_fa(F, A, X, Mod); 1147removed_cat(module, X, Mod) -> 1148 removed_fa('_', '_', X, Mod); 1149removed_cat(R, _X, _Mod) -> 1150 [{invalid_removed,R}]. 1151 1152removed_fa('_', '_', X, _Mod) -> 1153 case X of 1154 [_|_] -> [{bad_removed,{'_','_'}}]; 1155 [] -> [] 1156 end; 1157removed_fa(F, '_', X, _Mod) when is_atom(F) -> 1158 %% Don't use this syntax for built-in functions. 1159 case lists:filter(fun({F1,_}) -> F1 =:= F end, X) of 1160 [_|_] -> [{bad_removed,{F,'_'}}]; 1161 _ -> [] 1162 end; 1163removed_fa(F, A, X, Mod) when is_atom(F), is_integer(A), A >= 0 -> 1164 case lists:member({F,A}, X) of 1165 true -> 1166 [{bad_removed,{F,A}}]; 1167 false -> 1168 case erlang:is_builtin(Mod, F, A) of 1169 true -> [{bad_removed,{F,A}}]; 1170 false -> [] 1171 end 1172 end; 1173removed_fa(F, A, _X, _Mod) -> 1174 [{invalid_removed,{F,A}}]. 1175 1176removed_desc([Char | Str]) when is_integer(Char) -> removed_desc(Str); 1177removed_desc([]) -> true; 1178removed_desc(_) -> false. 1179 1180%% Ignores functions added by erl_internal:add_predefined_functions/1 1181ignore_predefined_funcs([{behaviour_info,1} | Fs]) -> 1182 ignore_predefined_funcs(Fs); 1183ignore_predefined_funcs([{module_info,0} | Fs]) -> 1184 ignore_predefined_funcs(Fs); 1185ignore_predefined_funcs([{module_info,1} | Fs]) -> 1186 ignore_predefined_funcs(Fs); 1187ignore_predefined_funcs([Other | Fs]) -> 1188 [Other | ignore_predefined_funcs(Fs)]; 1189ignore_predefined_funcs([]) -> 1190 []. 1191 1192%% check_imports(Forms, State0) -> State 1193 1194check_imports(Forms, St0) -> 1195 case is_warn_enabled(unused_import, St0) of 1196 false -> 1197 St0; 1198 true -> 1199 Usage = St0#lint.usage, 1200 Unused = ordsets:subtract(St0#lint.imports, Usage#usage.imported), 1201 Imports = [{{FA,Mod},L} || 1202 {attribute,L,import,{Mod,Fs}} <- Forms, 1203 FA <- lists:usort(Fs)], 1204 Bad = [{FM,L} || FM <- Unused, {FM2,L} <- Imports, FM =:= FM2], 1205 func_line_warning(unused_import, Bad, St0) 1206 end. 1207 1208%% check_inlines(Forms, State0) -> State 1209 1210check_inlines(Forms, St0) -> 1211 check_option_functions(Forms, inline, bad_inline, St0). 1212 1213%% check_unused_functions(Forms, State0) -> State 1214 1215check_unused_functions(Forms, St0) -> 1216 St1 = check_option_functions(Forms, nowarn_unused_function, 1217 bad_nowarn_unused_function, St0), 1218 Opts = St1#lint.compile, 1219 case member(export_all, Opts) orelse 1220 not is_warn_enabled(unused_function, St1) of 1221 true -> 1222 St1; 1223 false -> 1224 Nowarn = nowarn_function(nowarn_unused_function, Opts), 1225 Usage = St1#lint.usage, 1226 Used = reached_functions(initially_reached(St1), 1227 Usage#usage.calls), 1228 UsedOrNowarn = ordsets:union(Used, Nowarn), 1229 Unused = ordsets:subtract(gb_sets:to_list(St1#lint.defined), 1230 UsedOrNowarn), 1231 Functions = [{{N,A},L} || {function,L,N,A,_} <- Forms], 1232 Bad = [{FA,L} || FA <- Unused, {FA2,L} <- Functions, FA =:= FA2], 1233 func_line_warning(unused_function, Bad, St1) 1234 end. 1235 1236initially_reached(#lint{exports=Exp,on_load=OnLoad}) -> 1237 OnLoad ++ gb_sets:to_list(Exp). 1238 1239%% reached_functions(RootSet, CallRef) -> [ReachedFunc]. 1240%% reached_functions(RootSet, CallRef, [ReachedFunc]) -> [ReachedFunc]. 1241 1242reached_functions(Root, Ref) -> 1243 reached_functions(Root, [], Ref, gb_sets:empty()). 1244 1245reached_functions([R|Rs], More0, Ref, Reached0) -> 1246 case gb_sets:is_element(R, Reached0) of 1247 true -> reached_functions(Rs, More0, Ref, Reached0); 1248 false -> 1249 Reached = gb_sets:add_element(R, Reached0), %It IS reached 1250 case maps:find(R, Ref) of 1251 {ok,More} -> reached_functions(Rs, [More|More0], Ref, Reached); 1252 error -> reached_functions(Rs, More0, Ref, Reached) 1253 end 1254 end; 1255reached_functions([], [_|_]=More, Ref, Reached) -> 1256 reached_functions(lists:append(More), [], Ref, Reached); 1257reached_functions([], [], _Ref, Reached) -> gb_sets:to_list(Reached). 1258 1259%% check_undefined_functions(State0) -> State 1260 1261check_undefined_functions(#lint{called=Called0,defined=Def0}=St0) -> 1262 Called = sofs:relation(Called0, [{func,location}]), 1263 Def = sofs:from_external(gb_sets:to_list(Def0), [func]), 1264 Undef = sofs:to_external(sofs:drestriction(Called, Def)), 1265 foldl(fun ({NA,L}, St) -> 1266 add_error(L, {undefined_function,NA}, St) 1267 end, St0, Undef). 1268 1269%% check_undefined_types(State0) -> State 1270 1271check_undefined_types(#lint{usage=Usage,types=Def}=St0) -> 1272 Used = Usage#usage.used_types, 1273 UTAs = maps:keys(Used), 1274 Undef = [{TA,map_get(TA, Used)} || 1275 TA <- UTAs, 1276 not is_map_key(TA, Def), 1277 not is_default_type(TA)], 1278 foldl(fun ({TA,L}, St) -> 1279 add_error(L, {undefined_type,TA}, St) 1280 end, St0, Undef). 1281 1282%% check_bif_clashes(Forms, State0) -> State 1283 1284check_bif_clashes(Forms, St0) -> 1285 %% St0#lint.defined is now complete. 1286 check_option_functions(Forms, nowarn_bif_clash, 1287 bad_nowarn_bif_clash, St0). 1288 1289check_option_functions(Forms, Tag0, Type, St0) -> 1290 %% There are no line numbers in St0#lint.compile. 1291 FAsL = [{FA,L} || {attribute, L, compile, Args} <- Forms, 1292 {Tag, FAs0} <- lists:flatten([Args]), 1293 Tag0 =:= Tag, 1294 FA <- lists:flatten([FAs0])], 1295 DefFunctions = (gb_sets:to_list(St0#lint.defined) -- pseudolocals()) ++ 1296 [{F,A} || {{F,A},_} <- orddict:to_list(St0#lint.imports)], 1297 Bad = [{FA,L} || {FA,L} <- FAsL, not member(FA, DefFunctions)], 1298 func_line_error(Type, Bad, St0). 1299 1300nowarn_function(Tag, Opts) -> 1301 ordsets:from_list([FA || {Tag1,FAs} <- Opts, 1302 Tag1 =:= Tag, 1303 FA <- lists:flatten([FAs])]). 1304 1305func_line_warning(Type, Fs, St) -> 1306 foldl(fun ({F,Line}, St0) -> add_warning(Line, {Type,F}, St0) end, St, Fs). 1307 1308func_line_error(Type, Fs, St) -> 1309 foldl(fun ({F,Line}, St0) -> add_error(Line, {Type,F}, St0) end, St, Fs). 1310 1311check_untyped_records(Forms, St0) -> 1312 case is_warn_enabled(untyped_record, St0) of 1313 true -> 1314 %% Use the names of all records *defined* in the module (not used) 1315 RecNames = maps:keys(St0#lint.records), 1316 %% these are the records with field(s) containing type info 1317 TRecNames = [Name || 1318 {attribute,_,record,{Name,Fields}} <- Forms, 1319 lists:all(fun ({typed_record_field,_,_}) -> true; 1320 (_) -> false 1321 end, Fields)], 1322 foldl(fun (N, St) -> 1323 {L, Fields} = map_get(N, St0#lint.records), 1324 case Fields of 1325 [] -> St; % exclude records with no fields 1326 [_|_] -> add_warning(L, {untyped_record, N}, St) 1327 end 1328 end, St0, ordsets:subtract(ordsets:from_list(RecNames), 1329 ordsets:from_list(TRecNames))); 1330 false -> 1331 St0 1332 end. 1333 1334check_unused_records(Forms, St0) -> 1335 AttrFiles = [File || {attribute,_L,file,{File,_Line}} <- Forms], 1336 case {is_warn_enabled(unused_record, St0),AttrFiles} of 1337 {true,[FirstFile|_]} -> 1338 %% The check is a bit imprecise in that uses from unused 1339 %% functions count. 1340 Usage = St0#lint.usage, 1341 UsedRecords = Usage#usage.used_records, 1342 URecs = gb_sets:fold(fun (Used, Recs) -> 1343 maps:remove(Used, Recs) 1344 end, St0#lint.records, UsedRecords), 1345 Unused = [{Name,FileLine} || 1346 {Name,{FileLine,_Fields}} <- maps:to_list(URecs), 1347 element(1, loc(FileLine, St0)) =:= FirstFile], 1348 foldl(fun ({N,L}, St) -> 1349 add_warning(L, {unused_record, N}, St) 1350 end, St0, Unused); 1351 _ -> 1352 St0 1353 end. 1354 1355check_callback_information(#lint{callbacks = Callbacks, 1356 optional_callbacks = OptionalCbs, 1357 defined = Defined} = St0) -> 1358 OptFun = fun(MFA, Line, St) -> 1359 case is_map_key(MFA, Callbacks) of 1360 true -> 1361 St; 1362 false -> 1363 add_error(Line, {undefined_callback, MFA}, St) 1364 end 1365 end, 1366 St1 = maps:fold(OptFun, St0, OptionalCbs), 1367 case gb_sets:is_member({behaviour_info, 1}, Defined) of 1368 false -> St1; 1369 true -> 1370 case map_size(Callbacks) of 1371 0 -> St1; 1372 _ -> 1373 FoldFun = 1374 fun(Fa, Line, St) -> 1375 add_error(Line, {behaviour_info, Fa}, St) 1376 end, 1377 maps:fold(FoldFun, St1, Callbacks) 1378 end 1379 end. 1380 1381%% For storing the import list we use the orddict module. 1382%% We know an empty set is []. 1383 1384-spec export(line(), [fa()], lint_state()) -> lint_state(). 1385%% Mark functions as exported, also as called from the export line. 1386 1387export(Line, Es, #lint{exports = Es0, called = Called} = St0) -> 1388 {Es1,C1,St1} = 1389 foldl(fun (NA, {E,C,St2}) -> 1390 St = case gb_sets:is_element(NA, E) of 1391 true -> 1392 Warn = {duplicated_export,NA}, 1393 add_warning(Line, Warn, St2); 1394 false -> 1395 St2 1396 end, 1397 {gb_sets:add_element(NA, E), [{NA,Line}|C], St} 1398 end, 1399 {Es0,Called,St0}, Es), 1400 St1#lint{exports = Es1, called = C1}. 1401 1402-spec export_type(line(), [ta()], lint_state()) -> lint_state(). 1403%% Mark types as exported; also mark them as used from the export line. 1404 1405export_type(Line, ETs, #lint{usage = Usage, exp_types = ETs0} = St0) -> 1406 UTs0 = Usage#usage.used_types, 1407 try foldl(fun ({T,A}=TA, {E,U,St2}) when is_atom(T), is_integer(A) -> 1408 St = case gb_sets:is_element(TA, E) of 1409 true -> 1410 Warn = {duplicated_export_type,TA}, 1411 add_warning(Line, Warn, St2); 1412 false -> 1413 St2 1414 end, 1415 {gb_sets:add_element(TA, E), maps:put(TA, Line, U), St} 1416 end, 1417 {ETs0,UTs0,St0}, ETs) of 1418 {ETs1,UTs1,St1} -> 1419 St1#lint{usage = Usage#usage{used_types = UTs1}, exp_types = ETs1} 1420 catch 1421 error:_ -> 1422 add_error(Line, {bad_export_type, ETs}, St0) 1423 end. 1424 1425-spec exports(lint_state()) -> gb_sets:set(fa()). 1426 1427exports(#lint{compile = Opts, defined = Defs, exports = Es}) -> 1428 case lists:member(export_all, Opts) of 1429 true -> Defs; 1430 false -> Es 1431 end. 1432 1433-type import() :: {module(), [fa()]} | module(). 1434-spec import(line(), import(), lint_state()) -> lint_state(). 1435 1436import(Line, {Mod,Fs}, St00) -> 1437 St = check_module_name(Mod, Line, St00), 1438 Mfs = ordsets:from_list(Fs), 1439 case check_imports(Line, Mfs, St#lint.imports) of 1440 [] -> 1441 St#lint{imports=add_imports(Mod, Mfs, 1442 St#lint.imports)}; 1443 Efs -> 1444 {Err, St1} = 1445 foldl(fun ({bif,{F,A},_}, {Err,St0}) -> 1446 %% BifClash - import directive 1447 Warn = is_warn_enabled(bif_clash, St0) andalso 1448 (not bif_clash_specifically_disabled(St0,{F,A})), 1449 AutoImpSup = is_autoimport_suppressed(St0#lint.no_auto,{F,A}), 1450 OldBif = erl_internal:old_bif(F,A), 1451 {Err,if 1452 Warn and (not AutoImpSup) and OldBif -> 1453 add_error 1454 (Line, 1455 {redefine_old_bif_import, {F,A}}, 1456 St0); 1457 Warn and (not AutoImpSup) -> 1458 add_warning 1459 (Line, 1460 {redefine_bif_import, {F,A}}, 1461 St0); 1462 true -> 1463 St0 1464 end}; 1465 (Ef, {_Err,St0}) -> 1466 {true,add_error(Line, 1467 {redefine_import,Ef}, 1468 St0)} 1469 end, 1470 {false,St}, Efs), 1471 if 1472 not Err -> 1473 St1#lint{imports=add_imports(Mod, Mfs, 1474 St#lint.imports)}; 1475 true -> 1476 St1 1477 end 1478 end. 1479 1480check_imports(_Line, Fs, Is) -> 1481 foldl(fun (F, Efs) -> 1482 case orddict:find(F, Is) of 1483 {ok,Mod} -> [{F,Mod}|Efs]; 1484 error -> 1485 {N,A} = F, 1486 case erl_internal:bif(N, A) of 1487 true -> 1488 [{bif,F,erlang}|Efs]; 1489 false -> 1490 Efs 1491 end 1492 end end, [], Fs). 1493 1494add_imports(Mod, Fs, Is) -> 1495 foldl(fun (F, Is0) -> orddict:store(F, Mod, Is0) end, Is, Fs). 1496 1497-spec imported(atom(), arity(), lint_state()) -> {'yes',module()} | 'no'. 1498 1499imported(F, A, St) -> 1500 case orddict:find({F,A}, St#lint.imports) of 1501 {ok,Mod} -> {yes,Mod}; 1502 error -> no 1503 end. 1504 1505-spec on_load(erl_anno:anno(), fa(), lint_state()) -> lint_state(). 1506%% Check an on_load directive and remember it. 1507 1508on_load(Line, {Name,Arity}=Fa, #lint{on_load=OnLoad0}=St0) 1509 when is_atom(Name), is_integer(Arity) -> 1510 %% Always add the function name (even if there is a problem), 1511 %% to avoid irrelevant warnings for unused functions. 1512 St = St0#lint{on_load=[Fa|OnLoad0],on_load_line=Line}, 1513 case St of 1514 #lint{on_load=[{_,0}]} -> 1515 %% This is the first on_load attribute seen in the module 1516 %% and it has the correct arity. 1517 St; 1518 #lint{on_load=[{_,_}]} -> 1519 %% Wrong arity. 1520 add_error(Line, {bad_on_load_arity,Fa}, St); 1521 #lint{on_load=[_,_|_]} -> 1522 %% Multiple on_load attributes. 1523 add_error(Line, multiple_on_loads, St) 1524 end; 1525on_load(Line, Val, St) -> 1526 %% Bad syntax. 1527 add_error(Line, {bad_on_load,Val}, St). 1528 1529check_on_load(#lint{defined=Defined,on_load=[{_,0}=Fa], 1530 on_load_line=Line}=St) -> 1531 case gb_sets:is_member(Fa, Defined) of 1532 true -> St; 1533 false -> add_error(Line, {undefined_on_load,Fa}, St) 1534 end; 1535check_on_load(St) -> St. 1536 1537-spec call_function(line(), atom(), arity(), lint_state()) -> lint_state(). 1538%% Add to both called and calls. 1539 1540call_function(Line, F, A, #lint{usage=Usage0,called=Cd,func=Func,file=File}=St) -> 1541 #usage{calls = Cs} = Usage0, 1542 NA = {F,A}, 1543 Usage = case Cs of 1544 undefined -> Usage0; 1545 _ -> Usage0#usage{calls=maps_prepend(Func, NA, Cs)} 1546 end, 1547 Anno = erl_anno:set_file(File, Line), 1548 St#lint{called=[{NA,Anno}|Cd], usage=Usage}. 1549 1550%% function(Line, Name, Arity, Clauses, State) -> State. 1551 1552function(Line, Name, Arity, Cs, St0) -> 1553 St1 = St0#lint{func={Name,Arity}}, 1554 St2 = define_function(Line, Name, Arity, St1), 1555 clauses(Cs, St2). 1556 1557-spec define_function(line(), atom(), arity(), lint_state()) -> lint_state(). 1558 1559define_function(Line, Name, Arity, St0) -> 1560 St1 = keyword_warning(Line, Name, St0), 1561 NA = {Name,Arity}, 1562 case gb_sets:is_member(NA, St1#lint.defined) of 1563 true -> 1564 add_error(Line, {redefine_function,NA}, St1); 1565 false -> 1566 St2 = function_check_max_args(Line, Arity, St1), 1567 St3 = St2#lint{defined=gb_sets:add_element(NA, St2#lint.defined)}, 1568 case imported(Name, Arity, St3) of 1569 {yes,_M} -> add_error(Line, {define_import,NA}, St3); 1570 no -> St3 1571 end 1572 end. 1573 1574function_check_max_args(Line, Arity, St) when Arity > ?MAX_ARGUMENTS -> 1575 add_error(Line, {too_many_arguments,Arity}, St); 1576function_check_max_args(_, _, St) -> St. 1577 1578%% clauses([Clause], State) -> {VarTable, State}. 1579 1580clauses(Cs, St) -> 1581 foldl(fun (C, St0) -> 1582 {_,St1} = clause(C, St0), 1583 St1 1584 end, St, Cs). 1585 1586clause({clause,_Line,H,G,B}, St0) -> 1587 Vt0 = [], 1588 {Hvt,Binvt,St1} = head(H, Vt0, St0), 1589 %% Cannot ignore BinVt since "binsize variables" may have been used. 1590 Vt1 = vtupdate(Hvt, vtupdate(Binvt, Vt0)), 1591 {Gvt,St2} = guard(G, Vt1, St1), 1592 Vt2 = vtupdate(Gvt, Vt1), 1593 {Bvt,St3} = exprs(B, Vt2, St2), 1594 Upd = vtupdate(Bvt, Vt2), 1595 check_unused_vars(Upd, Vt0, St3). 1596 1597%% head([HeadPattern], VarTable, State) -> 1598%% {VarTable,BinVarTable,State} 1599%% Check a patterns in head returning "all" variables. Not updating the 1600%% known variable list will result in multiple error messages/warnings. 1601 1602head(Ps, Vt, St0) -> 1603 head(Ps, Vt, Vt, St0). % Old = Vt 1604 1605head([P|Ps], Vt, Old, St0) -> 1606 {Pvt,Bvt1,St1} = pattern(P, Vt, Old, [], St0), 1607 {Psvt,Bvt2,St2} = head(Ps, Vt, Old, St1), 1608 {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Bvt1,Bvt2),St2}; 1609head([], _Vt, _Env, St) -> {[],[],St}. 1610 1611%% pattern(Pattern, VarTable, Old, BinVarTable, State) -> 1612%% {UpdVarTable,BinVarTable,State}. 1613%% Check pattern return variables. Old is the set of variables used for 1614%% deciding whether an occurrence is a binding occurrence or a use, and 1615%% VarTable is the set of variables used for arguments to binary 1616%% patterns. UpdVarTable is updated when same variable in VarTable is 1617%% used in the size part of a bit segment. All other information about 1618%% used variables are recorded in BinVarTable. The caller can then decide 1619%% what to do with it depending on whether variables in the pattern shadow 1620%% variabler or not. This separation is one way of dealing with these: 1621%% A = 4, fun(<<A:A>>) -> % A #2 unused 1622%% A = 4, fun(<<A:8,16:A>>) -> % A #1 unused 1623 1624pattern(P, Vt, St) -> 1625 pattern(P, Vt, Vt, [], St). % Old = Vt 1626 1627pattern({var,_Line,'_'}, _Vt, _Old, _Bvt, St) -> 1628 {[],[],St}; %Ignore anonymous variable 1629pattern({var,Line,V}, _Vt, Old, Bvt, St) -> 1630 pat_var(V, Line, Old, Bvt, St); 1631pattern({char,_Line,_C}, _Vt, _Old, _Bvt, St) -> {[],[],St}; 1632pattern({integer,_Line,_I}, _Vt, _Old, _Bvt, St) -> {[],[],St}; 1633pattern({float,_Line,_F}, _Vt, _Old, _Bvt, St) -> {[],[],St}; 1634pattern({atom,Line,A}, _Vt, _Old, _Bvt, St) -> 1635 {[],[],keyword_warning(Line, A, St)}; 1636pattern({string,_Line,_S}, _Vt, _Old, _Bvt, St) -> {[],[],St}; 1637pattern({nil,_Line}, _Vt, _Old, _Bvt, St) -> {[],[],St}; 1638pattern({cons,_Line,H,T}, Vt, Old, Bvt, St0) -> 1639 {Hvt,Bvt1,St1} = pattern(H, Vt, Old, Bvt, St0), 1640 {Tvt,Bvt2,St2} = pattern(T, Vt, Old, Bvt, St1), 1641 {vtmerge_pat(Hvt, Tvt),vtmerge_pat(Bvt1,Bvt2),St2}; 1642pattern({tuple,_Line,Ps}, Vt, Old, Bvt, St) -> 1643 pattern_list(Ps, Vt, Old, Bvt, St); 1644pattern({map,_Line,Ps}, Vt, Old, Bvt, St) -> 1645 pattern_map(Ps, Vt, Old, Bvt, St); 1646pattern({record_index,Line,Name,Field}, _Vt, _Old, _Bvt, St) -> 1647 {Vt1,St1} = 1648 check_record(Line, Name, St, 1649 fun (Dfs, St1) -> 1650 pattern_field(Field, Name, Dfs, St1) 1651 end), 1652 {Vt1,[],St1}; 1653pattern({record,Line,Name,Pfs}, Vt, Old, Bvt, St) -> 1654 case maps:find(Name, St#lint.records) of 1655 {ok,{_Line,Fields}} -> 1656 St1 = used_record(Name, St), 1657 St2 = check_multi_field_init(Pfs, Line, Fields, St1), 1658 pattern_fields(Pfs, Name, Fields, Vt, Old, Bvt, St2); 1659 error -> {[],[],add_error(Line, {undefined_record,Name}, St)} 1660 end; 1661pattern({bin,_,Fs}, Vt, Old, Bvt, St) -> 1662 pattern_bin(Fs, Vt, Old, Bvt, St); 1663pattern({op,_Line,'++',{nil,_},R}, Vt, Old, Bvt, St) -> 1664 pattern(R, Vt, Old, Bvt, St); 1665pattern({op,_Line,'++',{cons,Li,{char,_L2,_C},T},R}, Vt, Old, Bvt, St) -> 1666 pattern({op,Li,'++',T,R}, Vt, Old, Bvt, St); %Char unimportant here 1667pattern({op,_Line,'++',{cons,Li,{integer,_L2,_I},T},R}, Vt, Old, Bvt, St) -> 1668 pattern({op,Li,'++',T,R}, Vt, Old, Bvt, St); %Weird, but compatible! 1669pattern({op,_Line,'++',{string,_Li,_S},R}, Vt, Old, Bvt, St) -> 1670 pattern(R, Vt, Old, Bvt, St); %String unimportant here 1671pattern({match,_Line,Pat1,Pat2}, Vt, Old, Bvt, St0) -> 1672 {Lvt,Bvt1,St1} = pattern(Pat1, Vt, Old, Bvt, St0), 1673 {Rvt,Bvt2,St2} = pattern(Pat2, Vt, Old, Bvt, St1), 1674 St3 = reject_invalid_alias(Pat1, Pat2, Vt, St2), 1675 {vtmerge_pat(Lvt, Rvt),vtmerge_pat(Bvt1,Bvt2),St3}; 1676%% Catch legal constant expressions, including unary +,-. 1677pattern(Pat, _Vt, _Old, _Bvt, St) -> 1678 case is_pattern_expr(Pat) of 1679 true -> {[],[],St}; 1680 false -> {[],[],add_error(element(2, Pat), illegal_pattern, St)} 1681 end. 1682 1683pattern_list(Ps, Vt, Old, Bvt0, St) -> 1684 foldl(fun (P, {Psvt,Bvt,St0}) -> 1685 {Pvt,Bvt1,St1} = pattern(P, Vt, Old, Bvt0, St0), 1686 {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Bvt,Bvt1),St1} 1687 end, {[],[],St}, Ps). 1688 1689%% Check for '_' initializing no fields. 1690check_multi_field_init(Fs, Line, Fields, St) -> 1691 case 1692 has_wildcard_field(Fs) andalso init_fields(Fs, Line, Fields) =:= [] 1693 of 1694 true -> add_error(Line, bad_multi_field_init, St); 1695 false -> St 1696 end. 1697 1698%% reject_invalid_alias(Pat, Expr, Vt, St) -> St' 1699%% Reject aliases for binary patterns at the top level. 1700%% Reject aliases for maps patterns at the top level. 1701%% The variables table (Vt) are for maps checkking. 1702 1703reject_invalid_alias_expr({bin,_,_}=P, {match,_,P0,E}, Vt, St0) -> 1704 St = reject_invalid_alias(P, P0, Vt, St0), 1705 reject_invalid_alias_expr(P, E, Vt, St); 1706reject_invalid_alias_expr({map,_,_}=P, {match,_,P0,E}, Vt, St0) -> 1707 St = reject_invalid_alias(P, P0, Vt, St0), 1708 reject_invalid_alias_expr(P, E, Vt, St); 1709reject_invalid_alias_expr({match,_,_,_}=P, {match,_,P0,E}, Vt, St0) -> 1710 St = reject_invalid_alias(P, P0, Vt, St0), 1711 reject_invalid_alias_expr(P, E, Vt, St); 1712reject_invalid_alias_expr(_, _, _, St) -> St. 1713 1714 1715 1716%% reject_invalid_alias(Pat1, Pat2, St) -> St' 1717%% Aliases of binary patterns, such as <<A:8>> = <<B:4,C:4>> or even 1718%% <<A:8>> = <<A:8>>, are not allowed. Traverse the patterns in parallel 1719%% and generate an error if any binary aliases are found. 1720%% We generate an error even if is obvious that the overall pattern can't 1721%% possibly match, for instance, {a,<<A:8>>,c}={x,<<A:8>>} WILL generate an 1722%% error. 1723%% Maps should reject unbound variables here. 1724 1725reject_invalid_alias({bin,Line,_}, {bin,_,_}, _, St) -> 1726 add_error(Line, illegal_bin_pattern, St); 1727reject_invalid_alias({map,_Line,Ps1}, {map,_,Ps2}, Vt, St0) -> 1728 Fun = fun ({map_field_exact,L,{var,_,K},_V}, Sti) -> 1729 case is_var_bound(K,Vt) of 1730 true -> 1731 Sti; 1732 false -> 1733 add_error(L, {unbound_var,K}, Sti) 1734 end; 1735 ({map_field_exact,_L,_K,_V}, Sti) -> 1736 Sti 1737 end, 1738 foldl(Fun, foldl(Fun, St0, Ps1), Ps2); 1739reject_invalid_alias({cons,_,H1,T1}, {cons,_,H2,T2}, Vt, St0) -> 1740 St = reject_invalid_alias(H1, H2, Vt, St0), 1741 reject_invalid_alias(T1, T2, Vt, St); 1742reject_invalid_alias({tuple,_,Es1}, {tuple,_,Es2}, Vt, St) -> 1743 reject_invalid_alias_list(Es1, Es2, Vt, St); 1744reject_invalid_alias({record,_,Name1,Pfs1}, {record,_,Name2,Pfs2}, Vt, 1745 #lint{records=Recs}=St) -> 1746 case Recs of 1747 #{Name1 := {_Line1,Fields1}, Name2 := {_Line2,Fields2}} -> 1748 reject_invalid_alias_rec(Pfs1, Pfs2, Fields1, Fields2, Vt, St); 1749 #{} -> 1750 %% One or more non-existing records. (An error messages has 1751 %% already been generated, so we are done here.) 1752 St 1753 end; 1754reject_invalid_alias({match,_,P1,P2}, P, Vt, St0) -> 1755 St = reject_invalid_alias(P1, P, Vt, St0), 1756 reject_invalid_alias(P2, P, Vt, St); 1757reject_invalid_alias(P, {match,_,_,_}=M, Vt, St) -> 1758 reject_invalid_alias(M, P, Vt, St); 1759reject_invalid_alias(_P1, _P2, _Vt, St) -> St. 1760 1761reject_invalid_alias_list([E1|Es1], [E2|Es2], Vt, St0) -> 1762 St = reject_invalid_alias(E1, E2, Vt, St0), 1763 reject_invalid_alias_list(Es1, Es2, Vt, St); 1764reject_invalid_alias_list(_, _, _, St) -> St. 1765 1766reject_invalid_alias_rec(PfsA0, PfsB0, FieldsA0, FieldsB0, Vt, St) -> 1767 %% We treat records as if they have been converted to tuples. 1768 PfsA1 = rbia_field_vars(PfsA0), 1769 PfsB1 = rbia_field_vars(PfsB0), 1770 FieldsA1 = rbia_fields(lists:reverse(FieldsA0), 0, []), 1771 FieldsB1 = rbia_fields(lists:reverse(FieldsB0), 0, []), 1772 FieldsA = sofs:relation(FieldsA1), 1773 PfsA = sofs:relation(PfsA1), 1774 A = sofs:join(FieldsA, 1, PfsA, 1), 1775 FieldsB = sofs:relation(FieldsB1), 1776 PfsB = sofs:relation(PfsB1), 1777 B = sofs:join(FieldsB, 1, PfsB, 1), 1778 C = sofs:join(A, 2, B, 2), 1779 D = sofs:projection({external,fun({_,_,P1,_,P2}) -> {P1,P2} end}, C), 1780 E = sofs:to_external(D), 1781 {Ps1,Ps2} = lists:unzip(E), 1782 reject_invalid_alias_list(Ps1, Ps2, Vt, St). 1783 1784rbia_field_vars(Fs) -> 1785 [{Name,Pat} || {record_field,_,{atom,_,Name},Pat} <- Fs]. 1786 1787rbia_fields([{record_field,_,{atom,_,Name},_}|Fs], I, Acc) -> 1788 rbia_fields(Fs, I+1, [{Name,I}|Acc]); 1789rbia_fields([_|Fs], I, Acc) -> 1790 rbia_fields(Fs, I+1, Acc); 1791rbia_fields([], _, Acc) -> Acc. 1792 1793%% is_pattern_expr(Expression) -> boolean(). 1794%% Test if a general expression is a valid pattern expression. 1795 1796is_pattern_expr(Expr) -> 1797 case is_pattern_expr_1(Expr) of 1798 false -> false; 1799 true -> 1800 %% Expression is syntactically correct - make sure that it 1801 %% also can be evaluated. 1802 case erl_eval:partial_eval(Expr) of 1803 {integer,_,_} -> true; 1804 {char,_,_} -> true; 1805 {float,_,_} -> true; 1806 {atom,_,_} -> true; 1807 _ -> false 1808 end 1809 end. 1810 1811is_pattern_expr_1({char,_Line,_C}) -> true; 1812is_pattern_expr_1({integer,_Line,_I}) -> true; 1813is_pattern_expr_1({float,_Line,_F}) -> true; 1814is_pattern_expr_1({atom,_Line,_A}) -> true; 1815is_pattern_expr_1({tuple,_Line,Es}) -> 1816 all(fun is_pattern_expr/1, Es); 1817is_pattern_expr_1({nil,_Line}) -> true; 1818is_pattern_expr_1({cons,_Line,H,T}) -> 1819 is_pattern_expr_1(H) andalso is_pattern_expr_1(T); 1820is_pattern_expr_1({op,_Line,Op,A}) -> 1821 erl_internal:arith_op(Op, 1) andalso is_pattern_expr_1(A); 1822is_pattern_expr_1({op,_Line,Op,A1,A2}) -> 1823 erl_internal:arith_op(Op, 2) andalso all(fun is_pattern_expr/1, [A1,A2]); 1824is_pattern_expr_1(_Other) -> false. 1825 1826pattern_map(Ps, Vt, Old, Bvt, St) -> 1827 foldl(fun({map_field_assoc,L,_,_}, {Psvt,Bvt0,St0}) -> 1828 {Psvt,Bvt0,add_error(L, illegal_pattern, St0)}; 1829 ({map_field_exact,_L,K,V}, {Psvt,Bvt0,St0}) -> 1830 St1 = St0#lint{gexpr_context=map_key}, 1831 {Kvt,St2} = gexpr(K, Vt, St1), 1832 {Vvt,Bvt2,St3} = pattern(V, Vt, Old, Bvt, St2), 1833 {vtmerge_pat(vtmerge_pat(Kvt, Vvt), Psvt), 1834 vtmerge_pat(Bvt0, Bvt2), 1835 St3} 1836 end, {[],[],St}, Ps). 1837 1838%% pattern_bin([Element], VarTable, Old, BinVarTable, State) -> 1839%% {UpdVarTable,UpdBinVarTable,State}. 1840%% Check a pattern group. BinVarTable are used binsize variables. 1841 1842pattern_bin(Es, Vt, Old, Bvt0, St0) -> 1843 {_Sz,Esvt,Bvt,St1} = foldl(fun (E, Acc) -> 1844 pattern_element(E, Vt, Old, Acc) 1845 end, 1846 {0,[],Bvt0,St0}, Es), 1847 {Esvt,Bvt,St1}. 1848 1849pattern_element({bin_element,Line,{string,_,_},Size,Ts}=Be, Vt, 1850 Old, {Sz,Esvt,Bvt,St0}=Acc) -> 1851 case good_string_size_type(Size, Ts) of 1852 true -> 1853 pattern_element_1(Be, Vt, Old, Acc); 1854 false -> 1855 St = add_error(Line, typed_literal_string, St0), 1856 {Sz,Esvt,Bvt,St} 1857 end; 1858pattern_element(Be, Vt, Old, Acc) -> 1859 pattern_element_1(Be, Vt, Old, Acc). 1860 1861pattern_element_1({bin_element,Line,E,Sz0,Ts}, Vt, Old, {Size0,Esvt,Bvt,St0}) -> 1862 {Pevt,Bvt1,St1} = pat_bit_expr(E, Old, Bvt, St0), 1863 %% vtmerge or vtmerge_pat doesn't matter here 1864 {Sz1,Szvt,Bvt2,St2} = pat_bit_size(Sz0, vtmerge(Vt, Esvt), Bvt, St1), 1865 {Sz2,Bt,St3} = bit_type(Line, Sz1, Ts, St2), 1866 {Sz3,St4} = bit_size_check(Line, Sz2, Bt, St3), 1867 Sz4 = case {E,Sz3} of 1868 {{string,_,S},all} -> 8*length(S); 1869 {_,_} -> Sz3 1870 end, 1871 {Size1,St5} = add_bit_size(Line, Sz4, Size0, false, St4), 1872 {Size1,vtmerge(Szvt,vtmerge(Pevt, Esvt)), 1873 vtmerge(Bvt2,vtmerge(Bvt, Bvt1)), St5}. 1874 1875good_string_size_type(default, default) -> 1876 true; 1877good_string_size_type(default, Ts) -> 1878 lists:any(fun(utf8) -> true; 1879 (utf16) -> true; 1880 (utf32) -> true; 1881 (_) -> false 1882 end, Ts); 1883good_string_size_type(_, _) -> false. 1884 1885%% pat_bit_expr(Pattern, OldVarTable, BinVarTable,State) -> 1886%% {UpdVarTable,UpdBinVarTable,State}. 1887%% Check pattern bit expression, only allow really valid patterns! 1888 1889pat_bit_expr({var,_,'_'}, _Old, _Bvt, St) -> {[],[],St}; 1890pat_bit_expr({var,Ln,V}, Old, Bvt, St) -> pat_var(V, Ln, Old, Bvt, St); 1891pat_bit_expr({string,_,_}, _Old, _Bvt, St) -> {[],[],St}; 1892pat_bit_expr({bin,L,_}, _Old, _Bvt, St) -> 1893 {[],[],add_error(L, illegal_pattern, St)}; 1894pat_bit_expr(P, _Old, _Bvt, St) -> 1895 case is_pattern_expr(P) of 1896 true -> {[],[],St}; 1897 false -> {[],[],add_error(element(2, P), illegal_pattern, St)} 1898 end. 1899 1900%% pat_bit_size(Size, VarTable, BinVarTable, State) -> 1901%% {Value,UpdVarTable,UpdBinVarTable,State}. 1902%% Check pattern size expression, only allow really valid sizes! 1903 1904pat_bit_size(default, _Vt, _Bvt, St) -> {default,[],[],St}; 1905pat_bit_size({var,Lv,V}, Vt0, Bvt0, St0) -> 1906 {Vt,Bvt,St1} = pat_binsize_var(V, Lv, Vt0, Bvt0, St0), 1907 {unknown,Vt,Bvt,St1}; 1908pat_bit_size(Size, Vt0, Bvt0, St0) -> 1909 Line = element(2, Size), 1910 case erl_eval:partial_eval(Size) of 1911 {integer,Line,I} -> {I,[],[],St0}; 1912 Expr -> 1913 %% The size is an expression using operators 1914 %% and/or guard BIFs calls. If the expression 1915 %% happens to evaluate to a non-integer value, the 1916 %% pattern will fail to match. 1917 St1 = St0#lint{bvt=Bvt0,gexpr_context=bin_seg_size}, 1918 {Vt,#lint{bvt=Bvt}=St2} = gexpr(Size, Vt0, St1), 1919 St3 = St2#lint{bvt=none,gexpr_context=St0#lint.gexpr_context}, 1920 St = case is_bit_size_illegal(Expr) of 1921 true -> 1922 %% The size is a non-integer literal or a simple 1923 %% expression that does not evaluate to an 1924 %% integer value. Issue a warning. 1925 add_warning(Line, non_integer_bitsize, St3); 1926 false -> St3 1927 end, 1928 {unknown,Vt,Bvt,St} 1929 end. 1930 1931is_bit_size_illegal({atom,_,_}) -> true; 1932is_bit_size_illegal({bin,_,_}) -> true; 1933is_bit_size_illegal({cons,_,_,_}) -> true; 1934is_bit_size_illegal({float,_,_}) -> true; 1935is_bit_size_illegal({map,_,_}) -> true; 1936is_bit_size_illegal({nil,_}) -> true; 1937is_bit_size_illegal({tuple,_,_}) -> true; 1938is_bit_size_illegal(_) -> false. 1939 1940%% expr_bin(Line, [Element], VarTable, State, CheckFun) -> {UpdVarTable,State}. 1941%% Check an expression group. 1942 1943expr_bin(Es, Vt, St0, Check) -> 1944 {_Sz,Esvt,St1} = foldl(fun (E, Acc) -> bin_element(E, Vt, Acc, Check) end, 1945 {0,[],St0}, Es), 1946 {Esvt,St1}. 1947 1948bin_element({bin_element,Line,E,Sz0,Ts}, Vt, {Size0,Esvt,St0}, Check) -> 1949 {Vt1,St1} = Check(E, Vt, St0), 1950 {Sz1,Vt2,St2} = bit_size(Sz0, Vt, St1, Check), 1951 {Sz2,Bt,St3} = bit_type(Line, Sz1, Ts, St2), 1952 {Sz3,St4} = bit_size_check(Line, Sz2, Bt, St3), 1953 {Size1,St5} = add_bit_size(Line, Sz3, Size0, true, St4), 1954 {Size1,vtmerge([Vt2,Vt1,Esvt]),St5}. 1955 1956bit_size(default, _Vt, St, _Check) -> {default,[],St}; 1957bit_size({atom,_Line,all}, _Vt, St, _Check) -> {all,[],St}; 1958bit_size(Size, Vt, St, Check) -> 1959 %% Try to safely evaluate Size if constant to get size, 1960 %% otherwise just treat it as an expression. 1961 Info = is_guard_test2_info(St), 1962 case is_gexpr(Size, Info) of 1963 true -> 1964 case erl_eval:partial_eval(Size) of 1965 {integer,_ILn,I} -> {I,[],St}; 1966 _Other -> 1967 {Evt,St1} = Check(Size, Vt, St), 1968 {unknown,Evt,St1} 1969 end; 1970 false -> 1971 {Evt,St1} = Check(Size, Vt, St), 1972 {unknown,Evt,St1} 1973 end. 1974 1975%% bit_type(Line, Size, TypeList, State) -> {Size,#bittype,St}. 1976%% Perform warning check on type and size. 1977 1978bit_type(Line, Size0, Type, St) -> 1979 case erl_bits:set_bit_type(Size0, Type) of 1980 {ok,Size1,Bt} -> {Size1,Bt,St}; 1981 {error,What} -> 1982 %% Flag error and generate a default. 1983 {ok,Size1,Bt} = erl_bits:set_bit_type(default, []), 1984 {Size1,Bt,add_error(Line, What, St)} 1985 end. 1986 1987%% bit_size_check(Line, Size, BitType, State) -> {BitSize,State}. 1988%% Do some checking & warnings on types 1989%% float == 32 or 64 1990 1991bit_size_check(_Line, unknown, _, St) -> {unknown,St}; 1992bit_size_check(_Line, undefined, #bittype{type=Type}, St) -> 1993 true = (Type =:= utf8) or (Type =:= utf16) or (Type =:= utf32), %Assertion. 1994 {undefined,St}; 1995bit_size_check(Line, all, #bittype{type=Type}, St) -> 1996 case Type of 1997 binary -> {all,St}; 1998 _ -> {unknown,add_error(Line, illegal_bitsize, St)} 1999 end; 2000bit_size_check(Line, Size, #bittype{type=Type,unit=Unit}, St) -> 2001 Sz = Unit * Size, %Total number of bits! 2002 St2 = elemtype_check(Line, Type, Sz, St), 2003 {Sz,St2}. 2004 2005elemtype_check(_Line, float, 32, St) -> St; 2006elemtype_check(_Line, float, 64, St) -> St; 2007elemtype_check(Line, float, _Size, St) -> 2008 add_warning(Line, {bad_bitsize,"float"}, St); 2009elemtype_check(_Line, _Type, _Size, St) -> St. 2010 2011 2012%% add_bit_size(Line, ElementSize, BinSize, Build, State) -> {Size,State}. 2013%% Add bits to group size. 2014 2015add_bit_size(Line, _Sz1, all, false, St) -> 2016 {all,add_error(Line, unsized_binary_not_at_end, St)}; 2017add_bit_size(_Line, _Sz1, all, true, St) -> 2018 {all,St}; 2019add_bit_size(_Line, all, _Sz2, _B, St) -> {all,St}; 2020add_bit_size(_Line, undefined, _Sz2, _B, St) -> {undefined,St}; 2021add_bit_size(_Line, unknown, _Sz2, _B, St) -> {unknown,St}; 2022add_bit_size(_Line, _Sz1, undefined, _B, St) -> {unknown,St}; 2023add_bit_size(_Line, _Sz1, unknown, _B, St) -> {unknown,St}; 2024add_bit_size(_Line, Sz1, Sz2, _B, St) -> {Sz1 + Sz2,St}. 2025 2026%% guard([GuardTest], VarTable, State) -> 2027%% {UsedVarTable,State} 2028%% Check a guard, return all variables. 2029 2030%% Disjunction of guard conjunctions 2031guard([L|R], Vt, St0) when is_list(L) -> 2032 {Gvt, St1} = guard_tests(L, Vt, St0), 2033 {Gsvt, St2} = guard(R, vtupdate(Gvt, Vt), St1), 2034 {vtupdate(Gvt, Gsvt),St2}; 2035guard(L, Vt, St0) -> 2036 guard_tests(L, Vt, St0). 2037 2038%% guard conjunction 2039guard_tests([G|Gs], Vt, St0) -> 2040 {Gvt,St1} = guard_test(G, Vt, St0), 2041 {Gsvt,St2} = guard_tests(Gs, vtupdate(Gvt, Vt), St1), 2042 {vtupdate(Gvt, Gsvt),St2}; 2043guard_tests([], _Vt, St) -> {[],St}. 2044 2045%% guard_test(Test, VarTable, State) -> 2046%% {UsedVarTable,State'} 2047%% Check one guard test, returns NewVariables. We now allow more 2048%% expressions in guards including the new is_XXX type tests, but 2049%% only allow the old type tests at the top level. 2050 2051guard_test(G, Vt, St0) -> 2052 St1 = obsolete_guard(G, St0), 2053 guard_test2(G, Vt, St1). 2054 2055%% Specially handle record type test here. 2056guard_test2({call,Line,{atom,Lr,record},[E,A]}, Vt, St0) -> 2057 gexpr({call,Line,{atom,Lr,is_record},[E,A]}, Vt, St0); 2058guard_test2({call,Line,{atom,_La,F},As}=G, Vt, St0) -> 2059 {Asvt,St1} = gexpr_list(As, Vt, St0), %Always check this. 2060 A = length(As), 2061 case erl_internal:type_test(F, A) of 2062 true when F =/= is_record, A =/= 2 -> 2063 case no_guard_bif_clash(St1, {F,A}) of 2064 false -> 2065 {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)}; 2066 true -> 2067 {Asvt,St1} 2068 end; 2069 _ -> 2070 gexpr(G, Vt, St0) 2071 end; 2072guard_test2(G, Vt, St) -> 2073 %% Everything else is a guard expression. 2074 gexpr(G, Vt, St). 2075 2076%% gexpr(GuardExpression, VarTable, State) -> 2077%% {UsedVarTable,State'} 2078%% Check a guard expression, returns NewVariables. 2079 2080gexpr({var,Line,V}, Vt, St) -> 2081 expr_var(V, Line, Vt, St); 2082gexpr({char,_Line,_C}, _Vt, St) -> {[],St}; 2083gexpr({integer,_Line,_I}, _Vt, St) -> {[],St}; 2084gexpr({float,_Line,_F}, _Vt, St) -> {[],St}; 2085gexpr({atom,Line,A}, _Vt, St) -> 2086 {[],keyword_warning(Line, A, St)}; 2087gexpr({string,_Line,_S}, _Vt, St) -> {[],St}; 2088gexpr({nil,_Line}, _Vt, St) -> {[],St}; 2089gexpr({cons,_Line,H,T}, Vt, St) -> 2090 gexpr_list([H,T], Vt, St); 2091gexpr({tuple,_Line,Es}, Vt, St) -> 2092 gexpr_list(Es, Vt, St); 2093gexpr({map,_Line,Es}, Vt, St) -> 2094 map_fields(Es, Vt, check_assoc_fields(Es, St), fun gexpr_list/3); 2095gexpr({map,_Line,Src,Es}, Vt, St) -> 2096 {Svt,St1} = gexpr(Src, Vt, St), 2097 {Fvt,St2} = map_fields(Es, Vt, St1, fun gexpr_list/3), 2098 {vtmerge(Svt, Fvt),St2}; 2099gexpr({record_index,Line,Name,Field}, _Vt, St) -> 2100 check_record(Line, Name, St, 2101 fun (Dfs, St1) -> record_field(Field, Name, Dfs, St1) end ); 2102gexpr({record_field,Line,Rec,Name,Field}, Vt, St0) -> 2103 {Rvt,St1} = gexpr(Rec, Vt, St0), 2104 {Fvt,St2} = check_record(Line, Name, St1, 2105 fun (Dfs, St) -> 2106 record_field(Field, Name, Dfs, St) 2107 end), 2108 {vtmerge(Rvt, Fvt),St2}; 2109gexpr({record,Line,Name,Inits}, Vt, St) -> 2110 check_record(Line, Name, St, 2111 fun (Dfs, St1) -> 2112 ginit_fields(Inits, Line, Name, Dfs, Vt, St1) 2113 end); 2114gexpr({bin,_Line,Fs}, Vt,St) -> 2115 expr_bin(Fs, Vt, St, fun gexpr/3); 2116gexpr({call,_Line,{atom,_Lr,is_record},[E,{atom,Ln,Name}]}, Vt, St0) -> 2117 {Rvt,St1} = gexpr(E, Vt, St0), 2118 {Rvt,exist_record(Ln, Name, St1)}; 2119gexpr({call,Line,{atom,_Lr,is_record},[E,R]}, Vt, St0) -> 2120 {Asvt,St1} = gexpr_list([E,R], Vt, St0), 2121 {Asvt,add_error(Line, illegal_guard_expr, St1)}; 2122gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]}, 2123 Vt, St0) -> 2124 gexpr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0); 2125gexpr({call,Line,{atom,_Lr,is_record},[E0,{atom,_,_Name},{integer,_,_}]}, 2126 Vt, St0) -> 2127 {E,St1} = gexpr(E0, Vt, St0), 2128 case no_guard_bif_clash(St0, {is_record,3}) of 2129 true -> 2130 {E,St1}; 2131 false -> 2132 {E,add_error(Line, {illegal_guard_local_call,{is_record,3}}, St1)} 2133 end; 2134gexpr({call,Line,{atom,_Lr,is_record},[_,_,_]=Asvt0}, Vt, St0) -> 2135 {Asvt,St1} = gexpr_list(Asvt0, Vt, St0), 2136 {Asvt,add_error(Line, illegal_guard_expr, St1)}; 2137gexpr({call,Line,{remote,_,{atom,_,erlang},{atom,_,is_record}=Isr},[_,_,_]=Args}, 2138 Vt, St0) -> 2139 gexpr({call,Line,Isr,Args}, Vt, St0); 2140gexpr({call,Line,{atom,_La,F},As}, Vt, St0) -> 2141 {Asvt,St1} = gexpr_list(As, Vt, St0), 2142 A = length(As), 2143 %% BifClash - Function called in guard 2144 case erl_internal:guard_bif(F, A) andalso no_guard_bif_clash(St1,{F,A}) of 2145 true -> 2146 %% Assert that it is auto-imported. 2147 true = erl_internal:bif(F, A), 2148 {Asvt,St1}; 2149 false -> 2150 case is_local_function(St1#lint.locals,{F,A}) orelse 2151 is_imported_function(St1#lint.imports,{F,A}) of 2152 true -> 2153 {Asvt,add_error(Line, {illegal_guard_local_call,{F,A}}, St1)}; 2154 _ -> 2155 {Asvt,add_error(Line, illegal_guard_expr, St1)} 2156 end 2157 end; 2158gexpr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,F}},As}, Vt, St0) -> 2159 {Asvt,St1} = gexpr_list(As, Vt, St0), 2160 A = length(As), 2161 case erl_internal:guard_bif(F, A) orelse is_gexpr_op(F, A) of 2162 true -> {Asvt,St1}; 2163 false -> {Asvt,add_error(Line, illegal_guard_expr, St1)} 2164 end; 2165gexpr({op,Line,Op,A}, Vt, St0) -> 2166 {Avt,St1} = gexpr(A, Vt, St0), 2167 case is_gexpr_op(Op, 1) of 2168 true -> {Avt,St1}; 2169 false -> {Avt,add_error(Line, illegal_guard_expr, St1)} 2170 end; 2171gexpr({op,_,'andalso',L,R}, Vt, St) -> 2172 gexpr_list([L,R], Vt, St); 2173gexpr({op,_,'orelse',L,R}, Vt, St) -> 2174 gexpr_list([L,R], Vt, St); 2175gexpr({op,Line,Op,L,R}, Vt, St0) -> 2176 {Avt,St1} = gexpr_list([L,R], Vt, St0), 2177 case is_gexpr_op(Op, 2) of 2178 true -> {Avt,St1}; 2179 false -> {Avt,add_error(Line, illegal_guard_expr, St1)} 2180 end; 2181%% Everything else is illegal! You could put explicit tests here to 2182%% better error diagnostics. 2183gexpr(E, _Vt, St) -> 2184 {[],add_error(element(2, E), illegal_guard_expr, St)}. 2185 2186%% gexpr_list(Expressions, VarTable, State) -> 2187%% {UsedVarTable,State'} 2188 2189gexpr_list(Es, Vt, St) -> 2190 foldl(fun (E, {Esvt,St0}) -> 2191 {Evt,St1} = gexpr(E, Vt, St0), 2192 {vtmerge(Evt, Esvt),St1} 2193 end, {[],St}, Es). 2194 2195%% is_guard_test(Expression) -> boolean(). 2196%% Test if a general expression is a guard test. 2197%% 2198%% Note: Only use this function in contexts where there can be 2199%% no definition of a local function that may override a guard BIF 2200%% (for example, in the shell). 2201-spec is_guard_test(Expr) -> boolean() when 2202 Expr :: erl_parse:abstract_expr(). 2203 2204is_guard_test(E) -> 2205 is_guard_test2(E, {maps:new(),fun(_) -> false end}). 2206 2207%% is_guard_test(Expression, Forms) -> boolean(). 2208is_guard_test(Expression, Forms) -> 2209 is_guard_test(Expression, Forms, fun(_) -> false end). 2210 2211 2212%% is_guard_test(Expression, Forms, IsOverridden) -> boolean(). 2213%% Test if a general expression is a guard test. 2214%% 2215%% IsOverridden({Name,Arity}) should return 'true' if Name/Arity is 2216%% a local or imported function in the module. If the abstract code has 2217%% passed through erl_expand_records, any call without an explicit 2218%% module is to a local function, so IsOverridden can be defined as: 2219%% 2220%% fun(_) -> true end 2221%% 2222-spec is_guard_test(Expr, Forms, IsOverridden) -> boolean() when 2223 Expr :: erl_parse:abstract_expr(), 2224 Forms :: [erl_parse:abstract_form() | erl_parse:form_info()], 2225 IsOverridden :: fun((fa()) -> boolean()). 2226 2227is_guard_test(Expression, Forms, IsOverridden) -> 2228 RecordAttributes = [A || A = {attribute, _, record, _D} <- Forms], 2229 St0 = foldl(fun(Attr0, St1) -> 2230 Attr = set_file(Attr0, "none"), 2231 attribute_state(Attr, St1) 2232 end, start(), RecordAttributes), 2233 is_guard_test2(set_file(Expression, "nofile"), 2234 {St0#lint.records,IsOverridden}). 2235 2236%% is_guard_test2(Expression, RecordDefs :: dict:dict()) -> boolean(). 2237is_guard_test2({call,Line,{atom,Lr,record},[E,A]}, Info) -> 2238 is_gexpr({call,Line,{atom,Lr,is_record},[E,A]}, Info); 2239is_guard_test2({call,_Line,{atom,_La,Test},As}=Call, {_,IsOverridden}=Info) -> 2240 A = length(As), 2241 not IsOverridden({Test,A}) andalso 2242 case erl_internal:type_test(Test, A) of 2243 true -> is_gexpr_list(As, Info); 2244 false -> is_gexpr(Call, Info) 2245 end; 2246is_guard_test2(G, Info) -> 2247 %%Everything else is a guard expression. 2248 is_gexpr(G, Info). 2249 2250%% is_guard_expr(Expression) -> boolean(). 2251%% Test if an expression is a guard expression. 2252 2253is_guard_expr(E) -> is_gexpr(E, {[],fun({_,_}) -> false end}). 2254 2255is_gexpr({var,_L,_V}, _Info) -> true; 2256is_gexpr({char,_L,_C}, _Info) -> true; 2257is_gexpr({integer,_L,_I}, _Info) -> true; 2258is_gexpr({float,_L,_F}, _Info) -> true; 2259is_gexpr({atom,_L,_A}, _Info) -> true; 2260is_gexpr({string,_L,_S}, _Info) -> true; 2261is_gexpr({nil,_L}, _Info) -> true; 2262is_gexpr({cons,_L,H,T}, Info) -> is_gexpr_list([H,T], Info); 2263is_gexpr({tuple,_L,Es}, Info) -> is_gexpr_list(Es, Info); 2264is_gexpr({map,_L,Es}, Info) -> 2265 is_map_fields(Es, Info); 2266is_gexpr({map,_L,Src,Es}, Info) -> 2267 is_gexpr(Src, Info) andalso is_map_fields(Es, Info); 2268is_gexpr({record_index,_L,_Name,Field}, Info) -> 2269 is_gexpr(Field, Info); 2270is_gexpr({record_field,_L,Rec,_Name,Field}, Info) -> 2271 is_gexpr_list([Rec,Field], Info); 2272is_gexpr({record,L,Name,Inits}, Info) -> 2273 is_gexpr_fields(Inits, L, Name, Info); 2274is_gexpr({bin,_L,Fs}, Info) -> 2275 all(fun ({bin_element,_Line,E,Sz,_Ts}) -> 2276 is_gexpr(E, Info) and (Sz =:= default orelse is_gexpr(Sz, Info)) 2277 end, Fs); 2278is_gexpr({call,_L,{atom,_Lf,F},As}, {_,IsOverridden}=Info) -> 2279 A = length(As), 2280 not IsOverridden({F,A}) andalso erl_internal:guard_bif(F, A) 2281 andalso is_gexpr_list(As, Info); 2282is_gexpr({call,_L,{remote,_Lr,{atom,_Lm,erlang},{atom,_Lf,F}},As}, Info) -> 2283 A = length(As), 2284 (erl_internal:guard_bif(F, A) orelse is_gexpr_op(F, A)) 2285 andalso is_gexpr_list(As, Info); 2286is_gexpr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,F}]},As}, Info) -> 2287 is_gexpr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,F}},As}, Info); 2288is_gexpr({op,_L,Op,A}, Info) -> 2289 is_gexpr_op(Op, 1) andalso is_gexpr(A, Info); 2290is_gexpr({op,_L,'andalso',A1,A2}, Info) -> 2291 is_gexpr_list([A1,A2], Info); 2292is_gexpr({op,_L,'orelse',A1,A2}, Info) -> 2293 is_gexpr_list([A1,A2], Info); 2294is_gexpr({op,_L,Op,A1,A2}, Info) -> 2295 is_gexpr_op(Op, 2) andalso is_gexpr_list([A1,A2], Info); 2296is_gexpr(_Other, _Info) -> false. 2297 2298is_gexpr_op(Op, A) -> 2299 try erl_internal:op_type(Op, A) of 2300 arith -> true; 2301 bool -> true; 2302 comp -> true; 2303 list -> false; 2304 send -> false 2305 catch _:_ -> false 2306 end. 2307 2308is_gexpr_list(Es, Info) -> all(fun (E) -> is_gexpr(E, Info) end, Es). 2309 2310is_map_fields([{Tag,_,K,V}|Fs], Info) when Tag =:= map_field_assoc; 2311 Tag =:= map_field_exact -> 2312 is_gexpr(K, Info) andalso 2313 is_gexpr(V, Info) andalso 2314 is_map_fields(Fs, Info); 2315is_map_fields([], _Info) -> true; 2316is_map_fields(_T, _Info) -> false. 2317 2318is_gexpr_fields(Fs, L, Name, {RDs,_}=Info) -> 2319 IFs = case maps:find(Name, RDs) of 2320 {ok,{_Line,Fields}} -> Fs ++ init_fields(Fs, L, Fields); 2321 error -> Fs 2322 end, 2323 all(fun ({record_field,_Lf,_Name,V}) -> is_gexpr(V, Info); 2324 (_Other) -> false end, IFs). 2325 2326%% exprs(Sequence, VarTable, State) -> 2327%% {UsedVarTable,State'} 2328%% Check a sequence of expressions, return all variables. 2329 2330exprs([E|Es], Vt, St0) -> 2331 {Evt,St1} = expr(E, Vt, St0), 2332 {Esvt,St2} = exprs(Es, vtupdate(Evt, Vt), St1), 2333 {vtupdate(Evt, Esvt),St2}; 2334exprs([], _Vt, St) -> {[],St}. 2335 2336%% expr(Expression, VarTable, State) -> 2337%% {UsedVarTable,State'} 2338%% Check an expression, returns NewVariables. Assume naive users and 2339%% mark illegally exported variables, e.g. from catch, as unsafe to better 2340%% show why unbound. 2341 2342expr({var,Line,V}, Vt, St) -> 2343 expr_var(V, Line, Vt, St); 2344expr({char,_Line,_C}, _Vt, St) -> {[],St}; 2345expr({integer,_Line,_I}, _Vt, St) -> {[],St}; 2346expr({float,_Line,_F}, _Vt, St) -> {[],St}; 2347expr({atom,Line,A}, _Vt, St) -> 2348 {[],keyword_warning(Line, A, St)}; 2349expr({string,_Line,_S}, _Vt, St) -> {[],St}; 2350expr({nil,_Line}, _Vt, St) -> {[],St}; 2351expr({cons,_Line,H,T}, Vt, St) -> 2352 expr_list([H,T], Vt, St); 2353expr({lc,_Line,E,Qs}, Vt, St) -> 2354 handle_comprehension(E, Qs, Vt, St); 2355expr({bc,_Line,E,Qs}, Vt, St) -> 2356 handle_comprehension(E, Qs, Vt, St); 2357expr({tuple,_Line,Es}, Vt, St) -> 2358 expr_list(Es, Vt, St); 2359expr({map,_Line,Es}, Vt, St) -> 2360 map_fields(Es, Vt, check_assoc_fields(Es, St), fun expr_list/3); 2361expr({map,_Line,Src,Es}, Vt, St) -> 2362 {Svt,St1} = expr(Src, Vt, St), 2363 {Fvt,St2} = map_fields(Es, Vt, St1, fun expr_list/3), 2364 {vtupdate(Svt, Fvt),St2}; 2365expr({record_index,Line,Name,Field}, _Vt, St) -> 2366 check_record(Line, Name, St, 2367 fun (Dfs, St1) -> record_field(Field, Name, Dfs, St1) end); 2368expr({record,Line,Name,Inits}, Vt, St) -> 2369 check_record(Line, Name, St, 2370 fun (Dfs, St1) -> 2371 init_fields(Inits, Line, Name, Dfs, Vt, St1) 2372 end); 2373expr({record_field,Line,Rec,Name,Field}, Vt, St0) -> 2374 {Rvt,St1} = record_expr(Line, Rec, Vt, St0), 2375 {Fvt,St2} = check_record(Line, Name, St1, 2376 fun (Dfs, St) -> 2377 record_field(Field, Name, Dfs, St) 2378 end), 2379 {vtmerge(Rvt, Fvt),St2}; 2380expr({record,Line,Rec,Name,Upds}, Vt, St0) -> 2381 {Rvt,St1} = record_expr(Line, Rec, Vt, St0), 2382 {Usvt,St2} = check_record(Line, Name, St1, 2383 fun (Dfs, St) -> 2384 update_fields(Upds, Name, Dfs, Vt, St) 2385 end ), 2386 case has_wildcard_field(Upds) of 2387 true -> {[],add_error(Line, {wildcard_in_update,Name}, St2)}; 2388 false -> {vtmerge(Rvt, Usvt),St2} 2389 end; 2390expr({bin,_Line,Fs}, Vt, St) -> 2391 expr_bin(Fs, Vt, St, fun expr/3); 2392expr({block,_Line,Es}, Vt, St) -> 2393 %% Unfold block into a sequence. 2394 exprs(Es, Vt, St); 2395expr({'if',Line,Cs}, Vt, St) -> 2396 icrt_clauses(Cs, {'if',Line}, Vt, St); 2397expr({'case',Line,E,Cs}, Vt, St0) -> 2398 {Evt,St1} = expr(E, Vt, St0), 2399 {Cvt,St2} = icrt_clauses(Cs, {'case',Line}, vtupdate(Evt, Vt), St1), 2400 {vtmerge(Evt, Cvt),St2}; 2401expr({'receive',Line,Cs}, Vt, St) -> 2402 icrt_clauses(Cs, {'receive',Line}, Vt, St); 2403expr({'receive',Line,Cs,To,ToEs}, Vt, St0) -> 2404 %% Are variables from the timeout expression visible in the clauses? NO! 2405 {Tvt,St1} = expr(To, Vt, St0), 2406 {Tevt,St2} = exprs(ToEs, Vt, St1), 2407 {Cvt,St3} = icrt_clauses(Cs, Vt, St2), 2408 %% Csvts = [vtnew(Tevt, Vt)|Cvt], %This is just NEW variables! 2409 Csvts = [Tevt|Cvt], 2410 Rvt = icrt_export(Csvts, Vt, {'receive',Line}, St3), 2411 {vtmerge([Tvt,Tevt,Rvt]),St3}; 2412expr({'fun',Line,Body}, Vt, St) -> 2413 %%No one can think funs export! 2414 case Body of 2415 {clauses,Cs} -> 2416 fun_clauses(Cs, Vt, St); 2417 {function,record_info,2} -> 2418 %% It is illegal to call record_info/2 with unknown arguments. 2419 {[],add_error(Line, illegal_record_info, St)}; 2420 {function,F,A} -> 2421 %% BifClash - Fun expression 2422 %% N.B. Only allows BIFs here as well, NO IMPORTS!! 2423 case ((not is_local_function(St#lint.locals,{F,A})) andalso 2424 (erl_internal:bif(F, A) andalso 2425 (not is_autoimport_suppressed(St#lint.no_auto,{F,A})))) of 2426 true -> {[],St}; 2427 false -> {[],call_function(Line, F, A, St)} 2428 end; 2429 {function,M,F,A} when is_atom(M), is_atom(F), is_integer(A) -> 2430 %% Compatibility with pre-R15 abstract format. 2431 {[],St}; 2432 {function,M,F,A} -> 2433 %% New in R15. 2434 expr_list([M,F,A], Vt, St) 2435 end; 2436expr({named_fun,_,'_',Cs}, Vt, St) -> 2437 fun_clauses(Cs, Vt, St); 2438expr({named_fun,Line,Name,Cs}, Vt, St0) -> 2439 Nvt0 = [{Name,{bound,unused,[Line]}}], 2440 St1 = shadow_vars(Nvt0, Vt, 'named fun', St0), 2441 Nvt1 = vtupdate(vtsubtract(Vt, Nvt0), Nvt0), 2442 {Csvt,St2} = fun_clauses(Cs, Nvt1, St1), 2443 {_,St3} = check_unused_vars(vtupdate(Csvt, Nvt0), [], St2), 2444 {vtold(Csvt, Vt),St3}; 2445expr({call,_Line,{atom,_Lr,is_record},[E,{atom,Ln,Name}]}, Vt, St0) -> 2446 {Rvt,St1} = expr(E, Vt, St0), 2447 {Rvt,exist_record(Ln, Name, St1)}; 2448expr({call,Line,{remote,_Lr,{atom,_Lm,erlang},{atom,Lf,is_record}},[E,A]}, 2449 Vt, St0) -> 2450 expr({call,Line,{atom,Lf,is_record},[E,A]}, Vt, St0); 2451expr({call,L,{tuple,Lt,[{atom,Lm,erlang},{atom,Lf,is_record}]},As}, Vt, St) -> 2452 expr({call,L,{remote,Lt,{atom,Lm,erlang},{atom,Lf,is_record}},As}, Vt, St); 2453expr({call,Line,{remote,_Lr,{atom,_Lm,M},{atom,Lf,F}},As}, Vt, St0) -> 2454 St1 = keyword_warning(Lf, F, St0), 2455 St2 = check_remote_function(Line, M, F, As, St1), 2456 St3 = check_module_name(M, Line, St2), 2457 expr_list(As, Vt, St3); 2458expr({call,Line,{remote,_Lr,M,F},As}, Vt, St0) -> 2459 St1 = keyword_warning(Line, M, St0), 2460 St2 = keyword_warning(Line, F, St1), 2461 St3 = case M of 2462 {atom,Lm,Mod} -> 2463 check_module_name(Mod, Lm, St2); 2464 _ -> 2465 St2 2466 end, 2467 expr_list([M,F|As], Vt, St3); 2468expr({call,Line,{atom,La,F},As}, Vt, St0) -> 2469 St1 = keyword_warning(La, F, St0), 2470 {Asvt,St2} = expr_list(As, Vt, St1), 2471 A = length(As), 2472 IsLocal = is_local_function(St2#lint.locals,{F,A}), 2473 IsAutoBif = erl_internal:bif(F, A), 2474 AutoSuppressed = is_autoimport_suppressed(St2#lint.no_auto,{F,A}), 2475 Warn = is_warn_enabled(bif_clash, St2) and (not bif_clash_specifically_disabled(St2,{F,A})), 2476 Imported = imported(F, A, St2), 2477 case ((not IsLocal) andalso (Imported =:= no) andalso 2478 IsAutoBif andalso (not AutoSuppressed)) of 2479 true -> 2480 St3 = deprecated_function(Line, erlang, F, As, St2), 2481 {Asvt,St3}; 2482 false -> 2483 {Asvt,case Imported of 2484 {yes,M} -> 2485 St3 = check_remote_function(Line, M, F, As, St2), 2486 U0 = St3#lint.usage, 2487 Imp = ordsets:add_element({{F,A},M},U0#usage.imported), 2488 St3#lint{usage=U0#usage{imported = Imp}}; 2489 no -> 2490 case {F,A} of 2491 {record_info,2} -> 2492 check_record_info_call(Line,La,As,St2); 2493 N -> 2494 %% BifClash - function call 2495 %% Issue these warnings/errors even if it's a recursive call 2496 St3 = if 2497 (not AutoSuppressed) andalso IsAutoBif andalso Warn -> 2498 case erl_internal:old_bif(F,A) of 2499 true -> 2500 add_error 2501 (Line, 2502 {call_to_redefined_old_bif, {F,A}}, 2503 St2); 2504 false -> 2505 add_warning 2506 (Line, 2507 {call_to_redefined_bif, {F,A}}, 2508 St2) 2509 end; 2510 true -> 2511 St2 2512 end, 2513 %% ...but don't lint recursive calls 2514 if 2515 N =:= St3#lint.func -> 2516 St3; 2517 true -> 2518 call_function(Line, F, A, St3) 2519 end 2520 end 2521 end} 2522 end; 2523expr({call,Line,F,As}, Vt, St0) -> 2524 St = warn_invalid_call(Line,F,St0), 2525 expr_list([F|As], Vt, St); %They see the same variables 2526expr({'try',Line,Es,Scs,Ccs,As}, Vt, St0) -> 2527 %% Currently, we don't allow any exports because later 2528 %% passes cannot handle exports in combination with 'after'. 2529 {Evt0,St1} = exprs(Es, Vt, St0), 2530 TryLine = {'try',Line}, 2531 Uvt = vtunsafe(TryLine, Evt0, Vt), 2532 Evt1 = vtupdate(Uvt, Evt0), 2533 {Sccs,St2} = try_clauses(Scs, Ccs, TryLine, 2534 vtupdate(Evt1, Vt), St1), 2535 Rvt0 = Sccs, 2536 Rvt1 = vtupdate(vtunsafe(TryLine, Rvt0, Vt), Rvt0), 2537 Evt2 = vtmerge(Evt1, Rvt1), 2538 {Avt0,St} = exprs(As, vtupdate(Evt2, Vt), St2), 2539 Avt1 = vtupdate(vtunsafe(TryLine, Avt0, Vt), Avt0), 2540 Avt = vtmerge(Evt2, Avt1), 2541 {Avt,St}; 2542expr({'catch',Line,E}, Vt, St0) -> 2543 %% No new variables added, flag new variables as unsafe. 2544 {Evt,St} = expr(E, Vt, St0), 2545 {vtupdate(vtunsafe({'catch',Line}, Evt, Vt), Evt),St}; 2546expr({match,_Line,P,E}, Vt, St0) -> 2547 {Evt,St1} = expr(E, Vt, St0), 2548 {Pvt,Bvt,St2} = pattern(P, vtupdate(Evt, Vt), St1), 2549 St = reject_invalid_alias_expr(P, E, Vt, St2), 2550 {vtupdate(Bvt, vtmerge(Evt, Pvt)),St}; 2551%% No comparison or boolean operators yet. 2552expr({op,_Line,_Op,A}, Vt, St) -> 2553 expr(A, Vt, St); 2554expr({op,Line,Op,L,R}, Vt, St0) when Op =:= 'orelse'; Op =:= 'andalso' -> 2555 {Evt1,St1} = expr(L, Vt, St0), 2556 Vt1 = vtupdate(Evt1, Vt), 2557 {Evt2,St2} = expr(R, Vt1, St1), 2558 Evt3 = vtupdate(vtunsafe({Op,Line}, Evt2, Vt1), Evt2), 2559 {vtmerge(Evt1, Evt3),St2}; 2560expr({op,_Line,_Op,L,R}, Vt, St) -> 2561 expr_list([L,R], Vt, St); %They see the same variables 2562%% The following are not allowed to occur anywhere! 2563expr({remote,Line,_M,_F}, _Vt, St) -> 2564 {[],add_error(Line, illegal_expr, St)}. 2565 2566%% expr_list(Expressions, Variables, State) -> 2567%% {UsedVarTable,State} 2568 2569expr_list(Es, Vt, St) -> 2570 foldl(fun (E, {Esvt,St0}) -> 2571 {Evt,St1} = expr(E, Vt, St0), 2572 {vtmerge_pat(Evt, Esvt),St1} 2573 end, {[],St}, Es). 2574 2575record_expr(Line, Rec, Vt, St0) -> 2576 St1 = warn_invalid_record(Line, Rec, St0), 2577 expr(Rec, Vt, St1). 2578 2579check_assoc_fields([{map_field_exact,Line,_,_}|Fs], St) -> 2580 check_assoc_fields(Fs, add_error(Line, illegal_map_construction, St)); 2581check_assoc_fields([{map_field_assoc,_,_,_}|Fs], St) -> 2582 check_assoc_fields(Fs, St); 2583check_assoc_fields([], St) -> 2584 St. 2585 2586map_fields([{Tag,_,K,V}|Fs], Vt, St, F) when Tag =:= map_field_assoc; 2587 Tag =:= map_field_exact -> 2588 {Pvt,St2} = F([K,V], Vt, St), 2589 {Vts,St3} = map_fields(Fs, Vt, St2, F), 2590 {vtupdate(Pvt, Vts),St3}; 2591map_fields([], _, St, _) -> 2592 {[],St}. 2593 2594%% warn_invalid_record(Line, Record, State0) -> State 2595%% Adds warning if the record is invalid. 2596 2597warn_invalid_record(Line, R, St) -> 2598 case is_valid_record(R) of 2599 true -> St; 2600 false -> add_warning(Line, invalid_record, St) 2601 end. 2602 2603%% is_valid_record(Record) -> boolean(). 2604 2605is_valid_record(Rec) -> 2606 case Rec of 2607 {char, _, _} -> false; 2608 {integer, _, _} -> false; 2609 {float, _, _} -> false; 2610 {atom, _, _} -> false; 2611 {string, _, _} -> false; 2612 {cons, _, _, _} -> false; 2613 {nil, _} -> false; 2614 {lc, _, _, _} -> false; 2615 {record_index, _, _, _} -> false; 2616 {'fun', _, _} -> false; 2617 {named_fun, _, _, _} -> false; 2618 _ -> true 2619 end. 2620 2621%% warn_invalid_call(Line, Call, State0) -> State 2622%% Adds warning if the call is invalid. 2623 2624warn_invalid_call(Line, F, St) -> 2625 case is_valid_call(F) of 2626 true -> St; 2627 false -> add_warning(Line, invalid_call, St) 2628 end. 2629 2630%% is_valid_call(Call) -> boolean(). 2631 2632is_valid_call(Call) -> 2633 case Call of 2634 {char, _, _} -> false; 2635 {integer, _, _} -> false; 2636 {float, _, _} -> false; 2637 {string, _, _} -> false; 2638 {cons, _, _, _} -> false; 2639 {nil, _} -> false; 2640 {lc, _, _, _} -> false; 2641 {record_index, _, _, _} -> false; 2642 {tuple, _, Exprs} when length(Exprs) =/= 2 -> false; 2643 _ -> true 2644 end. 2645 2646%% record_def(Line, RecordName, [RecField], State) -> State. 2647%% Add a record definition if it does not already exist. Normalise 2648%% so that all fields have explicit initial value. 2649 2650record_def(Line, Name, Fs0, St0) -> 2651 case is_map_key(Name, St0#lint.records) of 2652 true -> add_error(Line, {redefine_record,Name}, St0); 2653 false -> 2654 {Fs1,St1} = def_fields(normalise_fields(Fs0), Name, St0), 2655 St2 = St1#lint{records=maps:put(Name, {Line,Fs1}, 2656 St1#lint.records)}, 2657 Types = [T || {typed_record_field, _, T} <- Fs0], 2658 check_type({type, nowarn(), product, Types}, St2) 2659 end. 2660 2661%% def_fields([RecDef], RecordName, State) -> {[DefField],State}. 2662%% Check (normalised) fields for duplicates. Return unduplicated 2663%% record and set State. 2664 2665def_fields(Fs0, Name, St0) -> 2666 foldl(fun ({record_field,Lf,{atom,La,F},V}, {Fs,St}) -> 2667 case exist_field(F, Fs) of 2668 true -> {Fs,add_error(Lf, {redefine_field,Name,F}, St)}; 2669 false -> 2670 St1 = St#lint{recdef_top = true}, 2671 {_,St2} = expr(V, [], St1), 2672 %% Warnings and errors found are kept, but 2673 %% updated calls, records, etc. are discarded. 2674 St3 = St1#lint{warnings = St2#lint.warnings, 2675 errors = St2#lint.errors, 2676 called = St2#lint.called, 2677 recdef_top = false}, 2678 %% This is one way of avoiding a loop for 2679 %% "recursive" definitions. 2680 NV = case St2#lint.errors =:= St1#lint.errors of 2681 true -> V; 2682 false -> {atom,La,undefined} 2683 end, 2684 {[{record_field,Lf,{atom,La,F},NV}|Fs],St3} 2685 end 2686 end, {[],St0}, Fs0). 2687 2688%% normalise_fields([RecDef]) -> [Field]. 2689%% Normalise the field definitions to always have a default value. If 2690%% none has been given then use 'undefined'. 2691%% Also, strip type information from typed record fields. 2692 2693normalise_fields(Fs) -> 2694 map(fun ({record_field,Lf,Field}) -> 2695 {record_field,Lf,Field,{atom,Lf,undefined}}; 2696 ({typed_record_field,{record_field,Lf,Field},_Type}) -> 2697 {record_field,Lf,Field,{atom,Lf,undefined}}; 2698 ({typed_record_field,Field,_Type}) -> 2699 Field; 2700 (F) -> F end, Fs). 2701 2702%% exist_record(Line, RecordName, State) -> State. 2703%% Check if a record exists. Set State. 2704 2705exist_record(Line, Name, St) -> 2706 case is_map_key(Name, St#lint.records) of 2707 true -> used_record(Name, St); 2708 false -> add_error(Line, {undefined_record,Name}, St) 2709 end. 2710 2711%% check_record(Line, RecordName, State, CheckFun) -> 2712%% {UpdVarTable, State}. 2713%% The generic record checking function, first checks that the record 2714%% exists then calls the specific check function. N.B. the check 2715%% function can safely assume that the record exists. 2716%% 2717%% The check function is called: 2718%% CheckFun(RecordDefFields, State) 2719%% and must return 2720%% {UpdatedVarTable,State} 2721 2722check_record(Line, Name, St, CheckFun) -> 2723 case maps:find(Name, St#lint.records) of 2724 {ok,{_Line,Fields}} -> CheckFun(Fields, used_record(Name, St)); 2725 error -> {[],add_error(Line, {undefined_record,Name}, St)} 2726 end. 2727 2728used_record(Name, #lint{usage=Usage}=St) -> 2729 UsedRecs = gb_sets:add_element(Name, Usage#usage.used_records), 2730 St#lint{usage = Usage#usage{used_records=UsedRecs}}. 2731 2732%%% Record check functions. 2733 2734%% check_fields([ChkField], RecordName, [RecDefField], VarTable, State, CheckFun) -> 2735%% {UpdVarTable,State}. 2736 2737check_fields(Fs, Name, Fields, Vt, St0, CheckFun) -> 2738 {_SeenFields,Uvt,St1} = 2739 foldl(fun (Field, {Sfsa,Vta,Sta}) -> 2740 {Sfsb,{Vtb,Stb}} = check_field(Field, Name, Fields, 2741 Vt, Sta, Sfsa, CheckFun), 2742 {Sfsb,vtmerge_pat(Vta, Vtb),Stb} 2743 end, {[],[],St0}, Fs), 2744 {Uvt,St1}. 2745 2746check_field({record_field,Lf,{atom,La,F},Val}, Name, Fields, 2747 Vt, St, Sfs, CheckFun) -> 2748 case member(F, Sfs) of 2749 true -> {Sfs,{[],add_error(Lf, {redefine_field,Name,F}, St)}}; 2750 false -> 2751 {[F|Sfs], 2752 case find_field(F, Fields) of 2753 {ok,_I} -> CheckFun(Val, Vt, St); 2754 error -> {[],add_error(La, {undefined_field,Name,F}, St)} 2755 end} 2756 end; 2757check_field({record_field,_Lf,{var,La,'_'=F},Val}, _Name, _Fields, 2758 Vt, St, Sfs, CheckFun) -> 2759 case member(F, Sfs) of 2760 true -> {Sfs,{[],add_error(La, bad_multi_field_init, St)}}; 2761 false -> {[F|Sfs],CheckFun(Val, Vt, St)} 2762 end; 2763check_field({record_field,_Lf,{var,La,V},_Val}, Name, _Fields, 2764 Vt, St, Sfs, _CheckFun) -> 2765 {Sfs,{Vt,add_error(La, {field_name_is_variable,Name,V}, St)}}. 2766 2767%% pattern_field(Field, RecordName, [RecDefField], State) -> 2768%% {UpdVarTable,State}. 2769%% Test if record RecordName has field Field. Set State. 2770 2771pattern_field({atom,La,F}, Name, Fields, St) -> 2772 case find_field(F, Fields) of 2773 {ok,_I} -> {[],St}; 2774 error -> {[],add_error(La, {undefined_field,Name,F}, St)} 2775 end. 2776 2777%% pattern_fields([PatField],RecordName,[RecDefField], 2778%% VarTable,Old,Bvt,State) -> 2779%% {UpdVarTable,UpdBinVarTable,State}. 2780 2781pattern_fields(Fs, Name, Fields, Vt0, Old, Bvt, St0) -> 2782 CheckFun = fun (Val, Vt, St) -> pattern(Val, Vt, Old, Bvt, St) end, 2783 {_SeenFields,Uvt,Bvt1,St1} = 2784 foldl(fun (Field, {Sfsa,Vta,Bvt1,Sta}) -> 2785 case check_field(Field, Name, Fields, 2786 Vt0, Sta, Sfsa, CheckFun) of 2787 {Sfsb,{Vtb,Stb}} -> 2788 {Sfsb,vtmerge_pat(Vta, Vtb),[],Stb}; 2789 {Sfsb,{Vtb,Bvt2,Stb}} -> 2790 {Sfsb,vtmerge_pat(Vta, Vtb), 2791 vtmerge_pat(Bvt1,Bvt2),Stb} 2792 end 2793 end, {[],[],[],St0}, Fs), 2794 {Uvt,Bvt1,St1}. 2795 2796%% record_field(Field, RecordName, [RecDefField], State) -> 2797%% {UpdVarTable,State}. 2798%% Test if record RecordName has field Field. Set State. 2799 2800record_field({atom,La,F}, Name, Fields, St) -> 2801 case find_field(F, Fields) of 2802 {ok,_I} -> {[],St}; 2803 error -> {[],add_error(La, {undefined_field,Name,F}, St)} 2804 end. 2805 2806%% init_fields([InitField], InitLine, RecordName, [DefField], VarTable, State) -> 2807%% {UpdVarTable,State}. 2808%% ginit_fields([InitField], InitLine, RecordName, [DefField], VarTable, State) -> 2809%% {UpdVarTable,State}. 2810%% Check record initialisation. Explicit initialisations are checked 2811%% as is, while default values are checked only if there are no 2812%% explicit inititialisations of the fields. Be careful not to 2813%% duplicate warnings (and possibly errors, but def_fields 2814%% substitutes 'undefined' for bogus inititialisations) from when the 2815%% record definitions were checked. Usage of records, imports, and 2816%% functions is collected. 2817 2818init_fields(Ifs, Line, Name, Dfs, Vt0, St0) -> 2819 {Vt1,St1} = check_fields(Ifs, Name, Dfs, Vt0, St0, fun expr/3), 2820 Defs = init_fields(Ifs, Line, Dfs), 2821 {_,St2} = check_fields(Defs, Name, Dfs, Vt1, St1, fun expr/3), 2822 {Vt1,St1#lint{usage = St2#lint.usage}}. 2823 2824ginit_fields(Ifs, Line, Name, Dfs, Vt0, St0) -> 2825 {Vt1,St1} = check_fields(Ifs, Name, Dfs, Vt0, St0, fun gexpr/3), 2826 Defs = init_fields(Ifs, Line, Dfs), 2827 St2 = St1#lint{errors = []}, 2828 {_,St3} = check_fields(Defs, Name, Dfs, Vt1, St2, fun gexpr/3), 2829 #lint{usage = Usage, errors = Errors} = St3, 2830 IllErrs = [E || {_File,{_Line,erl_lint,illegal_guard_expr}}=E <- Errors], 2831 St4 = St1#lint{usage = Usage, errors = IllErrs ++ St1#lint.errors}, 2832 {Vt1,St4}. 2833 2834%% Default initializations to be carried out 2835init_fields(Ifs, Line, Dfs) -> 2836 [ {record_field,Lf,{atom,La,F},copy_expr(Di, Line)} || 2837 {record_field,Lf,{atom,La,F},Di} <- Dfs, 2838 not exist_field(F, Ifs) ]. 2839 2840%% update_fields(UpdFields, RecordName, RecDefFields, VarTable, State) -> 2841%% {UpdVarTable,State} 2842 2843update_fields(Ufs, Name, Dfs, Vt, St) -> 2844 check_fields(Ufs, Name, Dfs, Vt, St, fun expr/3). 2845 2846%% exist_field(FieldName, [Field]) -> boolean(). 2847%% Find a record field in a field list. 2848 2849exist_field(F, [{record_field,_Lf,{atom,_La,F},_Val}|_Fs]) -> true; 2850exist_field(F, [_|Fs]) -> exist_field(F, Fs); 2851exist_field(_F, []) -> false. 2852 2853%% find_field(FieldName, [Field]) -> {ok,Val} | error. 2854%% Find a record field in a field list. 2855 2856find_field(_F, [{record_field,_Lf,{atom,_La,_F},Val}|_Fs]) -> {ok,Val}; 2857find_field(F, [_|Fs]) -> find_field(F, Fs); 2858find_field(_F, []) -> error. 2859 2860%% type_def(Attr, Line, TypeName, PatField, Args, State) -> State. 2861%% Attr :: 'type' | 'opaque' 2862%% Checks that a type definition is valid. 2863 2864-dialyzer({no_match, type_def/6}). 2865 2866type_def(Attr, Line, TypeName, ProtoType, Args, St0) -> 2867 TypeDefs = St0#lint.types, 2868 Arity = length(Args), 2869 TypePair = {TypeName, Arity}, 2870 Info = #typeinfo{attr = Attr, line = Line}, 2871 StoreType = 2872 fun(St) -> 2873 NewDefs = maps:put(TypePair, Info, TypeDefs), 2874 CheckType = {type, nowarn(), product, [ProtoType|Args]}, 2875 check_type(CheckType, St#lint{types=NewDefs}) 2876 end, 2877 case is_default_type(TypePair) of 2878 true -> 2879 case is_obsolete_builtin_type(TypePair) of 2880 true -> StoreType(St0); 2881 false -> 2882 case is_newly_introduced_builtin_type(TypePair) of 2883 %% allow some types just for bootstrapping 2884 true -> 2885 Warn = {new_builtin_type, TypePair}, 2886 St1 = add_warning(Line, Warn, St0), 2887 StoreType(St1); 2888 false -> 2889 add_error(Line, {builtin_type, TypePair}, St0) 2890 end 2891 end; 2892 false -> 2893 case is_map_key(TypePair, TypeDefs) of 2894 true -> 2895 add_error(Line, {redefine_type, TypePair}, St0); 2896 false -> 2897 St1 = case 2898 Attr =:= opaque andalso 2899 is_underspecified(ProtoType, Arity) 2900 of 2901 true -> 2902 Warn = {underspecified_opaque, TypePair}, 2903 add_warning(Line, Warn, St0); 2904 false -> St0 2905 end, 2906 StoreType(St1) 2907 end 2908 end. 2909 2910is_underspecified({type,_,term,[]}, 0) -> true; 2911is_underspecified({type,_,any,[]}, 0) -> true; 2912is_underspecified(_ProtType, _Arity) -> false. 2913 2914check_type(Types, St) -> 2915 {SeenVars, St1} = check_type(Types, maps:new(), St), 2916 maps:fold(fun(Var, {seen_once, Line}, AccSt) -> 2917 case atom_to_list(Var) of 2918 "_"++_ -> AccSt; 2919 _ -> add_error(Line, {singleton_typevar, Var}, AccSt) 2920 end; 2921 (_Var, seen_multiple, AccSt) -> 2922 AccSt 2923 end, St1, SeenVars). 2924 2925check_type({ann_type, _L, [_Var, Type]}, SeenVars, St) -> 2926 check_type(Type, SeenVars, St); 2927check_type({remote_type, L, [{atom, _, Mod}, {atom, _, Name}, Args]}, 2928 SeenVars, St00) -> 2929 St0 = check_module_name(Mod, L, St00), 2930 St = deprecated_type(L, Mod, Name, Args, St0), 2931 CurrentMod = St#lint.module, 2932 case Mod =:= CurrentMod of 2933 true -> check_type({user_type, L, Name, Args}, SeenVars, St); 2934 false -> 2935 lists:foldl(fun(T, {AccSeenVars, AccSt}) -> 2936 check_type(T, AccSeenVars, AccSt) 2937 end, {SeenVars, St}, Args) 2938 end; 2939check_type({integer, _L, _}, SeenVars, St) -> {SeenVars, St}; 2940check_type({atom, _L, _}, SeenVars, St) -> {SeenVars, St}; 2941check_type({var, _L, '_'}, SeenVars, St) -> {SeenVars, St}; 2942check_type({var, L, Name}, SeenVars, St) -> 2943 NewSeenVars = 2944 case maps:find(Name, SeenVars) of 2945 {ok, {seen_once, _}} -> maps:put(Name, seen_multiple, SeenVars); 2946 {ok, seen_multiple} -> SeenVars; 2947 error -> maps:put(Name, {seen_once, L}, SeenVars) 2948 end, 2949 {NewSeenVars, St}; 2950check_type({type, L, bool, []}, SeenVars, St) -> 2951 {SeenVars, add_warning(L, {renamed_type, bool, boolean}, St)}; 2952check_type({type, L, 'fun', [Dom, Range]}, SeenVars, St) -> 2953 St1 = 2954 case Dom of 2955 {type, _, product, _} -> St; 2956 {type, _, any} -> St; 2957 _ -> add_error(L, {type_syntax, 'fun'}, St) 2958 end, 2959 check_type({type, nowarn(), product, [Dom, Range]}, SeenVars, St1); 2960check_type({type, L, range, [From, To]}, SeenVars, St) -> 2961 St1 = 2962 case {erl_eval:partial_eval(From), erl_eval:partial_eval(To)} of 2963 {{integer, _, X}, {integer, _, Y}} when X < Y -> St; 2964 _ -> add_error(L, {type_syntax, range}, St) 2965 end, 2966 {SeenVars, St1}; 2967check_type({type, _L, map, any}, SeenVars, St) -> 2968 {SeenVars, St}; 2969check_type({type, _L, map, Pairs}, SeenVars, St) -> 2970 lists:foldl(fun(Pair, {AccSeenVars, AccSt}) -> 2971 check_type(Pair, AccSeenVars, AccSt) 2972 end, {SeenVars, St}, Pairs); 2973check_type({type, _L, map_field_assoc, [Dom, Range]}, SeenVars, St) -> 2974 check_type({type, nowarn(), product, [Dom, Range]}, SeenVars, St); 2975check_type({type, _L, tuple, any}, SeenVars, St) -> {SeenVars, St}; 2976check_type({type, _L, any}, SeenVars, St) -> {SeenVars, St}; 2977check_type({type, L, binary, [Base, Unit]}, SeenVars, St) -> 2978 St1 = 2979 case {erl_eval:partial_eval(Base), erl_eval:partial_eval(Unit)} of 2980 {{integer, _, BaseVal}, 2981 {integer, _, UnitVal}} when BaseVal >= 0, UnitVal >= 0 -> St; 2982 _ -> add_error(L, {type_syntax, binary}, St) 2983 end, 2984 {SeenVars, St1}; 2985check_type({type, L, record, [Name|Fields]}, SeenVars, St) -> 2986 case Name of 2987 {atom, _, Atom} -> 2988 St1 = used_record(Atom, St), 2989 check_record_types(L, Atom, Fields, SeenVars, St1); 2990 _ -> {SeenVars, add_error(L, {type_syntax, record}, St)} 2991 end; 2992check_type({type, _L, Tag, Args}, SeenVars, St) when Tag =:= product; 2993 Tag =:= union; 2994 Tag =:= tuple -> 2995 lists:foldl(fun(T, {AccSeenVars, AccSt}) -> 2996 check_type(T, AccSeenVars, AccSt) 2997 end, {SeenVars, St}, Args); 2998check_type({type, La, TypeName, Args}, SeenVars, St) -> 2999 #lint{module = Module, types=Types} = St, 3000 Arity = length(Args), 3001 TypePair = {TypeName, Arity}, 3002 Obsolete = (is_warn_enabled(deprecated_type, St) 3003 andalso obsolete_builtin_type(TypePair)), 3004 St1 = case Obsolete of 3005 {deprecated, Repl, _} when element(1, Repl) =/= Module -> 3006 case maps:find(TypePair, Types) of 3007 {ok, _} -> 3008 used_type(TypePair, La, St); 3009 error -> 3010 {deprecated, Replacement, Rel} = Obsolete, 3011 Tag = deprecated_builtin_type, 3012 W = {Tag, TypePair, Replacement, Rel}, 3013 add_warning(La, W, St) 3014 end; 3015 _ -> St 3016 end, 3017 check_type({type, nowarn(), product, Args}, SeenVars, St1); 3018check_type({user_type, L, TypeName, Args}, SeenVars, St) -> 3019 Arity = length(Args), 3020 TypePair = {TypeName, Arity}, 3021 St1 = used_type(TypePair, L, St), 3022 lists:foldl(fun(T, {AccSeenVars, AccSt}) -> 3023 check_type(T, AccSeenVars, AccSt) 3024 end, {SeenVars, St1}, Args); 3025check_type([{typed_record_field,Field,_T}|_], SeenVars, St) -> 3026 {SeenVars, add_error(element(2, Field), old_abstract_code, St)}; 3027check_type(I, SeenVars, St) -> 3028 case erl_eval:partial_eval(I) of 3029 {integer,_ILn,_Integer} -> {SeenVars, St}; 3030 _Other -> 3031 {SeenVars, add_error(element(2, I), {type_syntax, integer}, St)} 3032 end. 3033 3034check_record_types(Line, Name, Fields, SeenVars, St) -> 3035 case maps:find(Name, St#lint.records) of 3036 {ok,{_L,DefFields}} -> 3037 case lists:all(fun({type, _, field_type, _}) -> true; 3038 (_) -> false 3039 end, Fields) of 3040 true -> 3041 check_record_types(Fields, Name, DefFields, SeenVars, St, []); 3042 false -> 3043 {SeenVars, add_error(Line, {type_syntax, record}, St)} 3044 end; 3045 error -> 3046 {SeenVars, add_error(Line, {undefined_record, Name}, St)} 3047 end. 3048 3049check_record_types([{type, _, field_type, [{atom, AL, FName}, Type]}|Left], 3050 Name, DefFields, SeenVars, St, SeenFields) -> 3051 %% Check that the field name is valid 3052 St1 = case exist_field(FName, DefFields) of 3053 true -> St; 3054 false -> add_error(AL, {undefined_field, Name, FName}, St) 3055 end, 3056 %% Check for duplicates 3057 St2 = case ordsets:is_element(FName, SeenFields) of 3058 true -> add_error(AL, {redefine_field, Name, FName}, St1); 3059 false -> St1 3060 end, 3061 %% Check Type 3062 {NewSeenVars, St3} = check_type(Type, SeenVars, St2), 3063 NewSeenFields = ordsets:add_element(FName, SeenFields), 3064 check_record_types(Left, Name, DefFields, NewSeenVars, St3, NewSeenFields); 3065check_record_types([], _Name, _DefFields, SeenVars, St, _SeenFields) -> 3066 {SeenVars, St}. 3067 3068used_type(TypePair, L, #lint{usage = Usage, file = File} = St) -> 3069 OldUsed = Usage#usage.used_types, 3070 UsedTypes = maps:put(TypePair, erl_anno:set_file(File, L), OldUsed), 3071 St#lint{usage=Usage#usage{used_types=UsedTypes}}. 3072 3073is_default_type({Name, NumberOfTypeVariables}) -> 3074 erl_internal:is_type(Name, NumberOfTypeVariables). 3075 3076is_newly_introduced_builtin_type({Name, _}) when is_atom(Name) -> false. 3077 3078is_obsolete_builtin_type(TypePair) -> 3079 obsolete_builtin_type(TypePair) =/= no. 3080 3081%% To keep Dialyzer silent... 3082obsolete_builtin_type({1, 255}) -> 3083 {deprecated, {2, 255}, ""}; 3084obsolete_builtin_type({Name, A}) when is_atom(Name), is_integer(A) -> no. 3085 3086%% spec_decl(Line, Fun, Types, State) -> State. 3087 3088spec_decl(Line, MFA0, TypeSpecs, St00 = #lint{specs = Specs, module = Mod}) -> 3089 MFA = case MFA0 of 3090 {F, Arity} -> {Mod, F, Arity}; 3091 {_M, _F, Arity} -> MFA0 3092 end, 3093 St0 = check_module_name(element(1, MFA), Line, St00), 3094 St1 = St0#lint{specs = maps:put(MFA, Line, Specs)}, 3095 case is_map_key(MFA, Specs) of 3096 true -> add_error(Line, {redefine_spec, MFA0}, St1); 3097 false -> 3098 case MFA of 3099 {Mod, _, _} -> 3100 check_specs(TypeSpecs, spec_wrong_arity, Arity, St1); 3101 _ -> 3102 add_error(Line, {bad_module, MFA}, St1) 3103 end 3104 end. 3105 3106%% callback_decl(Line, Fun, Types, State) -> State. 3107 3108callback_decl(Line, MFA0, TypeSpecs, 3109 St0 = #lint{callbacks = Callbacks, module = Mod}) -> 3110 case MFA0 of 3111 {M, _F, _A} -> 3112 St1 = check_module_name(M, Line, St0), 3113 add_error(Line, {bad_callback, MFA0}, St1); 3114 {F, Arity} -> 3115 MFA = {Mod, F, Arity}, 3116 St1 = St0#lint{callbacks = maps:put(MFA, Line, Callbacks)}, 3117 case is_map_key(MFA, Callbacks) of 3118 true -> add_error(Line, {redefine_callback, MFA0}, St1); 3119 false -> check_specs(TypeSpecs, callback_wrong_arity, 3120 Arity, St1) 3121 end 3122 end. 3123 3124%% optional_callbacks(Line, FAs, State) -> State. 3125 3126optional_callbacks(Line, Term, St0) -> 3127 try true = is_fa_list(Term), Term of 3128 FAs -> 3129 optional_cbs(Line, FAs, St0) 3130 catch 3131 _:_ -> 3132 St0 % ignore others 3133 end. 3134 3135optional_cbs(_Line, [], St) -> 3136 St; 3137optional_cbs(Line, [{F,A}|FAs], St0) -> 3138 #lint{optional_callbacks = OptionalCbs, module = Mod} = St0, 3139 MFA = {Mod, F, A}, 3140 St1 = St0#lint{optional_callbacks = maps:put(MFA, Line, OptionalCbs)}, 3141 St2 = case is_map_key(MFA, OptionalCbs) of 3142 true -> 3143 add_error(Line, {redefine_optional_callback, {F,A}}, St1); 3144 false -> 3145 St1 3146 end, 3147 optional_cbs(Line, FAs, St2). 3148 3149is_fa_list([E|L]) -> is_fa(E) andalso is_fa_list(L); 3150is_fa_list([]) -> true; 3151is_fa_list(_) -> false. 3152 3153is_fa({FuncName, Arity}) 3154 when is_atom(FuncName), is_integer(Arity), Arity >= 0 -> true; 3155is_fa(_) -> false. 3156 3157check_module_name(M, Line, St) -> 3158 case is_latin1_name(M) of 3159 true -> St; 3160 false -> 3161 add_error(Line, non_latin1_module_unsupported, St) 3162 end. 3163 3164is_latin1_name(Name) -> 3165 io_lib:latin1_char_list(atom_to_list(Name)). 3166 3167check_specs([FunType|Left], ETag, Arity, St0) -> 3168 {FunType1, CTypes} = 3169 case FunType of 3170 {type, _, bounded_fun, [FT = {type, _, 'fun', _}, Cs]} -> 3171 Types0 = [T || {type, _, constraint, [_, T]} <- Cs], 3172 {FT, lists:append(Types0)}; 3173 {type, _, 'fun', _} = FT -> {FT, []} 3174 end, 3175 {type, L, 'fun', [{type, _, product, D}, _]} = FunType1, 3176 SpecArity = length(D), 3177 St1 = case Arity =:= SpecArity of 3178 true -> St0; 3179 false -> %% Cannot happen if called from the compiler. 3180 add_error(L, ETag, St0) 3181 end, 3182 St2 = check_type({type, nowarn(), product, [FunType1|CTypes]}, St1), 3183 check_specs(Left, ETag, Arity, St2); 3184check_specs([], _ETag, _Arity, St) -> 3185 St. 3186 3187nowarn() -> 3188 A0 = erl_anno:new(0), 3189 A1 = erl_anno:set_generated(true, A0), 3190 erl_anno:set_file("", A1). 3191 3192check_specs_without_function(#lint{module=Mod,defined=Funcs,specs=Specs}=St) -> 3193 Fun = fun({M, F, A}, Line, AccSt) when M =:= Mod -> 3194 FA = {F, A}, 3195 case gb_sets:is_element(FA, Funcs) of 3196 true -> AccSt; 3197 false -> add_error(Line, {spec_fun_undefined, FA}, AccSt) 3198 end; 3199 ({_M, _F, _A}, _Line, AccSt) -> AccSt 3200 end, 3201 maps:fold(Fun, St, Specs). 3202 3203%% This generates warnings for functions without specs; if the user has 3204%% specified both options, we do not generate the same warnings twice. 3205check_functions_without_spec(Forms, St0) -> 3206 case is_warn_enabled(missing_spec_all, St0) of 3207 true -> 3208 add_missing_spec_warnings(Forms, St0, all); 3209 false -> 3210 case is_warn_enabled(missing_spec, St0) of 3211 true -> 3212 add_missing_spec_warnings(Forms, St0, exported); 3213 false -> 3214 St0 3215 end 3216 end. 3217 3218add_missing_spec_warnings(Forms, St0, Type) -> 3219 Specs = [{F,A} || {_M,F,A} <- maps:keys(St0#lint.specs)], 3220 Warns = %% functions + line numbers for which we should warn 3221 case Type of 3222 all -> 3223 [{FA,L} || {function,L,F,A,_} <- Forms, 3224 not lists:member(FA = {F,A}, Specs)]; 3225 exported -> 3226 Exps0 = gb_sets:to_list(St0#lint.exports) -- pseudolocals(), 3227 Exps = Exps0 -- Specs, 3228 [{FA,L} || {function,L,F,A,_} <- Forms, 3229 member(FA = {F,A}, Exps)] 3230 end, 3231 foldl(fun ({FA,L}, St) -> 3232 add_warning(L, {missing_spec,FA}, St) 3233 end, St0, Warns). 3234 3235check_unused_types(Forms, St) -> 3236 case is_warn_enabled(unused_type, St) of 3237 true -> check_unused_types_1(Forms, St); 3238 false -> St 3239 end. 3240 3241check_unused_types_1(Forms, #lint{usage=Usage, types=Ts, exp_types=ExpTs}=St) -> 3242 case [File || {attribute,_L,file,{File,_Line}} <- Forms] of 3243 [FirstFile|_] -> 3244 D = Usage#usage.used_types, 3245 L = gb_sets:to_list(ExpTs) ++ maps:keys(D), 3246 UsedTypes = gb_sets:from_list(L), 3247 FoldFun = 3248 fun({{record, _}=_Type, 0}, _, AccSt) -> 3249 AccSt; % Before Erlang/OTP 19.0 3250 (Type, #typeinfo{line = FileLine}, AccSt) -> 3251 case loc(FileLine, AccSt) of 3252 {FirstFile, _} -> 3253 case gb_sets:is_member(Type, UsedTypes) of 3254 true -> AccSt; 3255 false -> 3256 Warn = {unused_type,Type}, 3257 add_warning(FileLine, Warn, AccSt) 3258 end; 3259 _ -> 3260 %% No warns about unused types in include files 3261 AccSt 3262 end 3263 end, 3264 maps:fold(FoldFun, St, Ts); 3265 [] -> 3266 St 3267 end. 3268 3269check_local_opaque_types(St) -> 3270 #lint{types=Ts, exp_types=ExpTs} = St, 3271 FoldFun = 3272 fun(_Type, #typeinfo{attr = type}, AccSt) -> 3273 AccSt; 3274 (Type, #typeinfo{attr = opaque, line = FileLine}, AccSt) -> 3275 case gb_sets:is_element(Type, ExpTs) of 3276 true -> AccSt; 3277 false -> 3278 Warn = {not_exported_opaque,Type}, 3279 add_warning(FileLine, Warn, AccSt) 3280 end 3281 end, 3282 maps:fold(FoldFun, St, Ts). 3283 3284check_dialyzer_attribute(Forms, St0) -> 3285 Vals = [{L,V} || 3286 {attribute,L,dialyzer,Val} <- Forms, 3287 V0 <- lists:flatten([Val]), 3288 V <- case V0 of 3289 {O,F} -> 3290 [{A,B} || 3291 A <- lists:flatten([O]), 3292 B <- lists:flatten([F])]; 3293 T -> [T] 3294 end], 3295 {Wellformed, Bad} = 3296 lists:partition(fun ({_,{Option,FA}}) when is_atom(Option) -> 3297 is_fa(FA); 3298 ({_,Option}) when is_atom(Option) -> true; 3299 (_) -> false 3300 end, Vals), 3301 St1 = foldl(fun ({L,Term}, St) -> 3302 add_error(L, {bad_dialyzer_attribute,Term}, St) 3303 end, St0, Bad), 3304 DefFunctions = (gb_sets:to_list(St0#lint.defined) -- pseudolocals()), 3305 Fun = fun ({L,{Option,FA}}, St) -> 3306 case is_function_dialyzer_option(Option) of 3307 true -> 3308 case lists:member(FA, DefFunctions) of 3309 true -> St; 3310 false -> 3311 add_error(L, {undefined_function,FA}, St) 3312 end; 3313 false -> 3314 add_error(L, {bad_dialyzer_option,Option}, St) 3315 end; 3316 ({L,Option}, St) -> 3317 case is_module_dialyzer_option(Option) of 3318 true -> St; 3319 false -> 3320 add_error(L, {bad_dialyzer_option,Option}, St) 3321 end 3322 end, 3323 foldl(Fun, St1, Wellformed). 3324 3325is_function_dialyzer_option(nowarn_function) -> true; 3326is_function_dialyzer_option(Option) -> 3327 is_module_dialyzer_option(Option). 3328 3329is_module_dialyzer_option(Option) -> 3330 lists:member(Option, 3331 [no_return,no_unused,no_improper_lists,no_fun_app, 3332 no_match,no_opaque,no_fail_call,no_contracts, 3333 no_behaviours,no_undefined_callbacks,unmatched_returns, 3334 error_handling,race_conditions,no_missing_calls, 3335 specdiffs,overspecs,underspecs,unknown]). 3336 3337%% try_catch_clauses(Scs, Ccs, In, ImportVarTable, State) -> 3338%% {UpdVt,State}. 3339 3340try_clauses(Scs, Ccs, In, Vt, St0) -> 3341 {Csvt0,St1} = icrt_clauses(Scs, Vt, St0), 3342 St2 = St1#lint{in_try_head=true}, 3343 {Csvt1,St3} = icrt_clauses(Ccs, Vt, St2), 3344 Csvt = Csvt0 ++ Csvt1, 3345 UpdVt = icrt_export(Csvt, Vt, In, St3), 3346 {UpdVt,St3#lint{in_try_head=false}}. 3347 3348%% icrt_clauses(Clauses, In, ImportVarTable, State) -> 3349%% {UpdVt,State}. 3350 3351icrt_clauses(Cs, In, Vt, St0) -> 3352 {Csvt,St1} = icrt_clauses(Cs, Vt, St0), 3353 UpdVt = icrt_export(Csvt, Vt, In, St1), 3354 {UpdVt,St1}. 3355 3356%% icrt_clauses(Clauses, ImportVarTable, State) -> 3357%% {NewVts,State}. 3358 3359icrt_clauses(Cs, Vt, St) -> 3360 mapfoldl(fun (C, St0) -> icrt_clause(C, Vt, St0) end, St, Cs). 3361 3362icrt_clause({clause,_Line,H,G,B}, Vt0, St0) -> 3363 Vt1 = taint_stack_var(Vt0, H, St0), 3364 {Hvt,Binvt,St1} = head(H, Vt1, St0), 3365 Vt2 = vtupdate(Hvt, Binvt), 3366 Vt3 = taint_stack_var(Vt2, H, St0), 3367 {Gvt,St2} = guard(G, vtupdate(Vt3, Vt0), St1#lint{in_try_head=false}), 3368 Vt4 = vtupdate(Gvt, Vt2), 3369 {Bvt,St3} = exprs(B, vtupdate(Vt4, Vt0), St2), 3370 {vtupdate(Bvt, Vt4),St3}. 3371 3372taint_stack_var(Vt, Pat, #lint{in_try_head=true}) -> 3373 [{tuple,_,[_,_,{var,_,Stk}]}] = Pat, 3374 case Stk of 3375 '_' -> 3376 Vt; 3377 _ -> 3378 lists:map(fun({V,{bound,Used,Lines}}) when V =:= Stk -> 3379 {V,{stacktrace,Used,Lines}}; 3380 (B) -> 3381 B 3382 end, Vt) 3383 end; 3384taint_stack_var(Vt, _Pat, #lint{in_try_head=false}) -> 3385 Vt. 3386 3387icrt_export(Vts, Vt, {Tag,Attrs}, St) -> 3388 {_File,Loc} = loc(Attrs, St), 3389 icrt_export(lists:merge(Vts), Vt, {Tag,Loc}, length(Vts), []). 3390 3391icrt_export([{V,{{export,_},_,_}}|Vs0], [{V,{{export,_}=S0,_,Ls}}|Vt], 3392 In, I, Acc) -> 3393 %% V was an exported variable and has been used in an expression in at least 3394 %% one clause. Its state needs to be merged from all clauses to silence any 3395 %% exported var warning already emitted. 3396 {VVs,Vs} = lists:partition(fun ({K,_}) -> K =:= V end, Vs0), 3397 S = foldl(fun ({_,{S1,_,_}}, AccS) -> merge_state(AccS, S1) end, S0, VVs), 3398 icrt_export(Vs, Vt, In, I, [{V,{S,used,Ls}}|Acc]); 3399icrt_export([{V,_}|Vs0], [{V,{_,_,Ls}}|Vt], In, I, Acc) -> 3400 %% V was either unsafe or bound and has now been reused. It may also have 3401 %% been an export but as it was not matched by the previous clause, it means 3402 %% it has been changed to 'bound' in at least one clause because it was used 3403 %% in a pattern. 3404 Vs = lists:dropwhile(fun ({K,_}) -> K =:= V end, Vs0), 3405 icrt_export(Vs, Vt, In, I, [{V,{bound,used,Ls}}|Acc]); 3406icrt_export([{V1,_}|_]=Vs, [{V2,_}|Vt], In, I, Acc) when V1 > V2 -> 3407 %% V2 was already in scope and has not been reused in any clause. 3408 icrt_export(Vs, Vt, In, I, Acc); 3409icrt_export([{V,_}|_]=Vs0, Vt, In, I, Acc) -> 3410 %% V is a new variable. 3411 {VVs,Vs} = lists:partition(fun ({K,_}) -> K =:= V end, Vs0), 3412 F = fun ({_,{S,U,Ls}}, {AccI,AccS0,AccLs0}) -> 3413 AccS = case {S,AccS0} of 3414 {{unsafe,_},{unsafe,_}} -> 3415 %% V was found unsafe in a previous clause, mark 3416 %% it as unsafe for the whole parent expression. 3417 {unsafe,In}; 3418 {{unsafe,_},_} -> 3419 %% V was unsafe in a clause, keep that state and 3420 %% generalize it to the whole expression if it 3421 %% is found unsafe in another one. 3422 S; 3423 _ -> 3424 %% V is either bound or exported, keep original 3425 %% state. 3426 AccS0 3427 end, 3428 AccLs = case U of 3429 used -> AccLs0; 3430 unused -> merge_lines(AccLs0, Ls) 3431 end, 3432 {AccI + 1,AccS,AccLs} 3433 end, 3434 %% Initial state is exported from the current expression. 3435 {Count,S1,Ls} = foldl(F, {0,{export,In},[]}, VVs), 3436 S = case Count of 3437 I -> 3438 %% V was found in all clauses, keep computed state. 3439 S1; 3440 _ -> 3441 %% V was not bound in some clauses, mark as unsafe. 3442 {unsafe,In} 3443 end, 3444 U = case Ls of [] -> used; _ -> unused end, 3445 icrt_export(Vs, Vt, In, I, [{V,{S,U,Ls}}|Acc]); 3446icrt_export([], _, _, _, Acc) -> 3447 reverse(Acc). 3448 3449handle_comprehension(E, Qs, Vt0, St0) -> 3450 {Vt1, Uvt, St1} = lc_quals(Qs, Vt0, St0), 3451 {Evt,St2} = expr(E, Vt1, St1), 3452 Vt2 = vtupdate(Evt, Vt1), 3453 %% Shadowed global variables. 3454 {_,St3} = check_old_unused_vars(Vt2, Uvt, St2), 3455 %% There may be local variables in Uvt that are not global. 3456 {_,St4} = check_unused_vars(Uvt, Vt0, St3), 3457 %% Local variables that have not been shadowed. 3458 {_,St} = check_unused_vars(Vt2, Vt0, St4), 3459 Vt3 = vtmerge(vtsubtract(Vt2, Uvt), Uvt), 3460 %% Don't export local variables. 3461 Vt4 = vtold(Vt3, Vt0), 3462 %% Forget about old variables which were not used as well as unsafe 3463 %% variables, preventing them from being marked as used and bound by 3464 %% icrt_export/4. 3465 Vt = vt_no_unsafe(vt_no_unused(Vt4)), 3466 {Vt, St}. 3467 3468%% lc_quals(Qualifiers, ImportVarTable, State) -> 3469%% {VarTable,ShadowedVarTable,State} 3470%% Test list comprehension qualifiers, return all variables. Allow 3471%% filters to be both guard tests and general expressions, but the errors 3472%% will be for expressions. Return the complete updated vartable including 3473%% local variables and all updates. ShadowVarTable contains the state of 3474%% each shadowed variable. All variable states of variables in ImportVarTable 3475%% that have been shadowed are included in ShadowVarTable. In addition, all 3476%% shadowed variables that are not included in ImportVarTable are included 3477%% in ShadowVarTable (these are local variables that are not global variables). 3478 3479lc_quals(Qs, Vt0, St0) -> 3480 OldRecDef = St0#lint.recdef_top, 3481 {Vt,Uvt,St} = lc_quals(Qs, Vt0, [], St0#lint{recdef_top = false}), 3482 {Vt,Uvt,St#lint{recdef_top = OldRecDef}}. 3483 3484lc_quals([{generate,_Line,P,E} | Qs], Vt0, Uvt0, St0) -> 3485 {Vt,Uvt,St} = handle_generator(P,E,Vt0,Uvt0,St0), 3486 lc_quals(Qs, Vt, Uvt, St); 3487lc_quals([{b_generate,_Line,P,E} | Qs], Vt0, Uvt0, St0) -> 3488 St1 = handle_bitstring_gen_pat(P,St0), 3489 {Vt,Uvt,St} = handle_generator(P,E,Vt0,Uvt0,St1), 3490 lc_quals(Qs, Vt, Uvt, St); 3491lc_quals([F|Qs], Vt, Uvt, St0) -> 3492 Info = is_guard_test2_info(St0), 3493 {Fvt,St1} = case is_guard_test2(F, Info) of 3494 true -> guard_test(F, Vt, St0); 3495 false -> expr(F, Vt, St0) 3496 end, 3497 lc_quals(Qs, vtupdate(Fvt, Vt), Uvt, St1); 3498lc_quals([], Vt, Uvt, St) -> 3499 {Vt, Uvt, St}. 3500 3501is_guard_test2_info(#lint{records=RDs,locals=Locals,imports=Imports}) -> 3502 {RDs,fun(FA) -> 3503 is_local_function(Locals, FA) orelse 3504 is_imported_function(Imports, FA) 3505 end}. 3506 3507handle_generator(P,E,Vt,Uvt,St0) -> 3508 {Evt,St1} = expr(E, Vt, St0), 3509 %% Forget variables local to E immediately. 3510 Vt1 = vtupdate(vtold(Evt, Vt), Vt), 3511 {_, St2} = check_unused_vars(Evt, Vt, St1), 3512 {Pvt,Binvt,St3} = pattern(P, Vt1, [], [], St2), 3513 %% Have to keep fresh variables separated from used variables somehow 3514 %% in order to handle for example X = foo(), [X || <<X:X>> <- bar()]. 3515 %% 1 2 2 1 3516 Vt2 = vtupdate(Pvt, Vt1), 3517 St4 = shadow_vars(Binvt, Vt1, generate, St3), 3518 Svt = vtold(Vt2, Binvt), 3519 {_, St5} = check_old_unused_vars(Svt, Uvt, St4), 3520 NUvt = vtupdate(vtnew(Svt, Uvt), Uvt), 3521 Vt3 = vtupdate(vtsubtract(Vt2, Binvt), Binvt), 3522 {Vt3,NUvt,St5}. 3523 3524handle_bitstring_gen_pat({bin,_,Segments=[_|_]},St) -> 3525 case lists:last(Segments) of 3526 {bin_element,Line,_,default,Flags} when is_list(Flags) -> 3527 case member(binary, Flags) orelse member(bytes, Flags) 3528 orelse member(bits, Flags) orelse member(bitstring, Flags) of 3529 true -> 3530 add_error(Line, unsized_binary_in_bin_gen_pattern, St); 3531 false -> 3532 St 3533 end; 3534 _ -> 3535 St 3536 end; 3537handle_bitstring_gen_pat(_,St) -> 3538 St. 3539 3540%% fun_clauses(Clauses, ImportVarTable, State) -> 3541%% {UsedVars, State}. 3542%% Fun's cannot export any variables. 3543 3544%% It is an error if variable is bound inside a record definition 3545%% unless it was introduced in a fun or an lc. Only if pat_var finds 3546%% such variables can the correct line number be given. 3547 3548fun_clauses(Cs, Vt, St) -> 3549 OldRecDef = St#lint.recdef_top, 3550 {Bvt,St2} = foldl(fun (C, {Bvt0, St0}) -> 3551 {Cvt,St1} = fun_clause(C, Vt, St0), 3552 {vtmerge(Cvt, Bvt0),St1} 3553 end, {[],St#lint{recdef_top = false}}, Cs), 3554 Uvt = vt_no_unsafe(vt_no_unused(vtold(Bvt, Vt))), 3555 {Uvt,St2#lint{recdef_top = OldRecDef}}. 3556 3557fun_clause({clause,_Line,H,G,B}, Vt0, St0) -> 3558 {Hvt,Binvt,St1} = head(H, Vt0, [], St0), % No imported pattern variables 3559 Vt1 = vtupdate(Hvt, Vt0), 3560 St2 = shadow_vars(Binvt, Vt0, 'fun', St1), 3561 Vt2 = vtupdate(vtsubtract(Vt1, Binvt), Binvt), 3562 {Gvt,St3} = guard(G, Vt2, St2), 3563 Vt3 = vtupdate(Gvt, Vt2), 3564 {Bvt,St4} = exprs(B, Vt3, St3), 3565 Cvt = vtupdate(Bvt, Vt3), 3566 %% Check new local variables. 3567 {_, St5} = check_unused_vars(Cvt, Vt0, St4), 3568 %% Check all shadowing variables. 3569 Svt = vtold(Vt1, Binvt), 3570 {_, St6} = check_old_unused_vars(Cvt, Svt, St5), 3571 Vt4 = vtmerge(Svt, vtsubtract(Cvt, Svt)), 3572 {vtold(Vt4, Vt0),St6}. 3573 3574%% In the variable table we store information about variables. The 3575%% information is a tuple {State,Usage,Lines}, the variables state and 3576%% usage. A variable can be in the following states: 3577%% 3578%% bound everything is normal 3579%% {export,From} variable has been exported 3580%% {unsafe,In} variable is unsafe 3581%% 3582%% The usage information has the following form: 3583%% 3584%% used variable has been used 3585%% unused variable has been bound but not used 3586%% 3587%% Lines is a list of line numbers where the variable was bound. 3588%% 3589%% Report variable errors/warnings as soon as possible and then change 3590%% the state to ok. This simplifies the code and reports errors only 3591%% once. Having the usage information like this makes it easy too when 3592%% merging states. 3593 3594%% For keeping track of which variables are bound, ordsets are used. 3595%% In order to be able to give warnings about unused variables, a 3596%% possible value is {bound, unused, [Line]}. The usual value when a 3597%% variable is used is {bound, used, [Line]}. An exception occurs for 3598%% variables in the size position in a bin element in a pattern. 3599%% Currently, such a variable is never matched out, always used, and 3600%% therefore it makes no sense to warn for "variable imported in 3601%% match". 3602 3603%% For storing the variable table we use the orddict module. 3604%% We know an empty set is []. 3605 3606%% pat_var(Variable, LineNo, VarTable, State) -> {UpdVarTable,State} 3607%% A pattern variable has been found. Handle errors and warnings. Return 3608%% all variables as bound so errors and warnings are only reported once. 3609%% Bvt "shadows" Vt here, which is necessary in order to separate uses of 3610%% shadowed and shadowing variables. See also pat_binsize_var. 3611 3612pat_var(V, Line, Vt, Bvt, St) -> 3613 case orddict:find(V, Bvt) of 3614 {ok, {bound,_Usage,Ls}} -> 3615 {[],[{V,{bound,used,Ls}}],St}; 3616 error -> 3617 case orddict:find(V, Vt) of 3618 {ok,{bound,_Usage,Ls}} -> 3619 {[{V,{bound,used,Ls}}],[],St}; 3620 {ok,{{unsafe,In},_Usage,Ls}} -> 3621 {[{V,{bound,used,Ls}}],[], 3622 add_error(Line, {unsafe_var,V,In}, St)}; 3623 {ok,{{export,From},_Usage,Ls}} -> 3624 {[{V,{bound,used,Ls}}],[], 3625 %% As this is matching, exported vars are risky. 3626 add_warning(Line, {exported_var,V,From}, St)}; 3627 {ok,{stacktrace,_Usage,Ls}} -> 3628 {[{V,{bound,used,Ls}}],[], 3629 add_error(Line, {stacktrace_bound,V}, St)}; 3630 error when St#lint.recdef_top -> 3631 {[],[{V,{bound,unused,[Line]}}], 3632 add_error(Line, {variable_in_record_def,V}, St)}; 3633 error -> {[],[{V,{bound,unused,[Line]}}],St} 3634 end 3635 end. 3636 3637%% pat_binsize_var(Variable, LineNo, VarTable, BinVarTable, State) -> 3638%% {UpdVarTable,UpdBinVarTable,State'} 3639%% A pattern variable has been found. Handle errors and warnings. Return 3640%% all variables as bound so errors and warnings are only reported once. 3641 3642pat_binsize_var(V, Line, Vt, Bvt, St) -> 3643 case orddict:find(V, Bvt) of 3644 {ok,{bound,_Used,Ls}} -> 3645 {[],[{V,{bound,used,Ls}}],St}; 3646 error -> 3647 case orddict:find(V, Vt) of 3648 {ok,{bound,_Used,Ls}} -> 3649 {[{V,{bound,used,Ls}}],[],St}; 3650 {ok,{{unsafe,In},_Used,Ls}} -> 3651 {[{V,{bound,used,Ls}}],[], 3652 add_error(Line, {unsafe_var,V,In}, St)}; 3653 {ok,{{export,From},_Used,Ls}} -> 3654 {[{V,{bound,used,Ls}}],[], 3655 %% As this is not matching, exported vars are 3656 %% probably safe. 3657 exported_var(Line, V, From, St)}; 3658 error -> 3659 {[{V,{bound,used,[Line]}}],[], 3660 add_error(Line, {unbound_var,V}, St)} 3661 end 3662 end. 3663 3664%% expr_var(Variable, LineNo, VarTable, State) -> 3665%% {UpdVarTable,State} 3666%% Check if a variable is defined, or if there is an error or warning 3667%% connected to its usage. Return all variables as bound so errors 3668%% and warnings are only reported once. As this is not matching 3669%% exported vars are probably safe, warn only if warn_export_vars is 3670%% set. 3671 3672expr_var(V, Line, Vt, #lint{bvt=none}=St) -> 3673 do_expr_var(V, Line, Vt, St); 3674expr_var(V, Line, Vt0, #lint{bvt=Bvt0}=St0) when is_list(Bvt0) -> 3675 {Vt,Bvt,St} = pat_binsize_var(V, Line, Vt0, Bvt0, St0), 3676 {Vt,St#lint{bvt=vtmerge(Bvt0, Bvt)}}. 3677 3678do_expr_var(V, Line, Vt, St) -> 3679 case orddict:find(V, Vt) of 3680 {ok,{bound,_Usage,Ls}} -> 3681 {[{V,{bound,used,Ls}}],St}; 3682 {ok,{{unsafe,In},_Usage,Ls}} -> 3683 {[{V,{bound,used,Ls}}], 3684 add_error(Line, {unsafe_var,V,In}, St)}; 3685 {ok,{{export,From},_Usage,Ls}} -> 3686 case is_warn_enabled(export_vars, St) of 3687 true -> 3688 {[{V,{bound,used,Ls}}], 3689 add_warning(Line, {exported_var,V,From}, St)}; 3690 false -> 3691 {[{V,{{export,From},used,Ls}}],St} 3692 end; 3693 {ok,{stacktrace,_Usage,Ls}} -> 3694 {[{V,{bound,used,Ls}}], 3695 add_error(Line, {stacktrace_guard,V}, St)}; 3696 error -> 3697 {[{V,{bound,used,[Line]}}], 3698 add_error(Line, {unbound_var,V}, St)} 3699 end. 3700 3701exported_var(Line, V, From, St) -> 3702 case is_warn_enabled(export_vars, St) of 3703 true -> add_warning(Line, {exported_var,V,From}, St); 3704 false -> St 3705 end. 3706 3707shadow_vars(Vt, Vt0, In, St0) -> 3708 case is_warn_enabled(shadow_vars, St0) of 3709 true -> 3710 foldl(fun ({V,{_,_,[L | _]}}, St) -> 3711 add_warning(L, {shadowed_var,V,In}, St); 3712 (_, St) -> St 3713 end, St0, vtold(Vt, vt_no_unsafe(Vt0))); 3714 false -> St0 3715 end. 3716 3717check_unused_vars(Vt, Vt0, St0) -> 3718 U = unused_vars(Vt, Vt0, St0), 3719 warn_unused_vars(U, Vt, St0). 3720 3721check_old_unused_vars(Vt, Vt0, St0) -> 3722 U = unused_vars(vtold(Vt, Vt0), [], St0), 3723 warn_unused_vars(U, Vt, St0). 3724 3725unused_vars(Vt, Vt0, _St0) -> 3726 U0 = orddict:filter(fun (V, {_State,unused,_Ls}) -> 3727 case atom_to_list(V) of 3728 "_"++_ -> false; 3729 _ -> true 3730 end; 3731 (_V, _How) -> false 3732 end, Vt), 3733 vtnew(U0, Vt0). % Only new variables. 3734 3735warn_unused_vars([], Vt, St0) -> 3736 {Vt,St0}; 3737warn_unused_vars(U, Vt, St0) -> 3738 St1 = case is_warn_enabled(unused_vars, St0) of 3739 false -> St0; 3740 true -> 3741 foldl(fun ({V,{_,unused,Ls}}, St) -> 3742 foldl(fun (L, St2) -> 3743 add_warning(L, {unused_var,V}, 3744 St2) 3745 end, St, Ls) 3746 end, St0, U) 3747 end, 3748 %% Return all variables as bound so warnings are only reported once. 3749 UVt = map(fun ({V,{State,_,Ls}}) -> {V,{State,used,Ls}} end, U), 3750 {vtmerge(Vt, UVt), St1}. 3751 3752 3753is_var_bound(V, Vt) -> 3754 case orddict:find(V, Vt) of 3755 {ok,{bound,_Usage,_}} -> true; 3756 _ -> false 3757 end. 3758 3759 3760%% vtupdate(UpdVarTable, VarTable) -> VarTable. 3761%% Add the variables in the updated vartable to VarTable. The variables 3762%% will be updated with their property in UpdVarTable. The state of 3763%% the variables in UpdVarTable will be returned. 3764 3765vtupdate(Uvt, Vt0) -> 3766 orddict:merge(fun (_V, {S,U1,L1}, {_S,U2,L2}) -> 3767 {S, merge_used(U1, U2), merge_lines(L1, L2)} 3768 end, Uvt, Vt0). 3769 3770%% vtunsafe(From, UpdVarTable, VarTable) -> UnsafeVarTable. 3771%% Return all new variables in UpdVarTable as unsafe. 3772 3773vtunsafe({Tag,FileLine}, Uvt, Vt) -> 3774 Line = erl_anno:location(FileLine), 3775 [{V,{{unsafe,{Tag,Line}},U,Ls}} || {V,{_,U,Ls}} <- vtnew(Uvt, Vt)]. 3776 3777%% vtmerge(VarTable, VarTable) -> VarTable. 3778%% Merge two variables tables generating a new vartable. Give priority to 3779%% errors then warnings. 3780 3781vtmerge(Vt1, Vt2) -> 3782 orddict:merge(fun (_V, {S1,U1,L1}, {S2,U2,L2}) -> 3783 {merge_state(S1, S2), 3784 merge_used(U1, U2), 3785 merge_lines(L1, L2)} 3786 end, Vt1, Vt2). 3787 3788vtmerge(Vts) -> foldl(fun (Vt, Mvts) -> vtmerge(Vt, Mvts) end, [], Vts). 3789 3790vtmerge_pat(Vt1, Vt2) -> 3791 orddict:merge(fun (_V, {S1,_Usage1,L1}, {S2,_Usage2,L2}) -> 3792 {merge_state(S1, S2),used, merge_lines(L1, L2)} 3793 end, Vt1, Vt2). 3794 3795merge_lines(Ls1, Ls2) -> 3796 ordsets:union(Ls1,Ls2). 3797 3798merge_state({unsafe,_F1}=S1, _S2) -> S1; %Take the error case 3799merge_state(_S1, {unsafe,_F2}=S2) -> S2; 3800merge_state(bound, S2) -> S2; %Take the warning 3801merge_state(S1, bound) -> S1; 3802merge_state({export,F1},{export,_F2}) -> %Sanity check 3803 %% We want to report the outermost construct 3804 {export,F1}. 3805 3806merge_used(used, _Usage2) -> used; 3807merge_used(_Usage1, used) -> used; 3808merge_used(unused, unused) -> unused. 3809 3810%% vtnew(NewVarTable, OldVarTable) -> NewVarTable. 3811%% Return all the truly new variables in NewVarTable. 3812 3813vtnew(New, Old) -> 3814 orddict:filter(fun (V, _How) -> not orddict:is_key(V, Old) end, New). 3815 3816%% vtsubtract(VarTable1, VarTable2) -> NewVarTable. 3817%% Return all the variables in VarTable1 which don't occur in VarTable2. 3818%% Same thing as vtnew, but a more intuitive name for some uses. 3819vtsubtract(New, Old) -> 3820 vtnew(New, Old). 3821 3822%% vtold(NewVarTable, OldVarTable) -> OldVarTable. 3823%% Return all the truly old variables in NewVarTable. 3824 3825vtold(New, Old) -> 3826 orddict:filter(fun (V, _How) -> orddict:is_key(V, Old) end, New). 3827 3828vt_no_unsafe(Vt) -> [V || {_,{S,_U,_L}}=V <- Vt, 3829 case S of 3830 {unsafe,_} -> false; 3831 _ -> true 3832 end]. 3833 3834vt_no_unused(Vt) -> [V || {_,{_,U,_L}}=V <- Vt, U =/= unused]. 3835 3836%% copy_expr(Expr, Line) -> Expr. 3837%% Make a copy of Expr converting all line numbers to Line. 3838 3839copy_expr(Expr, Anno) -> 3840 erl_parse:map_anno(fun(_A) -> Anno end, Expr). 3841 3842%% Check a record_info call. We have already checked that it is not 3843%% shadowed by an import. 3844 3845check_record_info_call(_Line,La,[{atom,Li,Info},{atom,_Ln,Name}],St) -> 3846 case member(Info, [fields,size]) of 3847 true -> exist_record(La, Name, St); 3848 false -> add_error(Li, illegal_record_info, St) 3849 end; 3850check_record_info_call(Line,_La,_As,St) -> 3851 add_error(Line, illegal_record_info, St). 3852 3853has_wildcard_field([{record_field,_Lf,{var,_La,'_'},_Val}|_Fs]) -> true; 3854has_wildcard_field([_|Fs]) -> has_wildcard_field(Fs); 3855has_wildcard_field([]) -> false. 3856 3857%% check_remote_function(Line, ModuleName, FuncName, [Arg], State) -> State. 3858%% Perform checks on known remote calls. 3859 3860check_remote_function(Line, M, F, As, St0) -> 3861 St1 = deprecated_function(Line, M, F, As, St0), 3862 St2 = check_qlc_hrl(Line, M, F, As, St1), 3863 St3 = check_load_nif(Line, M, F, As, St2), 3864 format_function(Line, M, F, As, St3). 3865 3866%% check_load_nif(Line, ModName, FuncName, [Arg], State) -> State 3867%% Add warning if erlang:load_nif/2 is called when any kind of inlining has 3868%% been enabled. 3869check_load_nif(Line, erlang, load_nif, [_, _], St) -> 3870 case is_warn_enabled(nif_inline, St) of 3871 true -> check_nif_inline(Line, St); 3872 false -> St 3873 end; 3874check_load_nif(_Line, _ModName, _FuncName, _Args, St) -> 3875 St. 3876 3877check_nif_inline(Line, St) -> 3878 case any(fun is_inline_opt/1, St#lint.compile) of 3879 true -> add_warning(Line, nif_inline, St); 3880 false -> St 3881 end. 3882 3883is_inline_opt({inline, [_|_]=_FAs}) -> true; 3884is_inline_opt(inline) -> true; 3885is_inline_opt(_) -> false. 3886 3887%% check_qlc_hrl(Line, ModName, FuncName, [Arg], State) -> State 3888%% Add warning if qlc:q/1,2 has been called but qlc.hrl has not 3889%% been included. 3890 3891check_qlc_hrl(Line, M, F, As, St) -> 3892 Arity = length(As), 3893 case As of 3894 [{lc,_L,_E,_Qs}|_] when M =:= qlc, F =:= q, 3895 Arity < 3, not St#lint.xqlc -> 3896 add_warning(Line, {missing_qlc_hrl, Arity}, St); 3897 _ -> 3898 St 3899 end. 3900 3901%% deprecated_function(Line, ModName, FuncName, [Arg], State) -> State. 3902%% Add warning for calls to deprecated functions. 3903 3904-dialyzer({no_match, deprecated_function/5}). 3905 3906deprecated_function(Line, M, F, As, St) -> 3907 Arity = length(As), 3908 MFA = {M, F, Arity}, 3909 case otp_internal:obsolete(M, F, Arity) of 3910 {deprecated, String} when is_list(String) -> 3911 case not is_warn_enabled(deprecated_function, St) orelse 3912 ordsets:is_element(MFA, St#lint.not_deprecated) of 3913 true -> 3914 St; 3915 false -> 3916 add_warning(Line, {deprecated, MFA, String}, St) 3917 end; 3918 {deprecated, Replacement, Rel} -> 3919 case not is_warn_enabled(deprecated_function, St) orelse 3920 ordsets:is_element(MFA, St#lint.not_deprecated) of 3921 true -> 3922 St; 3923 false -> 3924 add_warning(Line, {deprecated, MFA, Replacement, Rel}, St) 3925 end; 3926 {removed, String} when is_list(String) -> 3927 add_removed_warning(Line, MFA, {removed, MFA, String}, St); 3928 {removed, Replacement, Rel} -> 3929 add_removed_warning(Line, MFA, {removed, MFA, Replacement, Rel}, St); 3930 no -> 3931 St 3932 end. 3933 3934add_removed_warning(Line, {M, _, _}=MFA, Warning, #lint{not_removed=NotRemoved}=St) -> 3935 case is_warn_enabled(removed, St) andalso 3936 not gb_sets:is_element(M, NotRemoved) andalso 3937 not gb_sets:is_element(MFA, NotRemoved) of 3938 true -> 3939 add_warning(Line, Warning, St); 3940 false -> 3941 St 3942 end. 3943 3944-dialyzer({no_match, deprecated_type/5}). 3945 3946deprecated_type(L, M, N, As, St) -> 3947 NAs = length(As), 3948 case otp_internal:obsolete_type(M, N, NAs) of 3949 {deprecated, String} when is_list(String) -> 3950 case is_warn_enabled(deprecated_type, St) of 3951 true -> 3952 add_warning(L, {deprecated_type, {M,N,NAs}, String}, St); 3953 false -> 3954 St 3955 end; 3956 {removed, String} -> 3957 add_warning(L, {removed_type, {M,N,NAs}, String}, St); 3958 no -> 3959 St 3960 end. 3961 3962obsolete_guard({call,Line,{atom,Lr,F},As}, St0) -> 3963 Arity = length(As), 3964 case erl_internal:old_type_test(F, Arity) of 3965 false -> 3966 deprecated_function(Line, erlang, F, As, St0); 3967 true -> 3968 St = case is_warn_enabled(obsolete_guard, St0) of 3969 true -> 3970 add_warning(Lr, {obsolete_guard, {F, Arity}}, St0); 3971 false -> 3972 St0 3973 end, 3974 test_overriden_by_local(Lr, F, Arity, St) 3975 end; 3976obsolete_guard(_G, St) -> 3977 St. 3978 3979test_overriden_by_local(Line, OldTest, Arity, St) -> 3980 ModernTest = list_to_atom("is_"++atom_to_list(OldTest)), 3981 case is_local_function(St#lint.locals, {ModernTest, Arity}) of 3982 true -> 3983 add_error(Line, {obsolete_guard_overridden,OldTest}, St); 3984 false -> 3985 St 3986 end. 3987 3988%% keyword_warning(Line, Atom, State) -> State. 3989%% Add warning for atoms that will be reserved keywords in the future. 3990%% (Currently, no such keywords to warn for.) 3991keyword_warning(_Line, _A, St) -> St. 3992 3993%% format_function(Line, ModName, FuncName, [Arg], State) -> State. 3994%% Add warning for bad calls to io:fwrite/format functions. 3995 3996format_function(Line, M, F, As, St) -> 3997 case is_format_function(M, F) of 3998 true -> 3999 case St#lint.warn_format of 4000 Lev when Lev > 0 -> 4001 case check_format_1(As) of 4002 {warn,Level,Fmt,Fas} when Level =< Lev -> 4003 add_warning(Line, {format_error,{Fmt,Fas}}, St); 4004 _ -> St 4005 end; 4006 _Lev -> St 4007 end; 4008 false -> St 4009 end. 4010 4011is_format_function(io, fwrite) -> true; 4012is_format_function(io, format) -> true; 4013is_format_function(io_lib, fwrite) -> true; 4014is_format_function(io_lib, format) -> true; 4015is_format_function(M, F) when is_atom(M), is_atom(F) -> false. 4016 4017%% check_format_1([Arg]) -> ok | {warn,Level,Format,[Arg]}. 4018 4019check_format_1([Fmt]) -> 4020 check_format_1([Fmt,{nil,0}]); 4021check_format_1([Fmt,As]) -> 4022 check_format_2(Fmt, canonicalize_string(As)); 4023check_format_1([_Dev,Fmt,As]) -> 4024 check_format_1([Fmt,As]); 4025check_format_1(_As) -> 4026 {warn,1,"format call with wrong number of arguments",[]}. 4027 4028canonicalize_string({string,Line,Cs}) -> 4029 foldr(fun (C, T) -> {cons,Line,{integer,Line,C},T} end, {nil,Line}, Cs); 4030canonicalize_string(Term) -> 4031 Term. 4032 4033%% check_format_2([Arg]) -> ok | {warn,Level,Format,[Arg]}. 4034 4035check_format_2(Fmt, As) -> 4036 case Fmt of 4037 {string,_L,S} -> check_format_2a(S, As); 4038 {atom,_L,A} -> check_format_2a(atom_to_list(A), As); 4039 _ -> {warn,2,"format string not a textual constant",[]} 4040 end. 4041 4042check_format_2a(Fmt, As) -> 4043 case args_list(As) of 4044 true -> check_format_3(Fmt, As); 4045 false -> {warn,1,"format arguments not a list",[]}; 4046 maybe -> {warn,2,"format arguments perhaps not a list",[]} 4047 end. 4048 4049%% check_format_3(FormatString, [Arg]) -> ok | {warn,Level,Format,[Arg]}. 4050 4051check_format_3(Fmt, As) -> 4052 case check_format_string(Fmt) of 4053 {ok,Need} -> 4054 case args_length(As) of 4055 Len when length(Need) =:= Len -> ok; 4056 _Len -> {warn,1,"wrong number of arguments in format call",[]} 4057 end; 4058 {error,S} -> 4059 {warn,1,"format string invalid (~ts)",[S]} 4060 end. 4061 4062args_list({cons,_L,_H,T}) -> args_list(T); 4063%% Strange case: user has written something like [a | "bcd"]; pretend 4064%% we don't know: 4065args_list({string,_L,_Cs}) -> maybe; 4066args_list({nil,_L}) -> true; 4067args_list({atom,_,_}) -> false; 4068args_list({integer,_,_}) -> false; 4069args_list({float,_,_}) -> false; 4070args_list(_Other) -> maybe. 4071 4072args_length({cons,_L,_H,T}) -> 1 + args_length(T); 4073args_length({nil,_L}) -> 0. 4074 4075check_format_string(Fmt) -> 4076 extract_sequences(Fmt, []). 4077 4078extract_sequences(Fmt, Need0) -> 4079 case string:find(Fmt, [$~]) of 4080 nomatch -> {ok,lists:reverse(Need0)}; %That's it 4081 [$~|Fmt1] -> 4082 case extract_sequence(1, Fmt1, Need0) of 4083 {ok,Need1,Rest} -> extract_sequences(Rest, Need1); 4084 Error -> Error 4085 end 4086 end. 4087 4088extract_sequence(1, [$-,C|Fmt], Need) when C >= $0, C =< $9 -> 4089 extract_sequence_digits(1, Fmt, Need); 4090extract_sequence(1, [C|Fmt], Need) when C >= $0, C =< $9 -> 4091 extract_sequence_digits(1, Fmt, Need); 4092extract_sequence(1, [$-,$*|Fmt], Need) -> 4093 extract_sequence(2, Fmt, [int|Need]); 4094extract_sequence(1, [$*|Fmt], Need) -> 4095 extract_sequence(2, Fmt, [int|Need]); 4096extract_sequence(1, Fmt, Need) -> 4097 extract_sequence(2, Fmt, Need); 4098extract_sequence(2, [$.,C|Fmt], Need) when C >= $0, C =< $9 -> 4099 extract_sequence_digits(2, Fmt, Need); 4100extract_sequence(2, [$.,$*|Fmt], Need) -> 4101 extract_sequence(3, Fmt, [int|Need]); 4102extract_sequence(2, [$.|Fmt], Need) -> 4103 extract_sequence(3, Fmt, Need); 4104extract_sequence(2, Fmt, Need) -> 4105 extract_sequence(4, Fmt, Need); 4106extract_sequence(3, [$.,$*|Fmt], Need) -> 4107 extract_sequence(4, Fmt, [int|Need]); 4108extract_sequence(3, [$.,_|Fmt], Need) -> 4109 extract_sequence(4, Fmt, Need); 4110extract_sequence(3, Fmt, Need) -> 4111 extract_sequence(4, Fmt, Need); 4112extract_sequence(4, [$t, $l | Fmt], Need) -> 4113 extract_sequence(4, [$l, $t | Fmt], Need); 4114extract_sequence(4, [$t, $c | Fmt], Need) -> 4115 extract_sequence(5, [$c|Fmt], Need); 4116extract_sequence(4, [$t, $s | Fmt], Need) -> 4117 extract_sequence(5, [$s|Fmt], Need); 4118extract_sequence(4, [$t, $p | Fmt], Need) -> 4119 extract_sequence(5, [$p|Fmt], Need); 4120extract_sequence(4, [$t, $P | Fmt], Need) -> 4121 extract_sequence(5, [$P|Fmt], Need); 4122extract_sequence(4, [$t, $w | Fmt], Need) -> 4123 extract_sequence(5, [$w|Fmt], Need); 4124extract_sequence(4, [$t, $W | Fmt], Need) -> 4125 extract_sequence(5, [$W|Fmt], Need); 4126extract_sequence(4, [$t, C | _Fmt], _Need) -> 4127 {error,"invalid control ~t" ++ [C]}; 4128extract_sequence(4, [$l, $p | Fmt], Need) -> 4129 extract_sequence(5, [$p|Fmt], Need); 4130extract_sequence(4, [$l, $t, $p | Fmt], Need) -> 4131 extract_sequence(5, [$p|Fmt], Need); 4132extract_sequence(4, [$l, $P | Fmt], Need) -> 4133 extract_sequence(5, [$P|Fmt], Need); 4134extract_sequence(4, [$l, $t, $P | Fmt], Need) -> 4135 extract_sequence(5, [$P|Fmt], Need); 4136extract_sequence(4, [$l, $t, C | _Fmt], _Need) -> 4137 {error,"invalid control ~lt" ++ [C]}; 4138extract_sequence(4, [$l, C | _Fmt], _Need) -> 4139 {error,"invalid control ~l" ++ [C]}; 4140extract_sequence(4, Fmt, Need) -> 4141 extract_sequence(5, Fmt, Need); 4142extract_sequence(5, [C|Fmt], Need0) -> 4143 case control_type(C, Need0) of 4144 error -> {error,"invalid control ~" ++ [C]}; 4145 Need1 -> {ok,Need1,Fmt} 4146 end; 4147extract_sequence(_, [], _Need) -> {error,"truncated"}. 4148 4149extract_sequence_digits(Fld, [C|Fmt], Need) when C >= $0, C =< $9 -> 4150 extract_sequence_digits(Fld, Fmt, Need); 4151extract_sequence_digits(Fld, Fmt, Need) -> 4152 extract_sequence(Fld+1, Fmt, Need). 4153 4154control_type($~, Need) -> Need; 4155control_type($c, Need) -> [int|Need]; 4156control_type($f, Need) -> [float|Need]; 4157control_type($e, Need) -> [float|Need]; 4158control_type($g, Need) -> [float|Need]; 4159control_type($s, Need) -> [string|Need]; 4160control_type($w, Need) -> [term|Need]; 4161control_type($p, Need) -> [term|Need]; 4162control_type($W, Need) -> [int,term|Need]; %% Note: reversed 4163control_type($P, Need) -> [int,term|Need]; %% Note: reversed 4164control_type($b, Need) -> [term|Need]; 4165control_type($B, Need) -> [term|Need]; 4166control_type($x, Need) -> [string,term|Need]; %% Note: reversed 4167control_type($X, Need) -> [string,term|Need]; %% Note: reversed 4168control_type($+, Need) -> [term|Need]; 4169control_type($#, Need) -> [term|Need]; 4170control_type($n, Need) -> Need; 4171control_type($i, Need) -> [term|Need]; 4172control_type(_C, _Need) -> error. 4173 4174 4175%% Prebuild set of local functions (to override auto-import) 4176local_functions(Forms) -> 4177 gb_sets:from_list([ {Func,Arity} || {function,_,Func,Arity,_} <- Forms ]). 4178%% Predicate to find out if the function is locally defined 4179is_local_function(LocalSet,{Func,Arity}) -> 4180 gb_sets:is_element({Func,Arity},LocalSet). 4181%% Predicate to see if a function is explicitly imported 4182is_imported_function(ImportSet,{Func,Arity}) -> 4183 case orddict:find({Func,Arity}, ImportSet) of 4184 {ok,_Mod} -> true; 4185 error -> false 4186 end. 4187%% Predicate to see if a function is explicitly imported from the erlang module 4188is_imported_from_erlang(ImportSet,{Func,Arity}) -> 4189 case orddict:find({Func,Arity}, ImportSet) of 4190 {ok,erlang} -> true; 4191 _ -> false 4192 end. 4193%% Build set of functions where auto-import is explicitly suppressed 4194auto_import_suppressed(CompileFlags) -> 4195 case lists:member(no_auto_import, CompileFlags) of 4196 true -> 4197 all; 4198 false -> 4199 L0 = [ X || {no_auto_import,X} <- CompileFlags ], 4200 L1 = [ {Y,Z} || {Y,Z} <- lists:flatten(L0), is_atom(Y), is_integer(Z) ], 4201 gb_sets:from_list(L1) 4202 end. 4203%% Predicate to find out if autoimport is explicitly suppressed for a function 4204is_autoimport_suppressed(all,{_Func,_Arity}) -> 4205 true; 4206is_autoimport_suppressed(NoAutoSet,{Func,Arity}) -> 4207 gb_sets:is_element({Func,Arity},NoAutoSet). 4208%% Predicate to find out if a function specific bif-clash suppression (old deprecated) is present 4209bif_clash_specifically_disabled(St,{F,A}) -> 4210 lists:member({F,A},St#lint.nowarn_bif_clash). 4211 4212%% Predicate to find out if an autoimported guard_bif is not overriden in some way 4213%% Guard Bif without module name is disallowed if 4214%% * It is overridden by local function 4215%% * It is overridden by -import and that import is not of itself (i.e. from module erlang) 4216%% * The autoimport is suppressed or it's not reimported by -import directive 4217%% Otherwise it's OK (given that it's actually a guard bif and actually is autoimported) 4218no_guard_bif_clash(St,{F,A}) -> 4219 ( 4220 (not is_local_function(St#lint.locals,{F,A})) 4221 andalso 4222 ( 4223 (not is_imported_function(St#lint.imports,{F,A})) orelse 4224 is_imported_from_erlang(St#lint.imports,{F,A}) 4225 ) 4226 andalso 4227 ( 4228 (not is_autoimport_suppressed(St#lint.no_auto, {F,A})) orelse 4229 is_imported_from_erlang(St#lint.imports,{F,A}) 4230 ) 4231 ). 4232 4233%% maps_prepend(Key, Value, Map) -> Map. 4234 4235maps_prepend(Key, Value, Map) -> 4236 case maps:find(Key, Map) of 4237 {ok, Values} -> 4238 maps:put(Key, [Value|Values], Map); 4239 error -> 4240 maps:put(Key, [Value], Map) 4241 end. 4242