1%% ``Licensed under the Apache License, Version 2.0 (the "License"); 2%% you may not use this file except in compliance with the License. 3%% You may obtain a copy of the License at 4%% 5%% http://www.apache.org/licenses/LICENSE-2.0 6%% 7%% Unless required by applicable law or agreed to in writing, software 8%% distributed under the License is distributed on an "AS IS" BASIS, 9%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10%% See the License for the specific language governing permissions and 11%% limitations under the License. 12%% 13%% The Initial Developer of the Original Code is Ericsson Utvecklings AB. 14%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings 15%% AB. All Rights Reserved.'' 16%% 17%% $Id: core_lint.erl,v 1.1 2008/12/17 09:53:42 mikpe Exp $ 18%% Purpose : Do necessary checking of Core Erlang code. 19 20%% Check Core module for errors. Seeing this module is used in the 21%% compiler after optimisations wedone more checking than would be 22%% necessary after just parsing. Don't check all constructs. 23%% 24%% We check the following: 25%% 26%% All referred functions, called and exported, are defined. 27%% Format of export list. 28%% Format of attributes 29%% Used variables are defined. 30%% Variables in let and funs. 31%% Patterns case clauses. 32%% Values only as multiple values/variables/patterns. 33%% Return same number of values as requested 34%% Correct number of arguments 35%% 36%% Checks to add: 37%% 38%% Consistency of values/variables 39%% Consistency of function return values/calls. 40%% 41%% We keep the names defined variables and functions in a ordered list 42%% of variable names and function name/arity pairs. 43 44-module(core_lint). 45 46 47-export([module/1,module/2,format_error/1]). 48 49-import(lists, [reverse/1,all/2,foldl/3]). 50-import(ordsets, [add_element/2,is_element/2,union/2]). 51%-import(ordsets, [subtract/2]). 52 53-include("core_parse.hrl"). 54 55%% Define the lint state record. 56 57-record(lint, {module=[], %Current module 58 func=[], %Current function 59 errors=[], %Errors 60 warnings=[]}). %Warnings 61 62%% Keep track of defined 63-record(def, {vars=[], 64 funs=[]}). 65 66%%-deftype retcount() -> any | unknown | int(). 67 68%% format_error(Error) 69%% Return a string describing the error. 70 71format_error(invalid_exports) -> "invalid exports"; 72format_error(invalid_attributes) -> "invalid attributes"; 73format_error({undefined_function,{F,A}}) -> 74 io_lib:format("function ~w/~w undefined", [F,A]); 75format_error({undefined_function,{F1,A1},{F2,A2}}) -> 76 io_lib:format("undefined function ~w/~w in ~w/~w", [F1,A1,F2,A2]); 77format_error({illegal_expr,{F,A}}) -> 78 io_lib:format("illegal expression in ~w/~w", [F,A]); 79format_error({illegal_guard,{F,A}}) -> 80 io_lib:format("illegal guard expression in ~w/~w", [F,A]); 81format_error({illegal_pattern,{F,A}}) -> 82 io_lib:format("illegal pattern in ~w/~w", [F,A]); 83format_error({illegal_try,{F,A}}) -> 84 io_lib:format("illegal try expression in ~w/~w", [F,A]); 85format_error({pattern_mismatch,{F,A}}) -> 86 io_lib:format("pattern count mismatch in ~w/~w", [F,A]); 87format_error({return_mismatch,{F,A}}) -> 88 io_lib:format("return count mismatch in ~w/~w", [F,A]); 89format_error({arg_mismatch,{F,A}}) -> 90 io_lib:format("argument count mismatch in ~w/~w", [F,A]); 91format_error({unbound_var,N,{F,A}}) -> 92 io_lib:format("unbound variable ~s in ~w/~w", [N,F,A]); 93format_error({duplicate_var,N,{F,A}}) -> 94 io_lib:format("duplicate variable ~s in ~w/~w", [N,F,A]); 95format_error({not_var,{F,A}}) -> 96 io_lib:format("expecting variable in ~w/~w", [F,A]); 97format_error({not_pattern,{F,A}}) -> 98 io_lib:format("expecting pattern in ~w/~w", [F,A]); 99format_error({not_bs_pattern,{F,A}}) -> 100 io_lib:format("expecting bit syntax pattern in ~w/~w", [F,A]). 101 102%% module(CoreMod) -> 103%% module(CoreMod, [CompileOption]) -> 104%% {ok,[Warning]} | {error,[Error],[Warning]} 105 106module(M) -> module(M, []). 107 108module(#c_module{name=M,exports=Es,attrs=As,defs=Ds}, _Opts) -> 109 Defined = defined_funcs(Ds), 110 St0 = #lint{module=M#c_atom.val}, 111 St1 = check_exports(Es, St0), 112 St2 = check_attrs(As, St1), 113 St3 = module_defs(Ds, Defined, St2), 114 St4 = check_state(Es, Defined, St3), 115 return_status(St4). 116 117%% defined_funcs([FuncDef]) -> [Fname]. 118 119defined_funcs(Fs) -> 120 foldl(fun (#c_def{name=#c_fname{id=I,arity=A}}, Def) -> 121 add_element({I,A}, Def) 122 end, [], Fs). 123 124%% return_status(State) -> 125%% {ok,[Warning]} | {error,[Error],[Warning]} 126%% Pack errors and warnings properly and return ok | error. 127 128return_status(St) -> 129 Ws = reverse(St#lint.warnings), 130 case reverse(St#lint.errors) of 131 [] -> {ok,[{St#lint.module,Ws}]}; 132 Es -> {error,[{St#lint.module,Es}],[{St#lint.module,Ws}]} 133 end. 134 135%% add_error(ErrorDescriptor, State) -> State' 136%% add_warning(ErrorDescriptor, State) -> State' 137%% Note that we don't use line numbers here. 138 139add_error(E, St) -> St#lint{errors=[{none,core_lint,E}|St#lint.errors]}. 140 141%%add_warning(W, St) -> St#lint{warnings=[{none,core_lint,W}|St#lint.warnings]}. 142 143check_exports(Es, St) -> 144 case all(fun (#c_fname{id=Name,arity=Arity}) when 145 atom(Name), integer(Arity) -> true; 146 (_) -> false 147 end, Es) of 148 true -> St; 149 false -> add_error(invalid_exports, St) 150 end. 151 152check_attrs(As, St) -> 153 case all(fun (#c_def{name=#c_atom{},val=V}) -> core_lib:is_literal(V); 154 (_) -> false 155 end, As) of 156 true -> St; 157 false -> add_error(invalid_attributes, St) 158 end. 159 160check_state(Es, Defined, St) -> 161 foldl(fun (#c_fname{id=N,arity=A}, St1) -> 162 F = {N,A}, 163 case is_element(F, Defined) of 164 true -> St1; 165 false -> add_error({undefined_function,F}, St) 166 end 167 end, St, Es). 168% Undef = subtract(Es, Defined), 169% St1 = foldl(fun (F, St) -> add_error({undefined_function,F}, St) end, 170% St0, Undef), 171% St1. 172 173%% module_defs(CoreBody, Defined, State) -> State. 174 175module_defs(B, Def, St) -> 176 %% Set top level function name. 177 foldl(fun (Func, St0) -> 178 #c_fname{id=F,arity=A} = Func#c_def.name, 179 St1 = St0#lint{func={F,A}}, 180 function(Func, Def, St1) 181 end, St, B). 182 183%% functions([Fdef], Defined, State) -> State. 184 185functions(Fs, Def, St0) -> 186 foldl(fun (F, St) -> function(F, Def, St) end, St0, Fs). 187 188%% function(CoreFunc, Defined, State) -> State. 189 190function(#c_def{name=#c_fname{},val=B}, Def, St) -> 191 %% Body must be a fun! 192 case B of 193 #c_fun{} -> expr(B, Def, any, St); 194 _ -> add_error({illegal_expr,St#lint.func}, St) 195 end. 196 197%% body(Expr, Defined, RetCount, State) -> State. 198 199body(#c_values{es=Es}, Def, Rt, St) -> 200 return_match(Rt, length(Es), expr_list(Es, Def, St)); 201body(E, Def, Rt, St0) -> 202 St1 = expr(E, Def, Rt, St0), 203 case core_lib:is_simple_top(E) of 204 true -> return_match(Rt, 1, St1); 205 false -> St1 206 end. 207 208%% guard(Expr, Defined, State) -> State. 209%% Guards are boolean expressions with test wrapped in a protected. 210 211guard(Expr, Def, St) -> gexpr(Expr, Def, 1, St). 212 213%% guard_list([Expr], Defined, State) -> State. 214 215%% guard_list(Es, Def, St0) -> 216%% foldl(fun (E, St) -> guard(E, Def, St) end, St0, Es). 217 218%% gbody(Expr, Defined, RetCount, State) -> State. 219 220gbody(#c_values{es=Es}, Def, Rt, St) -> 221 return_match(Rt, length(Es), gexpr_list(Es, Def, St)); 222gbody(E, Def, Rt, St0) -> 223 St1 = gexpr(E, Def, Rt, St0), 224 case core_lib:is_simple_top(E) of 225 true -> return_match(Rt, 1, St1); 226 false -> St1 227 end. 228 229gexpr(#c_var{name=N}, Def, _Rt, St) -> expr_var(N, Def, St); 230gexpr(#c_int{}, _Def, _Rt, St) -> St; 231gexpr(#c_float{}, _Def, _Rt, St) -> St; 232gexpr(#c_atom{}, _Def, _Rt, St) -> St; 233gexpr(#c_char{}, _Def, _Rt, St) -> St; 234gexpr(#c_string{}, _Def, _Rt, St) -> St; 235gexpr(#c_nil{}, _Def, _Rt, St) -> St; 236gexpr(#c_cons{hd=H,tl=T}, Def, _Rt, St) -> 237 gexpr_list([H,T], Def, St); 238gexpr(#c_tuple{es=Es}, Def, _Rt, St) -> 239 gexpr_list(Es, Def, St); 240gexpr(#c_binary{segments=Ss}, Def, _Rt, St) -> 241 gbitstr_list(Ss, Def, St); 242gexpr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) -> 243 St1 = gexpr(Arg, Def, any, St0), %Ignore values 244 gbody(B, Def, Rt, St1); 245gexpr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) -> 246 St1 = gbody(Arg, Def, let_varcount(Vs), St0), %This is a guard body 247 {Lvs,St2} = variable_list(Vs, St1), 248 gbody(B, union(Lvs, Def), Rt, St2); 249gexpr(#c_call{module=#c_atom{val=erlang}, 250 name=#c_atom{}, 251 args=As}, Def, 1, St) -> 252 gexpr_list(As, Def, St); 253gexpr(#c_primop{name=N,args=As}, Def, _Rt, St0) when record(N, c_atom) -> 254 gexpr_list(As, Def, St0); 255gexpr(#c_try{arg=E,vars=[#c_var{name=X}],body=#c_var{name=X}, 256 evars=[#c_var{},#c_var{},#c_var{}],handler=#c_atom{val=false}}, 257 Def, Rt, St) -> 258 gbody(E, Def, Rt, St); 259gexpr(_, _, _, St) -> 260 add_error({illegal_guard,St#lint.func}, St). 261 262%% gexpr_list([Expr], Defined, State) -> State. 263 264gexpr_list(Es, Def, St0) -> 265 foldl(fun (E, St) -> gexpr(E, Def, 1, St) end, St0, Es). 266 267%% gbitstr_list([Elem], Defined, State) -> State. 268 269gbitstr_list(Es, Def, St0) -> 270 foldl(fun (E, St) -> gbitstr(E, Def, St) end, St0, Es). 271 272gbitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, St0) -> 273 St1 = bit_type(U, T, Fs, St0), 274 gexpr_list([V,S], Def, St1). 275 276%% expr(Expr, Defined, RetCount, State) -> State. 277 278expr(#c_var{name=N}, Def, _Rt, St) -> expr_var(N, Def, St); 279expr(#c_int{}, _Def, _Rt, St) -> St; 280expr(#c_float{}, _Def, _Rt, St) -> St; 281expr(#c_atom{}, _Def, _Rt, St) -> St; 282expr(#c_char{}, _Def, _Rt, St) -> St; 283expr(#c_string{}, _Def, _Rt, St) -> St; 284expr(#c_nil{}, _Def, _Rt, St) -> St; 285expr(#c_cons{hd=H,tl=T}, Def, _Rt, St) -> 286 expr_list([H,T], Def, St); 287expr(#c_tuple{es=Es}, Def, _Rt, St) -> 288 expr_list(Es, Def, St); 289expr(#c_binary{segments=Ss}, Def, _Rt, St) -> 290 bitstr_list(Ss, Def, St); 291expr(#c_fname{id=I,arity=A}, Def, _Rt, St) -> 292 expr_fname({I,A}, Def, St); 293expr(#c_fun{vars=Vs,body=B}, Def, Rt, St0) -> 294 {Vvs,St1} = variable_list(Vs, St0), 295 return_match(Rt, 1, body(B, union(Vvs, Def), any, St1)); 296expr(#c_seq{arg=Arg,body=B}, Def, Rt, St0) -> 297 St1 = expr(Arg, Def, any, St0), %Ignore values 298 body(B, Def, Rt, St1); 299expr(#c_let{vars=Vs,arg=Arg,body=B}, Def, Rt, St0) -> 300 St1 = body(Arg, Def, let_varcount(Vs), St0), %This is a body 301 {Lvs,St2} = variable_list(Vs, St1), 302 body(B, union(Lvs, Def), Rt, St2); 303expr(#c_letrec{defs=Fs,body=B}, Def0, Rt, St0) -> 304 Def1 = union(defined_funcs(Fs), Def0), %All defined stuff 305 St1 = functions(Fs, Def1, St0), 306 body(B, Def1, Rt, St1#lint{func=St0#lint.func}); 307expr(#c_case{arg=Arg,clauses=Cs}, Def, Rt, St0) -> 308 Pc = case_patcount(Cs), 309 St1 = body(Arg, Def, Pc, St0), 310 clauses(Cs, Def, Pc, Rt, St1); 311expr(#c_receive{clauses=Cs,timeout=T,action=A}, Def, Rt, St0) -> 312 St1 = expr(T, Def, 1, St0), 313 St2 = body(A, Def, Rt, St1), 314 clauses(Cs, Def, 1, Rt, St2); 315expr(#c_apply{op=Op,args=As}, Def, _Rt, St0) -> 316 St1 = apply_op(Op, Def, length(As), St0), 317 expr_list(As, Def, St1); 318expr(#c_call{module=M,name=N,args=As}, Def, _Rt, St0) -> 319 St1 = expr(M, Def, 1, St0), 320 St2 = expr(N, Def, 1, St1), 321 expr_list(As, Def, St2); 322expr(#c_primop{name=N,args=As}, Def, _Rt, St0) when record(N, c_atom) -> 323 expr_list(As, Def, St0); 324expr(#c_catch{body=B}, Def, Rt, St) -> 325 return_match(Rt, 1, body(B, Def, 1, St)); 326expr(#c_try{arg=A,vars=Vs,body=B,evars=Evs,handler=H}, Def, Rt, St0) -> 327 St1 = case length(Evs) of 328 2 -> St0; 329 _ -> add_error({illegal_try,St0#lint.func}, St0) 330 end, 331 St2 = body(A, Def, let_varcount(Vs), St1), 332 {Ns,St3} = variable_list(Vs, St2), 333 St4 = body(B, union(Ns, Def), Rt, St3), 334 {Ens,St5} = variable_list(Evs, St4), 335 body(H, union(Ens, Def), Rt, St5); 336expr(_, _, _, St) -> 337 %%io:fwrite("clint: ~p~n", [Other]), 338 add_error({illegal_expr,St#lint.func}, St). 339 340%% expr_list([Expr], Defined, State) -> State. 341 342expr_list(Es, Def, St0) -> 343 foldl(fun (E, St) -> expr(E, Def, 1, St) end, St0, Es). 344 345%% bitstr_list([Elem], Defined, State) -> State. 346 347bitstr_list(Es, Def, St0) -> 348 foldl(fun (E, St) -> bitstr(E, Def, St) end, St0, Es). 349 350bitstr(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, St0) -> 351 St1 = bit_type(U, T, Fs, St0), 352 expr_list([V,S], Def, St1). 353 354%% apply_op(Op, Defined, ArgCount, State) -> State. 355%% A apply op is either an fname or an expression. 356 357apply_op(#c_fname{id=I,arity=A}, Def, Ac, St0) -> 358 St1 = expr_fname({I,A}, Def, St0), 359 arg_match(Ac, A, St1); 360apply_op(E, Def, _, St) -> expr(E, Def, 1, St). %Hard to check 361 362%% expr_var(VarName, Defined, State) -> State. 363 364expr_var(N, Def, St) -> 365 case is_element(N, Def) of 366 true -> St; 367 false -> add_error({unbound_var,N,St#lint.func}, St) 368 end. 369 370%% expr_fname(Fname, Defined, State) -> State. 371 372expr_fname(Fname, Def, St) -> 373 case is_element(Fname, Def) of 374 true -> St; 375 false -> add_error({undefined_function,Fname,St#lint.func}, St) 376 end. 377 378%% let_varcount([Var]) -> int(). 379 380let_varcount([]) -> any; %Ignore values 381let_varcount(Es) -> length(Es). 382 383%% case_patcount([Clause]) -> int(). 384 385case_patcount([#c_clause{pats=Ps}|_]) -> length(Ps). 386 387%% clauses([Clause], Defined, PatCount, RetCount, State) -> State. 388 389clauses(Cs, Def, Pc, Rt, St0) -> 390 foldl(fun (C, St) -> clause(C, Def, Pc, Rt, St) end, St0, Cs). 391 392%% clause(Clause, Defined, PatCount, RetCount, State) -> State. 393 394clause(#c_clause{pats=Ps,guard=G,body=B}, Def0, Pc, Rt, St0) -> 395 St1 = pattern_match(Pc, length(Ps), St0), 396 {Pvs,St2} = pattern_list(Ps, Def0, St1), 397 Def1 = union(Pvs, Def0), 398 St3 = guard(G, Def1, St2), 399 body(B, Def1, Rt, St3). 400 401%% variable(Var, [PatVar], State) -> {[VarName],State}. 402 403variable(#c_var{name=N}, Ps, St) -> 404 case is_element(N, Ps) of 405 true -> {[],add_error({duplicate_var,N,St#lint.func}, St)}; 406 false -> {[N],St} 407 end; 408variable(_, Def, St) -> {Def,add_error({not_var,St#lint.func}, St)}. 409 410%% variable_list([Var], State) -> {[Var],State}. 411%% variable_list([Var], [PatVar], State) -> {[Var],State}. 412 413variable_list(Vs, St) -> variable_list(Vs, [], St). 414 415variable_list(Vs, Ps, St) -> 416 foldl(fun (V, {Ps0,St0}) -> 417 {Vvs,St1} = variable(V, Ps0, St0), 418 {union(Vvs, Ps0),St1} 419 end, {Ps,St}, Vs). 420 421%% pattern(Pattern, Defined, State) -> {[PatVar],State}. 422%% pattern(Pattern, Defined, [PatVar], State) -> {[PatVar],State}. 423%% Patterns are complicated by sizes in binaries. These are pure 424%% input variables which create no bindings. We, therefor, need to 425%% carry around the original defined variables to get the correct 426%% handling. 427 428%% pattern(P, Def, St) -> pattern(P, Def, [], St). 429 430pattern(#c_var{name=N}, Def, Ps, St) -> 431 pat_var(N, Def, Ps, St); 432pattern(#c_int{}, _Def, Ps, St) -> {Ps,St}; 433pattern(#c_float{}, _Def, Ps, St) -> {Ps,St}; 434pattern(#c_atom{}, _Def, Ps, St) -> {Ps,St}; 435pattern(#c_char{}, _Def, Ps, St) -> {Ps,St}; 436pattern(#c_string{}, _Def, Ps, St) -> {Ps,St}; 437pattern(#c_nil{}, _Def, Ps, St) -> {Ps,St}; 438pattern(#c_cons{hd=H,tl=T}, Def, Ps, St) -> 439 pattern_list([H,T], Def, Ps, St); 440pattern(#c_tuple{es=Es}, Def, Ps, St) -> 441 pattern_list(Es, Def, Ps, St); 442pattern(#c_binary{segments=Ss}, Def, Ps, St) -> 443 pat_bin(Ss, Def, Ps, St); 444pattern(#c_alias{var=V,pat=P}, Def, Ps, St0) -> 445 {Vvs,St1} = variable(V, Ps, St0), 446 pattern(P, Def, union(Vvs, Ps), St1); 447pattern(_, _, Ps, St) -> {Ps,add_error({not_pattern,St#lint.func}, St)}. 448 449pat_var(N, _Def, Ps, St) -> 450 case is_element(N, Ps) of 451 true -> {Ps,add_error({duplicate_var,N,St#lint.func}, St)}; 452 false -> {add_element(N, Ps),St} 453 end. 454 455%% pat_bin_list([Elem], Defined, [PatVar], State) -> {[PatVar],State}. 456 457pat_bin(Es, Def, Ps0, St0) -> 458 foldl(fun (E, {Ps,St}) -> pat_segment(E, Def, Ps, St) end, {Ps0,St0}, Es). 459 460pat_segment(#c_bitstr{val=V,size=S,unit=U,type=T,flags=Fs}, Def, Ps, St0) -> 461 St1 = bit_type(U, T, Fs, St0), 462 St2 = pat_bit_expr(S, T, Def, St1), 463 pattern(V, Def, Ps, St2); 464pat_segment(_, _, Ps, St) -> 465 {Ps,add_error({not_bs_pattern,St#lint.func}, St)}. 466 467%% pat_bit_expr(SizePat, Type, Defined, State) -> State. 468%% Check the Size pattern, this is an input! Be a bit tough here. 469 470pat_bit_expr(#c_int{val=I}, _, _, St) when I >= 0 -> St; 471pat_bit_expr(#c_var{name=N}, _, Def, St) -> 472 expr_var(N, Def, St); 473pat_bit_expr(#c_atom{val=all}, binary, _Def, St) -> St; 474pat_bit_expr(_, _, _, St) -> 475 add_error({illegal_expr,St#lint.func}, St). 476 477bit_type(Unit, Type, Flags, St) -> 478 U = core_lib:literal_value(Unit), 479 T = core_lib:literal_value(Type), 480 Fs = core_lib:literal_value(Flags), 481 case erl_bits:set_bit_type(default, [T,{unit,U}|Fs]) of 482 {ok,_,_} -> St; 483 {error,E} -> add_error({E,St#lint.func}, St) 484 end. 485 486%% pattern_list([Var], Defined, State) -> {[PatVar],State}. 487%% pattern_list([Var], Defined, [PatVar], State) -> {[PatVar],State}. 488 489pattern_list(Pats, Def, St) -> pattern_list(Pats, Def, [], St). 490 491pattern_list(Pats, Def, Ps0, St0) -> 492 foldl(fun (P, {Ps,St}) -> pattern(P, Def, Ps, St) end, {Ps0,St0}, Pats). 493 494%% pattern_match(Required, Supplied, State) -> State. 495%% Check that the required number of patterns match the supplied. 496 497pattern_match(N, N, St) -> St; 498pattern_match(_Req, _Sup, St) -> 499 add_error({pattern_mismatch,St#lint.func}, St). 500 501%% return_match(Required, Supplied, State) -> State. 502%% Check that the required number of return values match the supplied. 503 504return_match(any, _Sup, St) -> St; 505return_match(_Req, unknown, St) -> St; 506return_match(N, N, St) -> St; 507return_match(_Req, _Sup, St) -> 508 add_error({return_mismatch,St#lint.func}, St). 509 510%% arg_match(Required, Supplied, State) -> State. 511 512arg_match(_Req, unknown, St) -> St; 513arg_match(N, N, St) -> St; 514arg_match(_Req, _Sup, St) -> 515 add_error({arg_mismatch,St#lint.func}, St). 516