Coccinelle release 0.2.5-rc7.
[bpt/coccinelle.git] / parsing_c / type_annoter_c.ml
CommitLineData
0708f913 1(* Yoann Padioleau
ae4735db
C
2 *
3 * Copyright (C) 2010, University of Copenhagen DIKU and INRIA.
4 * Copyright (C) 2007, 2008 Ecole des Mines de Nantes,
0708f913 5 * Copyright (C) 2009 University of Urbana Champaign
34e49164
C
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License (GPL)
9 * version 2 as published by the Free Software Foundation.
ae4735db 10 *
34e49164
C
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * file license.txt for more details.
15 *)
91eba41f 16
34e49164
C
17open Common
18
19open Ast_c
20
21module Lib = Lib_parsing_c
22
23(*****************************************************************************)
91eba41f
C
24(* Prelude *)
25(*****************************************************************************)
ae4735db 26(* History:
91eba41f
C
27 * - Done a first type checker in 2002, cf typing-semantic/, but
28 * was assuming that have all type info, and so was assuming had called
29 * cpp and everything was right.
ae4735db 30 * - Wrote this file, in 2006?, as we added pattern matching on type
91eba41f 31 * in coccinelle. Partial type annotater.
ae4735db 32 * - Julia extended it in 2008? to have localvar/notlocalvar and
91eba41f 33 * test/notest information, again used by coccinelle.
ae4735db 34 * - I extended it in Fall 2008 to have more type information for the
91eba41f
C
35 * global analysis. I also added some optimisations to process
36 * included code faster.
ae4735db
C
37 *
38 *
91eba41f
C
39 * Design choices. Can either do:
40 * - a kind of inferer
41 * - can first do a simple inferer, that just pass context
42 * - then a real inferer, managing partial info.
34e49164
C
43 * type context = fullType option
44 *
45 * - extract the information from the .h files
91eba41f 46 * (so no inference at all needed)
ae4735db 47 *
91eba41f
C
48 * Difference with julia's code in parsing_cocci/type_infer.ml:
49 * - She handles just the variable namespace. She does not type
50 * field access or enum or macros. This is because cocci programs are
51 * usually simple and have no structure definition or macro definitions
52 * that we need to type anyway.
53 * - She does more propagation.
ae4735db 54 * - She does not have to handle the typedef isomorphism which force me
91eba41f
C
55 * to use those typedef_fix and type_unfold_one_step
56 * - She does not handle I think the function pointer C isomorphism.
ae4735db
C
57 *
58 * - She has a cleaner type_cocci without any info. In my case
91eba41f 59 * I need to do those ugly al_type, or generate fake infos.
ae4735db 60 * - She has more compact code. Perhaps because she does not have to
91eba41f
C
61 * handle the extra exp_info that she added on me :) So I need those
62 * do_with_type, make_info_xxx, etc.
ae4735db 63 *
91eba41f
C
64 * Note: if need to debug this annotater, use -show_trace_profile, it can
65 * help. You can also set the typedef_debug flag below.
ae4735db
C
66 *
67 *
68 *
34e49164 69 * todo: expression contain types, and statements, which in turn can contain
ae4735db 70 * expression, so need recurse. Need define an annote_statement and
34e49164 71 * annotate_type.
ae4735db 72 *
34e49164
C
73 * todo: how deal with typedef isomorphisms ? How store them in Ast_c ?
74 * store all posible variations in ast_c ? a list of type instead of just
75 * the type ?
ae4735db 76 *
0708f913 77 * todo: how to handle multiple possible definitions for entities like
ae4735db 78 * struct or typedefs ? Because of ifdef, we should store list of
0708f913 79 * possibilities sometimes.
ae4735db 80 *
34e49164 81 * todo: define a new type ? like type_cocci ? where have a bool ?
ae4735db
C
82 *
83 * semi: How handle scope ? When search for type of field, we return
34e49164 84 * a type, but this type makes sense only in a certain scope.
ae4735db 85 * We could add a tag to each typedef, structUnionName to differentiate
34e49164
C
86 * them and also associate in ast_c to the type the scope
87 * of this type, the env that were used to define this type.
ae4735db
C
88 *
89 * todo: handle better the search in previous env, the env'. Cf the
91eba41f
C
90 * termination problem in typedef_fix when I was searching in the same
91 * env.
ae4735db 92 *
34e49164
C
93 *)
94
95(*****************************************************************************)
96(* Wrappers *)
97(*****************************************************************************)
708f4980 98let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_type
0708f913 99
34e49164
C
100(*****************************************************************************)
101(* Environment *)
102(*****************************************************************************)
103
91eba41f 104(* The different namespaces from stdC manual:
ae4735db 105 *
34e49164 106 * You introduce two new name spaces with every block that you write.
ae4735db
C
107 *
108 * One name space includes all
109 * - functions,
110 * - objects,
91eba41f 111 * - type definitions,
ae4735db
C
112 * - and enumeration constants
113 * that you declare or define within the block.
114 *
115 * The other name space includes all
116 * - enumeration,
117 * - structure,
118 * - and union
91eba41f 119 * *tags* that you define within the block.
ae4735db 120 *
34e49164
C
121 * You introduce a new member name space with every structure or union
122 * whose content you define. You identify a member name space by the
123 * type of left operand that you write for a member selection
124 * operator, as in x.y or p->y. A member name space ends with the end
125 * of the block in which you declare it.
ae4735db 126 *
34e49164
C
127 * You introduce a new goto label name space with every function
128 * definition you write. Each goto label name space ends with its
129 * function definition.
130 *)
131
132(* But I don't try to do a type-checker, I try to "resolve" type of var
133 * so don't need make difference between namespaces here.
ae4735db
C
134 *
135 * But, why not make simply a (string, kindstring) assoc ?
34e49164
C
136 * Because we dont want that a variable shadow a struct definition, because
137 * they are still in 2 different namespace. But could for typedef,
138 * because VarOrFunc and Typedef are in the same namespace.
139 * But could do a record as in c_info.ml
140 *)
141
142
91eba41f 143(* This type contains all "ident" like notion of C. Each time in Ast_c
ae4735db 144 * you have a string type (as in expression, function name, fields)
91eba41f 145 * then you need to manage the scope of this ident.
ae4735db 146 *
91eba41f
C
147 * The wrap for StructUnionNameDef contain the whole ii, the i for
148 * the string, the structUnion and the structType.
ae4735db 149 *
91eba41f
C
150 * Put Macro here ? after all the scoping rules for cpp macros is different
151 * and so does not vanish after the closing '}'.
ae4735db 152 *
91eba41f 153 * todo: EnumDef
34e49164 154 *)
ae4735db 155type namedef =
34e49164 156 | VarOrFunc of string * Ast_c.exp_type
91eba41f
C
157 | EnumConstant of string * string option
158
708f4980 159 (* also used for macro type aliases *)
91eba41f
C
160 | TypeDef of string * fullType
161 (* the structType contains nested "idents" with struct scope *)
34e49164 162 | StructUnionNameDef of string * (structUnion * structType) wrap
34e49164 163
91eba41f 164 (* cppext: *)
b1b2de81 165 | Macro of string * (define_kind * define_val)
91eba41f
C
166
167
168(* Because have nested scope, have nested list, hence the list list.
169 *
170 * opti? use a hash to accelerate ? hmm but may have some problems
171 * with hash to handle recursive lookup. For instance for the typedef
ae4735db
C
172 * example where have mutually recursive definition of the type,
173 * we must take care to not loop by starting the second search
174 * from the previous environment. With the list scheme in
91eba41f
C
175 * lookup_env below it's quite easy to do. With hash it may be
176 * more complicated.
177*)
ae4735db 178type environment = namedef list list
34e49164 179
91eba41f
C
180
181(* ------------------------------------------------------------ *)
ae4735db
C
182(* can be modified by the init_env function below, by
183 * the file environment_unix.h
91eba41f
C
184 *)
185let initial_env = ref [
186 [VarOrFunc("NULL",
187 (Lib.al_type (Parse_c.type_of_string "void *"),
188 Ast_c.NotLocalVar));
189
ae4735db 190 (*
91eba41f
C
191 VarOrFunc("malloc",
192 (Lib.al_type(Parse_c.type_of_string "void* (*)(int size)"),
193 Ast_c.NotLocalVar));
194 VarOrFunc("free",
195 (Lib.al_type(Parse_c.type_of_string "void (*)(void *ptr)"),
196 Ast_c.NotLocalVar));
197 *)
198 ]
34e49164
C
199]
200
201
ae4735db 202let typedef_debug = ref false
91eba41f
C
203
204
205(* ------------------------------------------------------------ *)
206(* generic, lookup and also return remaining env for further lookup *)
ae4735db
C
207let rec lookup_env2 f env =
208 match env with
34e49164 209 | [] -> raise Not_found
91eba41f 210 | []::zs -> lookup_env2 f zs
ae4735db 211 | (x::xs)::zs ->
91eba41f
C
212 (match f x with
213 | None -> lookup_env2 f (xs::zs)
34e49164 214 | Some y -> y, xs::zs
91eba41f 215 )
ae4735db 216let lookup_env a b =
91eba41f
C
217 Common.profile_code "TAC.lookup_env" (fun () -> lookup_env2 a b)
218
219
220
ae4735db
C
221let member_env lookupf env =
222 try
91eba41f
C
223 let _ = lookupf env in
224 true
225 with Not_found -> false
226
227
228
229
230(* ------------------------------------------------------------ *)
34e49164 231
34e49164 232
ae4735db 233let lookup_var s env =
34e49164 234 let f = function
b1b2de81 235 | VarOrFunc (s2, typ) -> if s2 =$= s then Some typ else None
34e49164
C
236 | _ -> None
237 in
238 lookup_env f env
239
ae4735db 240let lookup_typedef s env =
91eba41f 241 if !typedef_debug then pr2 ("looking for: " ^ s);
34e49164 242 let f = function
b1b2de81 243 | TypeDef (s2, typ) -> if s2 =$= s then Some typ else None
34e49164
C
244 | _ -> None
245 in
246 lookup_env f env
247
248let lookup_structunion (_su, s) env =
249 let f = function
b1b2de81 250 | StructUnionNameDef (s2, typ) -> if s2 =$= s then Some typ else None
34e49164
C
251 | _ -> None
252 in
253 lookup_env f env
254
ae4735db 255let lookup_macro s env =
91eba41f 256 let f = function
b1b2de81 257 | Macro (s2, typ) -> if s2 =$= s then Some typ else None
91eba41f
C
258 | _ -> None
259 in
260 lookup_env f env
261
ae4735db 262let lookup_enum s env =
91eba41f 263 let f = function
b1b2de81 264 | EnumConstant (s2, typ) -> if s2 =$= s then Some typ else None
91eba41f
C
265 | _ -> None
266 in
267 lookup_env f env
268
269
ae4735db 270let lookup_typedef a b =
91eba41f
C
271 Common.profile_code "TAC.lookup_typedef" (fun () -> lookup_typedef a b)
272
273
34e49164
C
274
275(*****************************************************************************)
276(* "type-lookup" *)
277(*****************************************************************************)
278
279(* find_final_type is used to know to what type a field correspond in
280 * x.foo. Sometimes the type of x is a typedef or a structName in which
281 * case we must look in environment to find the complete type, here
282 * structUnion that contains the information.
ae4735db 283 *
34e49164
C
284 * Because in C one can redefine in nested blocks some typedefs,
285 * struct, or variables, we have a static scoping resolving process.
286 * So, when we look for the type of a var, if this var is in an
287 * enclosing block, then maybe its type refer to a typdef of this
288 * enclosing block, so must restart the "type-resolving" of this
289 * typedef from this enclosing block, not from the bottom. So our
290 * "resolving-type functions" take an env and also return an env from
291 * where the next search must be performed. *)
292
293(*
ae4735db 294let rec find_final_type ty env =
34e49164 295
ae4735db 296 match Ast_c.unwrap_typeC ty with
34e49164 297 | BaseType x -> (BaseType x) +> Ast_c.rewrap_typeC ty
ae4735db 298
34e49164
C
299 | Pointer t -> (Pointer (find_final_type t env)) +> Ast_c.rewrap_typeC ty
300 | Array (e, t) -> Array (e, find_final_type t env) +> Ast_c.rewrap_typeC ty
ae4735db 301
34e49164 302 | StructUnion (sopt, su) -> StructUnion (sopt, su) +> Ast_c.rewrap_typeC ty
ae4735db 303
34e49164
C
304 | FunctionType t -> (FunctionType t) (* todo ? *) +> Ast_c.rewrap_typeC ty
305 | Enum (s, enumt) -> (Enum (s, enumt)) (* todo? *) +> Ast_c.rewrap_typeC ty
306 | EnumName s -> (EnumName s) (* todo? *) +> Ast_c.rewrap_typeC ty
ae4735db
C
307
308 | StructUnionName (su, s) ->
309 (try
34e49164
C
310 let ((structtyp,ii), env') = lookup_structunion (su, s) env in
311 Ast_c.nQ, (StructUnion (Some s, structtyp), ii)
ae4735db 312 (* old: +> Ast_c.rewrap_typeC ty
34e49164
C
313 * but must wrap with good ii, otherwise pretty_print_c
314 * will be lost and raise some Impossible
315 *)
ae4735db 316 with Not_found ->
34e49164
C
317 ty
318 )
ae4735db
C
319
320 | TypeName s ->
321 (try
34e49164
C
322 let (t', env') = lookup_typedef s env in
323 find_final_type t' env'
ae4735db 324 with Not_found ->
34e49164
C
325 ty
326 )
ae4735db 327
34e49164
C
328 | ParenType t -> find_final_type t env
329 | Typeof e -> failwith "typeof"
ae4735db 330*)
34e49164
C
331
332
333
334
91eba41f 335(* ------------------------------------------------------------ *)
ae4735db 336let rec type_unfold_one_step ty env =
34e49164 337
ae4735db 338 match Ast_c.unwrap_typeC ty with
f59c9fb7 339 | NoType -> ty
91eba41f
C
340 | BaseType x -> ty
341 | Pointer t -> ty
342 | Array (e, t) -> ty
343
34e49164 344 | StructUnion (sopt, su, fields) -> ty
ae4735db 345
91eba41f 346 | FunctionType t -> ty
34e49164 347 | Enum (s, enumt) -> ty
91eba41f
C
348
349 | EnumName s -> ty (* todo: look in env when will have EnumDef *)
ae4735db
C
350
351 | StructUnionName (su, s) ->
352 (try
34e49164 353 let (((su,fields),ii), env') = lookup_structunion (su, s) env in
708f4980 354 Ast_c.mk_ty (StructUnion (su, Some s, fields)) ii
ae4735db 355 (* old: +> Ast_c.rewrap_typeC ty
34e49164
C
356 * but must wrap with good ii, otherwise pretty_print_c
357 * will be lost and raise some Impossible
358 *)
ae4735db 359 with Not_found ->
34e49164
C
360 ty
361 )
ae4735db
C
362
363 | TypeName (name, _typ) ->
b1b2de81 364 let s = Ast_c.str_of_name name in
ae4735db 365 (try
91eba41f 366 if !typedef_debug then pr2 "type_unfold_one_step: lookup_typedef";
34e49164
C
367 let (t', env') = lookup_typedef s env in
368 type_unfold_one_step t' env'
ae4735db 369 with Not_found ->
34e49164
C
370 ty
371 )
ae4735db 372
34e49164 373 | ParenType t -> type_unfold_one_step t env
ae4735db 374 | TypeOfExpr e ->
34e49164
C
375 pr2_once ("Type_annoter: not handling typeof");
376 ty
377 | TypeOfType t -> type_unfold_one_step t env
378
379
380
34e49164
C
381
382
383
34e49164
C
384
385
386
ae4735db 387(* normalizer. can be seen as the opposite of the previous function as
0708f913
C
388 * we "fold" at least for the structUnion. Should return something that
389 * Type_c.is_completed_fullType likes, something that makes it easier
390 * for the programmer to work on, that has all the needed information
391 * for most tasks.
91eba41f 392 *)
ae4735db
C
393let rec typedef_fix ty env =
394 match Ast_c.unwrap_typeC ty with
f59c9fb7
C
395 | NoType ->
396 ty
ae4735db 397 | BaseType x ->
91eba41f 398 ty
ae4735db 399 | Pointer t ->
91eba41f 400 Pointer (typedef_fix t env) +> Ast_c.rewrap_typeC ty
ae4735db 401 | Array (e, t) ->
91eba41f 402 Array (e, typedef_fix t env) +> Ast_c.rewrap_typeC ty
ae4735db
C
403 | StructUnion (su, sopt, fields) ->
404 (* normalize, fold.
405 * todo? but what if correspond to a nested struct def ?
91eba41f
C
406 *)
407 Type_c.structdef_to_struct_name ty
ae4735db 408 | FunctionType ft ->
34e49164 409 (FunctionType ft) (* todo ? *) +> Ast_c.rewrap_typeC ty
ae4735db 410 | Enum (s, enumt) ->
34e49164 411 (Enum (s, enumt)) (* todo? *) +> Ast_c.rewrap_typeC ty
ae4735db 412 | EnumName s ->
34e49164
C
413 (EnumName s) (* todo? *) +> Ast_c.rewrap_typeC ty
414
415 (* we prefer StructUnionName to StructUnion when it comes to typed metavar *)
416 | StructUnionName (su, s) -> ty
91eba41f
C
417
418 (* keep the typename but complete with more information *)
ae4735db 419 | TypeName (name, typ) ->
b1b2de81 420 let s = Ast_c.str_of_name name in
0708f913 421 (match typ with
ae4735db 422 | Some _ ->
0708f913
C
423 pr2 ("typedef value already there:" ^ s);
424 ty
ae4735db 425 | None ->
0708f913 426 (try
91eba41f 427 if !typedef_debug then pr2 "typedef_fix: lookup_typedef";
34e49164 428 let (t', env') = lookup_typedef s env in
91eba41f
C
429
430 (* bugfix: termination bug if use env instead of env' below, because
0708f913 431 * can have some weird mutually recursive typedef which
91eba41f
C
432 * each new type alias search for its mutual def.
433 *)
b1b2de81 434 TypeName (name, Some (typedef_fix t' env')) +> Ast_c.rewrap_typeC ty
ae4735db 435 with Not_found ->
34e49164 436 ty
0708f913
C
437 ))
438
91eba41f 439 (* remove paren for better matching with typed metavar. kind of iso again *)
ae4735db 440 | ParenType t ->
91eba41f 441 typedef_fix t env
ae4735db 442 | TypeOfExpr e ->
34e49164
C
443 pr2_once ("Type_annoter: not handling typeof");
444 ty
445
ae4735db 446 | TypeOfType t ->
91eba41f
C
447 typedef_fix t env
448
449
450(*****************************************************************************)
451(* Helpers, part 1 *)
452(*****************************************************************************)
453
ae4735db 454let type_of_s2 s =
91eba41f 455 (Lib.al_type (Parse_c.type_of_string s))
ae4735db 456let type_of_s a =
91eba41f
C
457 Common.profile_code "Type_c.type_of_s" (fun () -> type_of_s2 a)
458
459
460(* pad: pb on:
461 * /home/pad/software-os-src2/freebsd/contrib/ipfilter/netinet/ip_fil_freebsd.c
462 * because in the code there is:
463 * static iss_seq_off = 0;
464 * which in the parser was generating a default int without a parse_info.
465 * I now add a fake parse_info for such default int so no more failwith
466 * normally.
467 *)
91eba41f 468
ae4735db 469let rec is_simple_expr expr =
91eba41f 470 match Ast_c.unwrap_expr expr with
ae4735db
C
471 (* todo? handle more special cases ? *)
472
473 | Ident _ ->
91eba41f 474 true
ae4735db 475 | Constant (_) ->
91eba41f 476 true
ae4735db 477 | Unary (op, e) ->
91eba41f 478 true
ae4735db 479 | Binary (e1, op, e2) ->
91eba41f 480 true
ae4735db 481 | Cast (t, e) ->
91eba41f
C
482 true
483 | ParenExpr (e) -> is_simple_expr e
484
485 | _ -> false
486
487(*****************************************************************************)
488(* Typing rules *)
489(*****************************************************************************)
490(* now in type_c.ml *)
491
492
34e49164
C
493
494(*****************************************************************************)
495(* (Semi) Globals, Julia's style *)
496(*****************************************************************************)
497
498(* opti: cache ? use hash ? *)
91eba41f 499let _scoped_env = ref !initial_env
34e49164
C
500
501(* memoise unnanoted var, to avoid too much warning messages *)
502let _notyped_var = ref (Hashtbl.create 100)
503
ae4735db 504let new_scope() = _scoped_env := []::!_scoped_env
34e49164
C
505let del_scope() = _scoped_env := List.tl !_scoped_env
506
ae4735db 507let do_in_new_scope f =
34e49164
C
508 begin
509 new_scope();
510 let res = f() in
511 del_scope();
512 res
513 end
514
515let add_in_scope namedef =
516 let (current, older) = Common.uncons !_scoped_env in
517 _scoped_env := (namedef::current)::older
518
91eba41f
C
519
520(* ------------------------------------------------------------ *)
521
34e49164
C
522(* sort of hackish... *)
523let islocal info =
b1b2de81 524 if List.length (!_scoped_env) =|= List.length !initial_env
34e49164
C
525 then Ast_c.NotLocalVar
526 else Ast_c.LocalVar info
527
91eba41f 528(* ------------------------------------------------------------ *)
ae4735db 529(* the warning argument is here to allow some binding to overwrite an
91eba41f
C
530 * existing one. With function, we first have the prototype and then the def,
531 * and the def binding with the same string is not an error.
ae4735db 532 *
34e49164 533 * todo?: but if we define two times the same function, then we will not
ae4735db 534 * detect it :( it would require to make a diff between adding a binding
34e49164 535 * from a prototype and from a definition.
ae4735db
C
536 *
537 * opti: disabling the check_annotater flag have some important
91eba41f 538 * performance benefit.
ae4735db 539 *
34e49164 540 *)
ae4735db 541let add_binding2 namedef warning =
34e49164
C
542 let (current_scope, _older_scope) = Common.uncons !_scoped_env in
543
91eba41f 544 if !Flag_parsing_c.check_annotater then begin
34e49164 545 (match namedef with
ae4735db 546 | VarOrFunc (s, typ) ->
91eba41f
C
547 if Hashtbl.mem !_notyped_var s
548 then pr2 ("warning: found typing information for a variable that was" ^
549 "previously unknown:" ^ s);
550 | _ -> ()
551 );
ae4735db
C
552
553 let (memberf, s) =
91eba41f 554 (match namedef with
ae4735db 555 | VarOrFunc (s, typ) ->
91eba41f 556 member_env (lookup_var s), s
ae4735db 557 | TypeDef (s, typ) ->
91eba41f 558 member_env (lookup_typedef s), s
ae4735db 559 | StructUnionNameDef (s, (su, typ)) ->
91eba41f 560 member_env (lookup_structunion (su, s)), s
ae4735db 561 | Macro (s, body) ->
91eba41f 562 member_env (lookup_macro s), s
ae4735db 563 | EnumConstant (s, body) ->
91eba41f
C
564 member_env (lookup_enum s), s
565 ) in
ae4735db 566
91eba41f 567 if memberf [current_scope] && warning
ae4735db 568 then pr2 ("Type_annoter: warning, " ^ s ^
91eba41f 569 " is already in current binding" ^ "\n" ^
0708f913 570 " so there is a weird shadowing");
91eba41f 571 end;
34e49164 572 add_in_scope namedef
91eba41f 573
ae4735db 574let add_binding namedef warning =
91eba41f 575 Common.profile_code "TAC.add_binding" (fun () -> add_binding2 namedef warning)
ae4735db 576
34e49164 577
91eba41f 578
34e49164 579(*****************************************************************************)
91eba41f 580(* Helpers, part 2 *)
34e49164
C
581(*****************************************************************************)
582
ae4735db 583let lookup_opt_env lookupf s =
91eba41f
C
584 Common.optionise (fun () ->
585 lookupf s !_scoped_env
586 )
587
ae4735db
C
588let unwrap_unfold_env2 typ =
589 Ast_c.unwrap_typeC
590 (type_unfold_one_step typ !_scoped_env)
591let unwrap_unfold_env typ =
91eba41f 592 Common.profile_code "TAC.unwrap_unfold_env" (fun () -> unwrap_unfold_env2 typ)
34e49164 593
ae4735db 594let typedef_fix a b =
91eba41f 595 Common.profile_code "TAC.typedef_fix" (fun () -> typedef_fix a b)
34e49164 596
ae4735db
C
597let make_info_def_fix x =
598 Type_c.make_info_def (typedef_fix x !_scoped_env)
34e49164 599
91eba41f
C
600let make_info_fix (typ, local) =
601 Type_c.make_info ((typedef_fix typ !_scoped_env),local)
602
ae4735db
C
603
604let make_info_def = Type_c.make_info_def
34e49164 605
34e49164 606(*****************************************************************************)
91eba41f 607(* Main typer code, put later in a visitor *)
34e49164 608(*****************************************************************************)
34e49164 609
ae4735db 610let annotater_expr_visitor_subpart = (fun (k,bigf) expr ->
34e49164 611
ae4735db 612 let ty =
91eba41f 613 match Ast_c.unwrap_expr expr with
ae4735db 614
91eba41f
C
615 (* -------------------------------------------------- *)
616 (* todo: should analyse the 's' for int to know if unsigned or not *)
5626f154
C
617 | Constant (String (s,kind)) -> make_info_def (type_of_s "char []")
618 | Constant MultiString _ -> make_info_def (type_of_s "char []")
91eba41f 619 | Constant (Char (s,kind)) -> make_info_def (type_of_s "char")
708f4980
C
620 | Constant (Int (s,kind)) ->
621 (* this seems really unpleasant, but perhaps the type needs to be set
622 up in some way that allows pretty printing *)
623 make_info_def
624 (match kind with
625 (* matches limited by what is generated in lexer_c.mll *)
626 Si(Signed,CInt) -> type_of_s "int"
627 | Si(UnSigned,CInt) -> type_of_s "unsigned int"
628 | Si(Signed,CLong) -> type_of_s "long"
629 | Si(UnSigned,CLong) -> type_of_s "unsigned long"
630 | Si(Signed,CLongLong) -> type_of_s "long long"
631 | Si(UnSigned,CLongLong) -> type_of_s "unsigned long long"
632 | _ -> failwith "unexpected kind for constant")
ae4735db 633 | Constant (Float (s,kind)) ->
91eba41f
C
634 let fake = Ast_c.fakeInfo (Common.fake_parse_info) in
635 let fake = Ast_c.rewrap_str "float" fake in
636 let iinull = [fake] in
708f4980 637 make_info_def (Ast_c.mk_ty (BaseType (FloatType kind)) iinull)
ae4735db
C
638
639
91eba41f 640 (* -------------------------------------------------- *)
ae4735db
C
641 (* note: could factorize this code with the code for Ident
642 * and the other code for Funcall below. But as the Ident can be
91eba41f
C
643 * a macro-func, I prefer to handle it separately. So
644 * this rule can handle the macro-func, the Ident-rule can handle
645 * the macro-var, and the other FunCall-rule the regular
646 * function calls through fields.
647 * Also as I don't want a warning on the Ident that are a FunCall,
648 * easier to have a rule separate from the Ident rule.
649 *)
ae4735db 650 | FunCall (e1, args) ->
708f4980 651 (match Ast_c.unwrap_expr e1 with
ae4735db 652 | Ident (ident) ->
91eba41f 653 (* recurse *)
ae4735db 654 args +> List.iter (fun (e,ii) ->
91eba41f
C
655 (* could typecheck if arguments agree with prototype *)
656 Visitor_c.vk_argument bigf e
657 );
b1b2de81 658 let s = Ast_c.str_of_name ident in
91eba41f 659 (match lookup_opt_env lookup_var s with
ae4735db
C
660 | Some ((typ,local),_nextenv) ->
661
91eba41f
C
662 (* set type for ident *)
663 let tyinfo = make_info_fix (typ, local) in
664 Ast_c.set_type_expr e1 tyinfo;
665
666 (match unwrap_unfold_env typ with
667 | FunctionType (ret, params) -> make_info_def ret
668
ae4735db 669 (* can be function pointer, C have an iso for that,
91eba41f
C
670 * same pfn() syntax than regular function call.
671 *)
ae4735db 672 | Pointer (typ2) ->
91eba41f
C
673 (match unwrap_unfold_env typ2 with
674 | FunctionType (ret, params) -> make_info_def ret
675 | _ -> Type_c.noTypeHere
676 )
677 | _ -> Type_c.noTypeHere
678 )
ae4735db 679 | None ->
91eba41f
C
680
681 (match lookup_opt_env lookup_macro s with
ae4735db 682 | Some ((defkind, defval), _nextenv) ->
91eba41f 683 (match defkind, defval with
ae4735db 684 | DefineFunc _, DefineExpr e ->
91eba41f
C
685 let rettype = Ast_c.get_onlytype_expr e in
686
687 (* todo: could also set type for ident ?
688 have return type and at least type of concrete
689 parameters so can generate a fake FunctionType
690 *)
ae4735db 691 let macrotype_opt =
91eba41f
C
692 Type_c.fake_function_type rettype args
693 in
694
ae4735db 695 macrotype_opt +> Common.do_option (fun t ->
91eba41f
C
696 pr2 ("Type_annotater: generate fake function type" ^
697 "for macro: " ^ s);
698 let tyinfo = make_info_def_fix t in
699 Ast_c.set_type_expr e1 tyinfo;
700 );
701
702 Ast_c.get_type_expr e
ae4735db 703 | DefineVar, _ ->
91eba41f
C
704 pr2 ("Type_annoter: not a macro-func: " ^ s);
705 Type_c.noTypeHere
3a314143
C
706 | Undef, _ ->
707 pr2 ("Type_annoter: not a macro-func: " ^ s);
708 Type_c.noTypeHere
ae4735db 709 | DefineFunc _, _ ->
3a314143 710 (* normally the FunCall case should have caught it *)
91eba41f
C
711 pr2 ("Type_annoter: not a macro-func-expr: " ^ s);
712 Type_c.noTypeHere
713 )
ae4735db 714 | None ->
0708f913 715 pr2_once ("type_annotater: no type for function ident: " ^ s);
91eba41f
C
716 Type_c.noTypeHere
717 )
718 )
34e49164 719
34e49164 720
ae4735db 721 | _e ->
91eba41f 722 k expr;
ae4735db
C
723
724 (Ast_c.get_type_expr e1) +> Type_c.do_with_type (fun typ ->
725 (* copy paste of above *)
91eba41f
C
726 (match unwrap_unfold_env typ with
727 | FunctionType (ret, params) -> make_info_def ret
ae4735db 728 | Pointer (typ) ->
91eba41f
C
729 (match unwrap_unfold_env typ with
730 | FunctionType (ret, params) -> make_info_def ret
731 | _ -> Type_c.noTypeHere
732 )
733 | _ -> Type_c.noTypeHere
34e49164 734 )
91eba41f 735 )
708f4980 736 )
91eba41f
C
737
738
739 (* -------------------------------------------------- *)
ae4735db 740 | Ident (ident) ->
b1b2de81 741 let s = Ast_c.str_of_name ident in
91eba41f 742 (match lookup_opt_env lookup_var s with
ae4735db 743 | Some ((typ,local),_nextenv) ->
91eba41f 744 make_info_fix (typ,local)
ae4735db 745 | None ->
91eba41f 746 (match lookup_opt_env lookup_macro s with
ae4735db 747 | Some ((defkind, defval), _nextenv) ->
91eba41f 748 (match defkind, defval with
ae4735db 749 | DefineVar, DefineExpr e ->
91eba41f 750 Ast_c.get_type_expr e
ae4735db 751 | DefineVar, _ ->
91eba41f
C
752 pr2 ("Type_annoter: not a expression: " ^ s);
753 Type_c.noTypeHere
ae4735db 754 | DefineFunc _, _ ->
91eba41f
C
755 (* normally the FunCall case should have catch it *)
756 pr2 ("Type_annoter: not a macro-var: " ^ s);
757 Type_c.noTypeHere
3a314143
C
758 | Undef, _ ->
759 pr2 ("Type_annoter: not a expression: " ^ s);
760 Type_c.noTypeHere
91eba41f 761 )
ae4735db 762 | None ->
91eba41f 763 (match lookup_opt_env lookup_enum s with
ae4735db
C
764 | Some (_, _nextenv) ->
765 make_info_def (type_of_s "int")
766 | None ->
91eba41f 767 if not (s =~ "[A-Z_]+") (* if macro then no warning *)
ae4735db
C
768 then
769 if !Flag_parsing_c.check_annotater then
91eba41f 770 if not (Hashtbl.mem !_notyped_var s)
ae4735db 771 then begin
002099fc 772 pr2 ("Type_annoter: no type found for: " ^ s);
91eba41f
C
773 Hashtbl.add !_notyped_var s true;
774 end
775 else ()
ae4735db 776 else
002099fc 777 pr2 ("Type_annoter: no type found for: " ^ s)
91eba41f
C
778 ;
779 Type_c.noTypeHere
780 )
781 )
782 )
ae4735db 783
91eba41f
C
784 (* -------------------------------------------------- *)
785 (* C isomorphism on type on array and pointers *)
786 | Unary (e, DeRef)
787 | ArrayAccess (e, _) ->
788 k expr; (* recurse to set the types-ref of sub expressions *)
789
ae4735db 790 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
91eba41f
C
791 (* todo: maybe not good env !! *)
792 match unwrap_unfold_env t with
ae4735db
C
793 | Pointer x
794 | Array (_, x) ->
91eba41f
C
795 make_info_def_fix x
796 | _ -> Type_c.noTypeHere
797
798 )
799
ae4735db 800 | Unary (e, GetRef) ->
91eba41f
C
801 k expr; (* recurse to set the types-ref of sub expressions *)
802
ae4735db
C
803 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
804 (* must generate an element so that '=' can be used
91eba41f
C
805 * to compare type ?
806 *)
807 let fake = Ast_c.fakeInfo Common.fake_parse_info in
808 let fake = Ast_c.rewrap_str "*" fake in
ae4735db 809
708f4980 810 let ft = Ast_c.mk_ty (Pointer t) [fake] in
91eba41f
C
811 make_info_def_fix ft
812 )
813
814
815 (* -------------------------------------------------- *)
816 (* fields *)
ae4735db
C
817 | RecordAccess (e, namefld)
818 | RecordPtAccess (e, namefld) as x ->
b1b2de81
C
819
820 let fld = Ast_c.str_of_name namefld in
34e49164 821
91eba41f 822 k expr; (* recurse to set the types-ref of sub expressions *)
91eba41f 823
ae4735db
C
824 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
825
826 let topt =
91eba41f
C
827 match x with
828 | RecordAccess _ -> Some t
ae4735db
C
829 | RecordPtAccess _ ->
830 (match unwrap_unfold_env t with
91eba41f
C
831 | Pointer (t) -> Some t
832 | _ -> None
34e49164 833 )
91eba41f 834 | _ -> raise Impossible
ae4735db 835
91eba41f
C
836 in
837 (match topt with
838 | None -> Type_c.noTypeHere
ae4735db 839 | Some t ->
91eba41f 840 match unwrap_unfold_env t with
ae4735db
C
841 | StructUnion (su, sopt, fields) ->
842 (try
91eba41f 843 (* todo: which env ? *)
ae4735db 844 make_info_def_fix
91eba41f 845 (Type_c.type_field fld (su, fields))
ae4735db
C
846 with
847 | Not_found ->
848 pr2 (spf
91eba41f
C
849 "TYPE-ERROR: field '%s' does not belong in struct %s"
850 fld (match sopt with Some s -> s |_ -> "<anon>"));
851 Type_c.noTypeHere
ae4735db 852 | Multi_found ->
91eba41f
C
853 pr2 "TAC:MultiFound";
854 Type_c.noTypeHere
855 )
856 | _ -> Type_c.noTypeHere
34e49164 857 )
91eba41f 858 )
ae4735db 859
91eba41f
C
860
861
862 (* -------------------------------------------------- *)
ae4735db 863 | Cast (t, e) ->
91eba41f
C
864 k expr;
865 (* todo: if infer, can "push" info ? add_types_expr [t] e ? *)
866 make_info_def_fix (Lib.al_type t)
867
868 (* todo? lub, hmm maybe not, cos type must be e1 *)
ae4735db
C
869 | Assignment (e1, op, e2) ->
870 k expr;
c491d8ee
C
871 (* value of an assignment is the value of the RHS expression, but its
872 type is the type of the lhs expression. Use the rhs exp if no
873 information is available *)
874 (match Ast_c.get_type_expr e1 with
875 (None,_) -> Ast_c.get_type_expr e2
876 | (Some ty,t) -> (Some ty,t))
ae4735db
C
877 | Sequence (e1, e2) ->
878 k expr;
91eba41f 879 Ast_c.get_type_expr e2
ae4735db
C
880
881 | Binary (e1, Logical _, e2) ->
708f4980
C
882 k expr;
883 make_info_def (type_of_s "int")
884
91eba41f 885 (* todo: lub *)
ae4735db 886 | Binary (e1, Arith op, e2) ->
91eba41f 887 k expr;
708f4980 888 Type_c.lub op (Type_c.get_opt_type e1) (Type_c.get_opt_type e2)
91eba41f 889
ae4735db 890 | CondExpr (cond, e1opt, e2) ->
91eba41f
C
891 k expr;
892 Ast_c.get_type_expr e2
34e49164 893
34e49164 894
ae4735db 895 | ParenExpr e ->
91eba41f
C
896 k expr;
897 Ast_c.get_type_expr e
898
ae4735db 899 | Infix (e, op) | Postfix (e, op) ->
91eba41f
C
900 k expr;
901 Ast_c.get_type_expr e
ae4735db 902
91eba41f 903 (* pad: julia wrote this ? *)
ae4735db 904 | Unary (e, UnPlus) ->
91eba41f
C
905 k expr; (* recurse to set the types-ref of sub expressions *)
906 make_info_def (type_of_s "int")
907 (* todo? can convert from unsigned to signed if UnMinus ? *)
ae4735db 908 | Unary (e, UnMinus) ->
91eba41f
C
909 k expr; (* recurse to set the types-ref of sub expressions *)
910 make_info_def (type_of_s "int")
ae4735db
C
911
912 | SizeOfType _|SizeOfExpr _ ->
91eba41f 913 k expr; (* recurse to set the types-ref of sub expressions *)
1eddfd50 914 make_info_def (type_of_s "size_t")
ae4735db
C
915
916 | Constructor (ft, ini) ->
91eba41f
C
917 k expr; (* recurse to set the types-ref of sub expressions *)
918 make_info_def (Lib.al_type ft)
ae4735db
C
919
920 | Unary (e, Not) ->
91eba41f 921 k expr; (* recurse to set the types-ref of sub expressions *)
5636bb2c
C
922 (* the result of ! is always 0 or 1, not the argument type *)
923 make_info_def (type_of_s "int")
ae4735db 924 | Unary (e, Tilde) ->
91eba41f
C
925 k expr; (* recurse to set the types-ref of sub expressions *)
926 Ast_c.get_type_expr e
ae4735db 927
91eba41f
C
928 (* -------------------------------------------------- *)
929 (* todo *)
ae4735db 930 | Unary (_, GetRefLabel) ->
91eba41f
C
931 k expr; (* recurse to set the types-ref of sub expressions *)
932 pr2_once "Type annotater:not handling GetRefLabel";
933 Type_c.noTypeHere
934 (* todo *)
ae4735db 935 | StatementExpr _ ->
91eba41f 936 k expr; (* recurse to set the types-ref of sub expressions *)
951c7801 937 pr2_once "Type annotater:not handling StatementExpr";
91eba41f
C
938 Type_c.noTypeHere
939 (*
940 | _ -> k expr; Type_c.noTypeHere
941 *)
ae4735db 942
f59c9fb7
C
943 | New ty ->
944 k expr;
945 pr2_once "Type annotater:not handling New";
946 Type_c.noTypeHere (* TODO *)
947
4dfbc1c2
C
948 | Delete e ->
949 k expr;
950 pr2_once "Type annotater:not handling Delete";
951 Type_c.noTypeHere (* TODO *)
952
91eba41f
C
953 in
954 Ast_c.set_type_expr expr ty
955
956)
957
ae4735db 958
91eba41f
C
959(*****************************************************************************)
960(* Visitor *)
961(*****************************************************************************)
962
963(* Processing includes that were added after a cpp_ast_c makes the
964 * type annotater quite slow, especially when the depth of cpp_ast_c is
965 * big. But for such includes the only thing we really want is to modify
966 * the environment to have enough type information. We don't need
967 * to type the expressions inside those includes (they will be typed
ae4735db 968 * when we process the include file directly). Here the goal is
91eba41f 969 * to not recurse.
ae4735db 970 *
91eba41f
C
971 * Note that as usually header files contain mostly structure
972 * definitions and defines, that means we still have to do lots of work.
ae4735db 973 * We only win on function definition bodies, but usually header files
91eba41f
C
974 * have just prototypes, or inline function definitions which anyway have
975 * usually a small body. But still, we win. It also makes clearer
976 * that when processing include as we just need the environment, the caller
ae4735db 977 * of this module can do further optimisations such as memorising the
91eba41f 978 * state of the environment after each header files.
ae4735db
C
979 *
980 *
91eba41f
C
981 * For sparse its makes the annotating speed goes from 9s to 4s
982 * For Linux the speedup is even better, from ??? to ???.
ae4735db 983 *
91eba41f
C
984 * Because There would be some copy paste with annotate_program, it is
985 * better to factorize code hence the just_add_in_env parameter below.
ae4735db 986 *
91eba41f
C
987 * todo? alternative optimisation for the include problem:
988 * - processing all headers files one time and construct big env
989 * - use hashtbl for env (but apparently not biggest problem)
990 *)
ae4735db
C
991
992let rec visit_toplevel ~just_add_in_env ~depth elem =
91eba41f
C
993 let need_annotate_body = not just_add_in_env in
994
ae4735db 995 let bigf = { Visitor_c.default_visitor_c with
91eba41f
C
996
997 (* ------------------------------------------------------------ *)
ae4735db 998 Visitor_c.kcppdirective = (fun (k, bigf) directive ->
91eba41f
C
999 match directive with
1000 (* do error messages for type annotater only for the real body of the
1001 * file, not inside include.
1002 *)
ae4735db
C
1003 | Include {i_content = opt} ->
1004 opt +> Common.do_option (fun (filename, program) ->
1005 Common.save_excursion Flag_parsing_c.verbose_type (fun () ->
91eba41f
C
1006 Flag_parsing_c.verbose_type := false;
1007
ae4735db 1008 (* old: Visitor_c.vk_program bigf program;
91eba41f
C
1009 * opti: set the just_add_in_env
1010 *)
ae4735db 1011 program +> List.iter (fun elem ->
91eba41f 1012 visit_toplevel ~just_add_in_env:true ~depth:(depth+1) elem
34e49164 1013 )
91eba41f 1014 )
34e49164 1015 )
91eba41f 1016
ae4735db 1017 | Define ((s,ii), (defkind, defval)) ->
91eba41f
C
1018
1019
1020 (* even if we are in a just_add_in_env phase, such as when
ae4735db
C
1021 * we process include, as opposed to the body of functions,
1022 * with macros we still to type the body of the macro as
91eba41f
C
1023 * the macro has no type and so we infer its type from its
1024 * body (and one day later maybe from its use).
1025 *)
1026 (match defval with
1027 (* can try to optimize and recurse only when the define body
ae4735db 1028 * is simple ?
91eba41f
C
1029 *)
1030
ae4735db 1031 | DefineExpr expr ->
951c7801
C
1032 (* prevent macro-declared variables from leaking out *)
1033 do_in_new_scope (fun () ->
1034 if is_simple_expr expr
91eba41f 1035 (* even if not need_annotate_body, still recurse*)
ae4735db
C
1036 then k directive
1037 else
951c7801
C
1038 if need_annotate_body
1039 then k directive)
ae4735db 1040 | _ ->
951c7801
C
1041 do_in_new_scope (fun () ->
1042 if need_annotate_body
1043 then k directive)
91eba41f
C
1044 );
1045
1046 add_binding (Macro (s, (defkind, defval) )) true;
1047
91eba41f 1048 | PragmaAndCo _ -> ()
34e49164
C
1049 );
1050
91eba41f
C
1051 (* ------------------------------------------------------------ *)
1052 (* main typer code *)
1053 (* ------------------------------------------------------------ *)
1054 Visitor_c.kexpr = annotater_expr_visitor_subpart;
1055
1056 (* ------------------------------------------------------------ *)
ae4735db
C
1057 Visitor_c.kstatement = (fun (k, bigf) st ->
1058 match Ast_c.unwrap_st st with
708f4980 1059 | Compound statxs -> do_in_new_scope (fun () -> k st);
34e49164 1060 | _ -> k st
34e49164 1061 );
91eba41f 1062 (* ------------------------------------------------------------ *)
ae4735db 1063 Visitor_c.kdecl = (fun (k, bigf) d ->
34e49164 1064 (match d with
ae4735db 1065 | (DeclList (xs, ii)) ->
485bce71 1066 xs +> List.iter (fun ({v_namei = var; v_type = t;
978fd7e5
C
1067 v_storage = sto; v_local = local} as x
1068 , iicomma) ->
485bce71 1069
34e49164
C
1070 (* to add possible definition in type found in Decl *)
1071 Visitor_c.vk_type bigf t;
91eba41f
C
1072
1073
1074 let local =
1075 match local with
1076 | Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
978fd7e5 1077 | Ast_c.LocalDecl -> Ast_c.LocalVar (Ast_c.info_of_type t)
91eba41f 1078 in
ae4735db 1079 var +> Common.do_option (fun (name, iniopt) ->
b1b2de81
C
1080 let s = Ast_c.str_of_name name in
1081
ae4735db
C
1082 match sto with
1083 | StoTypedef, _inline ->
34e49164 1084 add_binding (TypeDef (s,Lib.al_type t)) true;
ae4735db 1085 | _ ->
34e49164 1086 add_binding (VarOrFunc (s, (Lib.al_type t, local))) true;
91eba41f 1087
ae4735db 1088 x.v_type_bis :=
978fd7e5 1089 Some (typedef_fix (Lib.al_type t) !_scoped_env);
91eba41f
C
1090
1091 if need_annotate_body then begin
1092 (* int x = sizeof(x) is legal so need process ini *)
4dfbc1c2
C
1093 match iniopt with
1094 Ast_c.NoInit -> ()
1095 | Ast_c.ValInit(iini,init) -> Visitor_c.vk_ini bigf init
1096 | Ast_c.ConstrInit((args,_)) ->
1097 args +> List.iter (fun (e,ii) ->
1098 Visitor_c.vk_argument bigf e
1099 )
91eba41f 1100 end
34e49164
C
1101 );
1102 );
ae4735db 1103 | MacroDecl _ ->
91eba41f
C
1104 if need_annotate_body
1105 then k d
34e49164 1106 );
ae4735db 1107
34e49164
C
1108 );
1109
91eba41f 1110 (* ------------------------------------------------------------ *)
ae4735db
C
1111 Visitor_c.ktype = (fun (k, bigf) typ ->
1112 (* bugfix: have a 'Lib.al_type typ' before, but because we can
91eba41f 1113 * have enum with possible expression, we don't want to change
ae4735db 1114 * the ref of abstract-lined types, but the real one, so
91eba41f
C
1115 * don't al_type here
1116 *)
708f4980 1117 let (_q, tbis) = typ in
ae4735db
C
1118 match Ast_c.unwrap_typeC typ with
1119 | StructUnion (su, Some s, structType) ->
1120 let structType' = Lib.al_fields structType in
708f4980 1121 let ii = Ast_c.get_ii_typeC_take_care tbis in
91eba41f
C
1122 let ii' = Lib.al_ii ii in
1123 add_binding (StructUnionNameDef (s, ((su, structType'),ii'))) true;
1124
1125 if need_annotate_body
1126 then k typ (* todo: restrict ? new scope so use do_in_scope ? *)
1127
ae4735db 1128 | Enum (sopt, enums) ->
91eba41f 1129
ae4735db 1130 enums +> List.iter (fun ((name, eopt), iicomma) ->
b1b2de81
C
1131
1132 let s = Ast_c.str_of_name name in
91eba41f
C
1133
1134 if need_annotate_body
ae4735db 1135 then eopt +> Common.do_option (fun (ieq, e) ->
91eba41f
C
1136 Visitor_c.vk_expr bigf e
1137 );
1138 add_binding (EnumConstant (s, sopt)) true;
1139 );
34e49164
C
1140
1141
1142 (* TODO: if have a TypeName, then maybe can fill the option
1143 * information.
1144 *)
ae4735db 1145 | _ ->
91eba41f
C
1146 if need_annotate_body
1147 then k typ
ae4735db
C
1148
1149 );
34e49164 1150
91eba41f 1151 (* ------------------------------------------------------------ *)
ae4735db 1152 Visitor_c.ktoplevel = (fun (k, bigf) elem ->
34e49164
C
1153 _notyped_var := Hashtbl.create 100;
1154 match elem with
ae4735db 1155 | Definition def ->
b1b2de81 1156 let {f_name = name;
485bce71
C
1157 f_type = ((returnt, (paramst, b)) as ftyp);
1158 f_storage = sto;
91eba41f
C
1159 f_body = statxs;
1160 f_old_c_style = oldstyle;
ae4735db 1161 },ii
91eba41f 1162 = def
34e49164 1163 in
ae4735db
C
1164 let (i1, i2) =
1165 match ii with
1166 (* what is iifunc1? it should be a type. jll
002099fc
C
1167 * pad: it's the '(' in the function definition. The
1168 * return type is part of f_type.
1169 *)
ae4735db 1170 | iifunc1::iifunc2::ibrace1::ibrace2::ifakestart::isto ->
34e49164
C
1171 iifunc1, iifunc2
1172 | _ -> raise Impossible
1173 in
b1b2de81 1174 let funcs = Ast_c.str_of_name name in
91eba41f 1175
ae4735db
C
1176 (match oldstyle with
1177 | None ->
1178 let typ' =
708f4980 1179 Lib.al_type (Ast_c.mk_ty (FunctionType ftyp) [i1;i2]) in
91eba41f 1180
ae4735db 1181 add_binding (VarOrFunc (funcs, (typ',islocal i1.Ast_c.pinfo)))
91eba41f
C
1182 false;
1183
1184 if need_annotate_body then
ae4735db
C
1185 do_in_new_scope (fun () ->
1186 paramst +> List.iter (fun ({p_namei= nameopt; p_type= t},_)->
1187 match nameopt with
b1b2de81
C
1188 | Some name ->
1189 let s = Ast_c.str_of_name name in
978fd7e5 1190 let local = Ast_c.LocalVar (Ast_c.info_of_type t) in
91eba41f 1191 add_binding (VarOrFunc (s,(Lib.al_type t,local))) true
ae4735db 1192 | None ->
91eba41f
C
1193 pr2 "no type, certainly because Void type ?"
1194 );
1195 (* recurse *)
1196 k elem
1197 );
ae4735db 1198 | Some oldstyle ->
91eba41f
C
1199 (* generate regular function type *)
1200
ae4735db 1201 pr2 "TODO generate type for function";
91eba41f
C
1202 (* add bindings *)
1203 if need_annotate_body then
ae4735db 1204 do_in_new_scope (fun () ->
91eba41f 1205 (* recurse. should naturally call the kdecl visitor and
ae4735db 1206 * add binding
91eba41f
C
1207 *)
1208 k elem;
1209 );
1210
34e49164 1211 );
ae4735db 1212 | CppTop x ->
708f4980 1213 (match x with
ae4735db 1214 | Define ((s,ii), (DefineVar, DefineType t)) ->
708f4980
C
1215 add_binding (TypeDef (s,Lib.al_type t)) true;
1216 | _ -> k elem
ae4735db 1217 )
708f4980 1218
91eba41f
C
1219 | Declaration _
1220
708f4980
C
1221
1222
91eba41f 1223 | IfdefTop _
ae4735db 1224 | MacroTop _
91eba41f
C
1225 | EmptyDef _
1226 | NotParsedCorrectly _
1227 | FinalDef _
ae4735db 1228 ->
91eba41f 1229 k elem
34e49164 1230 );
ae4735db 1231 }
34e49164 1232 in
91eba41f 1233 if just_add_in_env
ae4735db
C
1234 then
1235 if depth > 1
91eba41f 1236 then Visitor_c.vk_toplevel bigf elem
ae4735db
C
1237 else
1238 Common.profile_code "TAC.annotate_only_included" (fun () ->
91eba41f
C
1239 Visitor_c.vk_toplevel bigf elem
1240 )
1241 else Visitor_c.vk_toplevel bigf elem
1242
1243(*****************************************************************************)
1244(* Entry point *)
1245(*****************************************************************************)
1246(* catch all the decl to grow the environment *)
1247
1248
ae4735db 1249let rec (annotate_program2 :
91eba41f
C
1250 environment -> toplevel list -> (toplevel * environment Common.pair) list) =
1251 fun env prog ->
1252
ae4735db 1253 (* globals (re)initialialisation *)
91eba41f
C
1254 _scoped_env := env;
1255 _notyped_var := (Hashtbl.create 100);
34e49164 1256
ae4735db 1257 prog +> List.map (fun elem ->
34e49164 1258 let beforeenv = !_scoped_env in
91eba41f 1259 visit_toplevel ~just_add_in_env:false ~depth:0 elem;
34e49164
C
1260 let afterenv = !_scoped_env in
1261 (elem, (beforeenv, afterenv))
1262 )
1263
91eba41f
C
1264
1265
1266
1267(*****************************************************************************)
1268(* Annotate test *)
1269(*****************************************************************************)
1270
ae4735db 1271(* julia: for coccinelle *)
34e49164
C
1272let annotate_test_expressions prog =
1273 let rec propagate_test e =
1274 let ((e_term,info),_) = e in
1275 let (ty,_) = !info in
1276 info := (ty,Test);
1277 match e_term with
1278 Binary(e1,Logical(AndLog),e2)
1279 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1280 | Unary(e1,Not) -> propagate_test e1
1281 | ParenExpr(e) -> propagate_test e
3a314143
C
1282 | FunCall(e,args) -> (* not very nice, but so painful otherwise *)
1283 (match (unwrap e,args) with
1284 ((Ident(i),_),[(Left a,_)]) ->
1285 let nm = str_of_name i in
1286 if List.mem nm ["likely";"unlikely"]
1287 then propagate_test a
1288 else ()
1289 | _ -> ())
34e49164
C
1290 | _ -> () in
1291
1292 let bigf = { Visitor_c.default_visitor_c with
1293 Visitor_c.kexpr = (fun (k,bigf) expr ->
708f4980
C
1294 (match unwrap_expr expr with
1295 CondExpr(e,_,_) -> propagate_test e
d6a55602
C
1296 | Binary(e1,Logical(AndLog),e2)
1297 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1298 | Unary(e1,Not) -> propagate_test e1
1299 | _ -> ()
91eba41f
C
1300 );
1301 k expr
1302 );
34e49164 1303 Visitor_c.kstatement = (fun (k, bigf) st ->
ae4735db 1304 match unwrap_st st with
34e49164
C
1305 Selection(s) ->
1306 (match s with If(e1,s1,s2) -> propagate_test e1 | _ -> ());
1307 k st;
1308 | Iteration(i) ->
1309 (match i with
1310 While(e,s) -> propagate_test e
1311 | DoWhile(s,e) -> propagate_test e
1312 | For(_,es,_,_) ->
1313 (match unwrap es with Some e -> propagate_test e | None -> ())
1314 | _ -> ());
1315 k st
91eba41f 1316 | _ -> k st
ae4735db 1317 )
91eba41f 1318 } in
ae4735db 1319 (prog +> List.iter (fun elem ->
34e49164
C
1320 Visitor_c.vk_toplevel bigf elem
1321 ))
1322
91eba41f
C
1323
1324
1325(*****************************************************************************)
1326(* Annotate types *)
1327(*****************************************************************************)
ae4735db 1328let annotate_program env prog =
91eba41f
C
1329 Common.profile_code "TAC.annotate_program"
1330 (fun () ->
1331 let res = annotate_program2 env prog in
34e49164 1332 annotate_test_expressions prog;
91eba41f
C
1333 res
1334 )
1335
ae4735db 1336let annotate_type_and_localvar env prog =
91eba41f
C
1337 Common.profile_code "TAC.annotate_type"
1338 (fun () -> annotate_program2 env prog)
1339
1340
1341(*****************************************************************************)
1342(* changing default typing environment, do concatenation *)
ae4735db 1343let init_env filename =
91eba41f
C
1344 pr2 ("init_env: " ^ filename);
1345 let (ast2, _stat) = Parse_c.parse_c_and_cpp filename in
1346 let ast = Parse_c.program_of_program2 ast2 in
1347
1348 let res = annotate_type_and_localvar !initial_env ast in
1349 match List.rev res with
1350 | [] -> pr2 "empty environment"
ae4735db 1351 | (_top,(env1,env2))::xs ->
91eba41f
C
1352 initial_env := !initial_env ++ env2;
1353 ()
1354