Release coccinelle-0.2.3rc1
[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
91eba41f
C
339 | BaseType x -> ty
340 | Pointer t -> ty
341 | Array (e, t) -> ty
342
34e49164 343 | StructUnion (sopt, su, fields) -> ty
ae4735db 344
91eba41f 345 | FunctionType t -> ty
34e49164 346 | Enum (s, enumt) -> ty
91eba41f
C
347
348 | EnumName s -> ty (* todo: look in env when will have EnumDef *)
ae4735db
C
349
350 | StructUnionName (su, s) ->
351 (try
34e49164 352 let (((su,fields),ii), env') = lookup_structunion (su, s) env in
708f4980 353 Ast_c.mk_ty (StructUnion (su, Some s, fields)) ii
ae4735db 354 (* old: +> Ast_c.rewrap_typeC ty
34e49164
C
355 * but must wrap with good ii, otherwise pretty_print_c
356 * will be lost and raise some Impossible
357 *)
ae4735db 358 with Not_found ->
34e49164
C
359 ty
360 )
ae4735db
C
361
362 | TypeName (name, _typ) ->
b1b2de81 363 let s = Ast_c.str_of_name name in
ae4735db 364 (try
91eba41f 365 if !typedef_debug then pr2 "type_unfold_one_step: lookup_typedef";
34e49164
C
366 let (t', env') = lookup_typedef s env in
367 type_unfold_one_step t' env'
ae4735db 368 with Not_found ->
34e49164
C
369 ty
370 )
ae4735db 371
34e49164 372 | ParenType t -> type_unfold_one_step t env
ae4735db 373 | TypeOfExpr e ->
34e49164
C
374 pr2_once ("Type_annoter: not handling typeof");
375 ty
376 | TypeOfType t -> type_unfold_one_step t env
377
378
379
34e49164
C
380
381
382
34e49164
C
383
384
385
ae4735db 386(* normalizer. can be seen as the opposite of the previous function as
0708f913
C
387 * we "fold" at least for the structUnion. Should return something that
388 * Type_c.is_completed_fullType likes, something that makes it easier
389 * for the programmer to work on, that has all the needed information
390 * for most tasks.
91eba41f 391 *)
ae4735db
C
392let rec typedef_fix ty env =
393 match Ast_c.unwrap_typeC ty with
394 | BaseType x ->
91eba41f 395 ty
ae4735db 396 | Pointer t ->
91eba41f 397 Pointer (typedef_fix t env) +> Ast_c.rewrap_typeC ty
ae4735db 398 | Array (e, t) ->
91eba41f 399 Array (e, typedef_fix t env) +> Ast_c.rewrap_typeC ty
ae4735db
C
400 | StructUnion (su, sopt, fields) ->
401 (* normalize, fold.
402 * todo? but what if correspond to a nested struct def ?
91eba41f
C
403 *)
404 Type_c.structdef_to_struct_name ty
ae4735db 405 | FunctionType ft ->
34e49164 406 (FunctionType ft) (* todo ? *) +> Ast_c.rewrap_typeC ty
ae4735db 407 | Enum (s, enumt) ->
34e49164 408 (Enum (s, enumt)) (* todo? *) +> Ast_c.rewrap_typeC ty
ae4735db 409 | EnumName s ->
34e49164
C
410 (EnumName s) (* todo? *) +> Ast_c.rewrap_typeC ty
411
412 (* we prefer StructUnionName to StructUnion when it comes to typed metavar *)
413 | StructUnionName (su, s) -> ty
91eba41f
C
414
415 (* keep the typename but complete with more information *)
ae4735db 416 | TypeName (name, typ) ->
b1b2de81 417 let s = Ast_c.str_of_name name in
0708f913 418 (match typ with
ae4735db 419 | Some _ ->
0708f913
C
420 pr2 ("typedef value already there:" ^ s);
421 ty
ae4735db 422 | None ->
0708f913 423 (try
91eba41f 424 if !typedef_debug then pr2 "typedef_fix: lookup_typedef";
34e49164 425 let (t', env') = lookup_typedef s env in
91eba41f
C
426
427 (* bugfix: termination bug if use env instead of env' below, because
0708f913 428 * can have some weird mutually recursive typedef which
91eba41f
C
429 * each new type alias search for its mutual def.
430 *)
b1b2de81 431 TypeName (name, Some (typedef_fix t' env')) +> Ast_c.rewrap_typeC ty
ae4735db 432 with Not_found ->
34e49164 433 ty
0708f913
C
434 ))
435
91eba41f 436 (* remove paren for better matching with typed metavar. kind of iso again *)
ae4735db 437 | ParenType t ->
91eba41f 438 typedef_fix t env
ae4735db 439 | TypeOfExpr e ->
34e49164
C
440 pr2_once ("Type_annoter: not handling typeof");
441 ty
442
ae4735db 443 | TypeOfType t ->
91eba41f
C
444 typedef_fix t env
445
446
447(*****************************************************************************)
448(* Helpers, part 1 *)
449(*****************************************************************************)
450
ae4735db 451let type_of_s2 s =
91eba41f 452 (Lib.al_type (Parse_c.type_of_string s))
ae4735db 453let type_of_s a =
91eba41f
C
454 Common.profile_code "Type_c.type_of_s" (fun () -> type_of_s2 a)
455
456
457(* pad: pb on:
458 * /home/pad/software-os-src2/freebsd/contrib/ipfilter/netinet/ip_fil_freebsd.c
459 * because in the code there is:
460 * static iss_seq_off = 0;
461 * which in the parser was generating a default int without a parse_info.
462 * I now add a fake parse_info for such default int so no more failwith
463 * normally.
464 *)
91eba41f 465
ae4735db 466let rec is_simple_expr expr =
91eba41f 467 match Ast_c.unwrap_expr expr with
ae4735db
C
468 (* todo? handle more special cases ? *)
469
470 | Ident _ ->
91eba41f 471 true
ae4735db 472 | Constant (_) ->
91eba41f 473 true
ae4735db 474 | Unary (op, e) ->
91eba41f 475 true
ae4735db 476 | Binary (e1, op, e2) ->
91eba41f 477 true
ae4735db 478 | Cast (t, e) ->
91eba41f
C
479 true
480 | ParenExpr (e) -> is_simple_expr e
481
482 | _ -> false
483
484(*****************************************************************************)
485(* Typing rules *)
486(*****************************************************************************)
487(* now in type_c.ml *)
488
489
34e49164
C
490
491(*****************************************************************************)
492(* (Semi) Globals, Julia's style *)
493(*****************************************************************************)
494
495(* opti: cache ? use hash ? *)
91eba41f 496let _scoped_env = ref !initial_env
34e49164
C
497
498(* memoise unnanoted var, to avoid too much warning messages *)
499let _notyped_var = ref (Hashtbl.create 100)
500
ae4735db 501let new_scope() = _scoped_env := []::!_scoped_env
34e49164
C
502let del_scope() = _scoped_env := List.tl !_scoped_env
503
ae4735db 504let do_in_new_scope f =
34e49164
C
505 begin
506 new_scope();
507 let res = f() in
508 del_scope();
509 res
510 end
511
512let add_in_scope namedef =
513 let (current, older) = Common.uncons !_scoped_env in
514 _scoped_env := (namedef::current)::older
515
91eba41f
C
516
517(* ------------------------------------------------------------ *)
518
34e49164
C
519(* sort of hackish... *)
520let islocal info =
b1b2de81 521 if List.length (!_scoped_env) =|= List.length !initial_env
34e49164
C
522 then Ast_c.NotLocalVar
523 else Ast_c.LocalVar info
524
91eba41f 525(* ------------------------------------------------------------ *)
ae4735db 526(* the warning argument is here to allow some binding to overwrite an
91eba41f
C
527 * existing one. With function, we first have the prototype and then the def,
528 * and the def binding with the same string is not an error.
ae4735db 529 *
34e49164 530 * todo?: but if we define two times the same function, then we will not
ae4735db 531 * detect it :( it would require to make a diff between adding a binding
34e49164 532 * from a prototype and from a definition.
ae4735db
C
533 *
534 * opti: disabling the check_annotater flag have some important
91eba41f 535 * performance benefit.
ae4735db 536 *
34e49164 537 *)
ae4735db 538let add_binding2 namedef warning =
34e49164
C
539 let (current_scope, _older_scope) = Common.uncons !_scoped_env in
540
91eba41f 541 if !Flag_parsing_c.check_annotater then begin
34e49164 542 (match namedef with
ae4735db 543 | VarOrFunc (s, typ) ->
91eba41f
C
544 if Hashtbl.mem !_notyped_var s
545 then pr2 ("warning: found typing information for a variable that was" ^
546 "previously unknown:" ^ s);
547 | _ -> ()
548 );
ae4735db
C
549
550 let (memberf, s) =
91eba41f 551 (match namedef with
ae4735db 552 | VarOrFunc (s, typ) ->
91eba41f 553 member_env (lookup_var s), s
ae4735db 554 | TypeDef (s, typ) ->
91eba41f 555 member_env (lookup_typedef s), s
ae4735db 556 | StructUnionNameDef (s, (su, typ)) ->
91eba41f 557 member_env (lookup_structunion (su, s)), s
ae4735db 558 | Macro (s, body) ->
91eba41f 559 member_env (lookup_macro s), s
ae4735db 560 | EnumConstant (s, body) ->
91eba41f
C
561 member_env (lookup_enum s), s
562 ) in
ae4735db 563
91eba41f 564 if memberf [current_scope] && warning
ae4735db 565 then pr2 ("Type_annoter: warning, " ^ s ^
91eba41f 566 " is already in current binding" ^ "\n" ^
0708f913 567 " so there is a weird shadowing");
91eba41f 568 end;
34e49164 569 add_in_scope namedef
91eba41f 570
ae4735db 571let add_binding namedef warning =
91eba41f 572 Common.profile_code "TAC.add_binding" (fun () -> add_binding2 namedef warning)
ae4735db 573
34e49164 574
91eba41f 575
34e49164 576(*****************************************************************************)
91eba41f 577(* Helpers, part 2 *)
34e49164
C
578(*****************************************************************************)
579
ae4735db 580let lookup_opt_env lookupf s =
91eba41f
C
581 Common.optionise (fun () ->
582 lookupf s !_scoped_env
583 )
584
ae4735db
C
585let unwrap_unfold_env2 typ =
586 Ast_c.unwrap_typeC
587 (type_unfold_one_step typ !_scoped_env)
588let unwrap_unfold_env typ =
91eba41f 589 Common.profile_code "TAC.unwrap_unfold_env" (fun () -> unwrap_unfold_env2 typ)
34e49164 590
ae4735db 591let typedef_fix a b =
91eba41f 592 Common.profile_code "TAC.typedef_fix" (fun () -> typedef_fix a b)
34e49164 593
ae4735db
C
594let make_info_def_fix x =
595 Type_c.make_info_def (typedef_fix x !_scoped_env)
34e49164 596
91eba41f
C
597let make_info_fix (typ, local) =
598 Type_c.make_info ((typedef_fix typ !_scoped_env),local)
599
ae4735db
C
600
601let make_info_def = Type_c.make_info_def
34e49164 602
34e49164 603(*****************************************************************************)
91eba41f 604(* Main typer code, put later in a visitor *)
34e49164 605(*****************************************************************************)
34e49164 606
ae4735db 607let annotater_expr_visitor_subpart = (fun (k,bigf) expr ->
34e49164 608
ae4735db 609 let ty =
91eba41f 610 match Ast_c.unwrap_expr expr with
ae4735db 611
91eba41f
C
612 (* -------------------------------------------------- *)
613 (* todo: should analyse the 's' for int to know if unsigned or not *)
614 | Constant (String (s,kind)) -> make_info_def (type_of_s "char *")
0708f913 615 | Constant MultiString _ -> make_info_def (type_of_s "char *")
91eba41f 616 | Constant (Char (s,kind)) -> make_info_def (type_of_s "char")
708f4980
C
617 | Constant (Int (s,kind)) ->
618 (* this seems really unpleasant, but perhaps the type needs to be set
619 up in some way that allows pretty printing *)
620 make_info_def
621 (match kind with
622 (* matches limited by what is generated in lexer_c.mll *)
623 Si(Signed,CInt) -> type_of_s "int"
624 | Si(UnSigned,CInt) -> type_of_s "unsigned int"
625 | Si(Signed,CLong) -> type_of_s "long"
626 | Si(UnSigned,CLong) -> type_of_s "unsigned long"
627 | Si(Signed,CLongLong) -> type_of_s "long long"
628 | Si(UnSigned,CLongLong) -> type_of_s "unsigned long long"
629 | _ -> failwith "unexpected kind for constant")
ae4735db 630 | Constant (Float (s,kind)) ->
91eba41f
C
631 let fake = Ast_c.fakeInfo (Common.fake_parse_info) in
632 let fake = Ast_c.rewrap_str "float" fake in
633 let iinull = [fake] in
708f4980 634 make_info_def (Ast_c.mk_ty (BaseType (FloatType kind)) iinull)
ae4735db
C
635
636
91eba41f 637 (* -------------------------------------------------- *)
ae4735db
C
638 (* note: could factorize this code with the code for Ident
639 * and the other code for Funcall below. But as the Ident can be
91eba41f
C
640 * a macro-func, I prefer to handle it separately. So
641 * this rule can handle the macro-func, the Ident-rule can handle
642 * the macro-var, and the other FunCall-rule the regular
643 * function calls through fields.
644 * Also as I don't want a warning on the Ident that are a FunCall,
645 * easier to have a rule separate from the Ident rule.
646 *)
ae4735db 647 | FunCall (e1, args) ->
708f4980 648 (match Ast_c.unwrap_expr e1 with
ae4735db
C
649 | Ident (ident) ->
650
91eba41f 651 (* recurse *)
ae4735db 652 args +> List.iter (fun (e,ii) ->
91eba41f
C
653 (* could typecheck if arguments agree with prototype *)
654 Visitor_c.vk_argument bigf e
655 );
b1b2de81 656 let s = Ast_c.str_of_name ident in
91eba41f 657 (match lookup_opt_env lookup_var s with
ae4735db
C
658 | Some ((typ,local),_nextenv) ->
659
91eba41f
C
660 (* set type for ident *)
661 let tyinfo = make_info_fix (typ, local) in
662 Ast_c.set_type_expr e1 tyinfo;
663
664 (match unwrap_unfold_env typ with
665 | FunctionType (ret, params) -> make_info_def ret
666
ae4735db 667 (* can be function pointer, C have an iso for that,
91eba41f
C
668 * same pfn() syntax than regular function call.
669 *)
ae4735db 670 | Pointer (typ2) ->
91eba41f
C
671 (match unwrap_unfold_env typ2 with
672 | FunctionType (ret, params) -> make_info_def ret
673 | _ -> Type_c.noTypeHere
674 )
675 | _ -> Type_c.noTypeHere
676 )
ae4735db 677 | None ->
91eba41f
C
678
679 (match lookup_opt_env lookup_macro s with
ae4735db 680 | Some ((defkind, defval), _nextenv) ->
91eba41f 681 (match defkind, defval with
ae4735db 682 | DefineFunc _, DefineExpr e ->
91eba41f
C
683 let rettype = Ast_c.get_onlytype_expr e in
684
685 (* todo: could also set type for ident ?
686 have return type and at least type of concrete
687 parameters so can generate a fake FunctionType
688 *)
ae4735db 689 let macrotype_opt =
91eba41f
C
690 Type_c.fake_function_type rettype args
691 in
692
ae4735db 693 macrotype_opt +> Common.do_option (fun t ->
91eba41f
C
694 pr2 ("Type_annotater: generate fake function type" ^
695 "for macro: " ^ s);
696 let tyinfo = make_info_def_fix t in
697 Ast_c.set_type_expr e1 tyinfo;
698 );
699
700 Ast_c.get_type_expr e
ae4735db 701 | DefineVar, _ ->
91eba41f
C
702 pr2 ("Type_annoter: not a macro-func: " ^ s);
703 Type_c.noTypeHere
ae4735db 704 | DefineFunc _, _ ->
91eba41f
C
705 (* normally the FunCall case should have catch it *)
706 pr2 ("Type_annoter: not a macro-func-expr: " ^ s);
707 Type_c.noTypeHere
708 )
ae4735db 709 | None ->
0708f913 710 pr2_once ("type_annotater: no type for function ident: " ^ s);
91eba41f
C
711 Type_c.noTypeHere
712 )
713 )
34e49164 714
34e49164 715
ae4735db 716 | _e ->
91eba41f 717 k expr;
ae4735db
C
718
719 (Ast_c.get_type_expr e1) +> Type_c.do_with_type (fun typ ->
720 (* copy paste of above *)
91eba41f
C
721 (match unwrap_unfold_env typ with
722 | FunctionType (ret, params) -> make_info_def ret
ae4735db 723 | Pointer (typ) ->
91eba41f
C
724 (match unwrap_unfold_env typ with
725 | FunctionType (ret, params) -> make_info_def ret
726 | _ -> Type_c.noTypeHere
727 )
728 | _ -> Type_c.noTypeHere
34e49164 729 )
91eba41f 730 )
708f4980 731 )
91eba41f
C
732
733
734 (* -------------------------------------------------- *)
ae4735db 735 | Ident (ident) ->
b1b2de81 736 let s = Ast_c.str_of_name ident in
91eba41f 737 (match lookup_opt_env lookup_var s with
ae4735db 738 | Some ((typ,local),_nextenv) ->
91eba41f 739 make_info_fix (typ,local)
ae4735db 740 | None ->
91eba41f 741 (match lookup_opt_env lookup_macro s with
ae4735db 742 | Some ((defkind, defval), _nextenv) ->
91eba41f 743 (match defkind, defval with
ae4735db 744 | DefineVar, DefineExpr e ->
91eba41f 745 Ast_c.get_type_expr e
ae4735db 746 | DefineVar, _ ->
91eba41f
C
747 pr2 ("Type_annoter: not a expression: " ^ s);
748 Type_c.noTypeHere
ae4735db 749 | DefineFunc _, _ ->
91eba41f
C
750 (* normally the FunCall case should have catch it *)
751 pr2 ("Type_annoter: not a macro-var: " ^ s);
752 Type_c.noTypeHere
753 )
ae4735db 754 | None ->
91eba41f 755 (match lookup_opt_env lookup_enum s with
ae4735db
C
756 | Some (_, _nextenv) ->
757 make_info_def (type_of_s "int")
758 | None ->
91eba41f 759 if not (s =~ "[A-Z_]+") (* if macro then no warning *)
ae4735db
C
760 then
761 if !Flag_parsing_c.check_annotater then
91eba41f 762 if not (Hashtbl.mem !_notyped_var s)
ae4735db 763 then begin
002099fc 764 pr2 ("Type_annoter: no type found for: " ^ s);
91eba41f
C
765 Hashtbl.add !_notyped_var s true;
766 end
767 else ()
ae4735db 768 else
002099fc 769 pr2 ("Type_annoter: no type found for: " ^ s)
91eba41f
C
770 ;
771 Type_c.noTypeHere
772 )
773 )
774 )
ae4735db 775
91eba41f
C
776 (* -------------------------------------------------- *)
777 (* C isomorphism on type on array and pointers *)
778 | Unary (e, DeRef)
779 | ArrayAccess (e, _) ->
780 k expr; (* recurse to set the types-ref of sub expressions *)
781
ae4735db 782 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
91eba41f
C
783 (* todo: maybe not good env !! *)
784 match unwrap_unfold_env t with
ae4735db
C
785 | Pointer x
786 | Array (_, x) ->
91eba41f
C
787 make_info_def_fix x
788 | _ -> Type_c.noTypeHere
789
790 )
791
ae4735db 792 | Unary (e, GetRef) ->
91eba41f
C
793 k expr; (* recurse to set the types-ref of sub expressions *)
794
ae4735db
C
795 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
796 (* must generate an element so that '=' can be used
91eba41f
C
797 * to compare type ?
798 *)
799 let fake = Ast_c.fakeInfo Common.fake_parse_info in
800 let fake = Ast_c.rewrap_str "*" fake in
ae4735db 801
708f4980 802 let ft = Ast_c.mk_ty (Pointer t) [fake] in
91eba41f
C
803 make_info_def_fix ft
804 )
805
806
807 (* -------------------------------------------------- *)
808 (* fields *)
ae4735db
C
809 | RecordAccess (e, namefld)
810 | RecordPtAccess (e, namefld) as x ->
b1b2de81
C
811
812 let fld = Ast_c.str_of_name namefld in
34e49164 813
91eba41f 814 k expr; (* recurse to set the types-ref of sub expressions *)
91eba41f 815
ae4735db
C
816 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
817
818 let topt =
91eba41f
C
819 match x with
820 | RecordAccess _ -> Some t
ae4735db
C
821 | RecordPtAccess _ ->
822 (match unwrap_unfold_env t with
91eba41f
C
823 | Pointer (t) -> Some t
824 | _ -> None
34e49164 825 )
91eba41f 826 | _ -> raise Impossible
ae4735db 827
91eba41f
C
828 in
829 (match topt with
830 | None -> Type_c.noTypeHere
ae4735db 831 | Some t ->
91eba41f 832 match unwrap_unfold_env t with
ae4735db
C
833 | StructUnion (su, sopt, fields) ->
834 (try
91eba41f 835 (* todo: which env ? *)
ae4735db 836 make_info_def_fix
91eba41f 837 (Type_c.type_field fld (su, fields))
ae4735db
C
838 with
839 | Not_found ->
840 pr2 (spf
91eba41f
C
841 "TYPE-ERROR: field '%s' does not belong in struct %s"
842 fld (match sopt with Some s -> s |_ -> "<anon>"));
843 Type_c.noTypeHere
ae4735db 844 | Multi_found ->
91eba41f
C
845 pr2 "TAC:MultiFound";
846 Type_c.noTypeHere
847 )
848 | _ -> Type_c.noTypeHere
34e49164 849 )
91eba41f 850 )
ae4735db 851
91eba41f
C
852
853
854 (* -------------------------------------------------- *)
ae4735db 855 | Cast (t, e) ->
91eba41f
C
856 k expr;
857 (* todo: if infer, can "push" info ? add_types_expr [t] e ? *)
858 make_info_def_fix (Lib.al_type t)
859
860 (* todo? lub, hmm maybe not, cos type must be e1 *)
ae4735db
C
861 | Assignment (e1, op, e2) ->
862 k expr;
b1b2de81
C
863 (* value of an assignment is the value of the RHS expression *)
864 Ast_c.get_type_expr e2
ae4735db
C
865 | Sequence (e1, e2) ->
866 k expr;
91eba41f 867 Ast_c.get_type_expr e2
ae4735db
C
868
869 | Binary (e1, Logical _, e2) ->
708f4980
C
870 k expr;
871 make_info_def (type_of_s "int")
872
91eba41f 873 (* todo: lub *)
ae4735db 874 | Binary (e1, Arith op, e2) ->
91eba41f 875 k expr;
708f4980 876 Type_c.lub op (Type_c.get_opt_type e1) (Type_c.get_opt_type e2)
91eba41f 877
ae4735db 878 | CondExpr (cond, e1opt, e2) ->
91eba41f
C
879 k expr;
880 Ast_c.get_type_expr e2
34e49164 881
34e49164 882
ae4735db 883 | ParenExpr e ->
91eba41f
C
884 k expr;
885 Ast_c.get_type_expr e
886
ae4735db 887 | Infix (e, op) | Postfix (e, op) ->
91eba41f
C
888 k expr;
889 Ast_c.get_type_expr e
ae4735db 890
91eba41f 891 (* pad: julia wrote this ? *)
ae4735db 892 | Unary (e, UnPlus) ->
91eba41f
C
893 k expr; (* recurse to set the types-ref of sub expressions *)
894 make_info_def (type_of_s "int")
895 (* todo? can convert from unsigned to signed if UnMinus ? *)
ae4735db 896 | Unary (e, UnMinus) ->
91eba41f
C
897 k expr; (* recurse to set the types-ref of sub expressions *)
898 make_info_def (type_of_s "int")
ae4735db
C
899
900 | SizeOfType _|SizeOfExpr _ ->
91eba41f
C
901 k expr; (* recurse to set the types-ref of sub expressions *)
902 make_info_def (type_of_s "int")
ae4735db
C
903
904 | Constructor (ft, ini) ->
91eba41f
C
905 k expr; (* recurse to set the types-ref of sub expressions *)
906 make_info_def (Lib.al_type ft)
ae4735db
C
907
908 | Unary (e, Not) ->
91eba41f 909 k expr; (* recurse to set the types-ref of sub expressions *)
5636bb2c
C
910 (* the result of ! is always 0 or 1, not the argument type *)
911 make_info_def (type_of_s "int")
ae4735db 912 | Unary (e, Tilde) ->
91eba41f
C
913 k expr; (* recurse to set the types-ref of sub expressions *)
914 Ast_c.get_type_expr e
ae4735db 915
91eba41f
C
916 (* -------------------------------------------------- *)
917 (* todo *)
ae4735db 918 | Unary (_, GetRefLabel) ->
91eba41f
C
919 k expr; (* recurse to set the types-ref of sub expressions *)
920 pr2_once "Type annotater:not handling GetRefLabel";
921 Type_c.noTypeHere
922 (* todo *)
ae4735db 923 | StatementExpr _ ->
91eba41f 924 k expr; (* recurse to set the types-ref of sub expressions *)
951c7801 925 pr2_once "Type annotater:not handling StatementExpr";
91eba41f
C
926 Type_c.noTypeHere
927 (*
928 | _ -> k expr; Type_c.noTypeHere
929 *)
ae4735db 930
91eba41f
C
931 in
932 Ast_c.set_type_expr expr ty
933
934)
935
ae4735db 936
91eba41f
C
937(*****************************************************************************)
938(* Visitor *)
939(*****************************************************************************)
940
941(* Processing includes that were added after a cpp_ast_c makes the
942 * type annotater quite slow, especially when the depth of cpp_ast_c is
943 * big. But for such includes the only thing we really want is to modify
944 * the environment to have enough type information. We don't need
945 * to type the expressions inside those includes (they will be typed
ae4735db 946 * when we process the include file directly). Here the goal is
91eba41f 947 * to not recurse.
ae4735db 948 *
91eba41f
C
949 * Note that as usually header files contain mostly structure
950 * definitions and defines, that means we still have to do lots of work.
ae4735db 951 * We only win on function definition bodies, but usually header files
91eba41f
C
952 * have just prototypes, or inline function definitions which anyway have
953 * usually a small body. But still, we win. It also makes clearer
954 * that when processing include as we just need the environment, the caller
ae4735db 955 * of this module can do further optimisations such as memorising the
91eba41f 956 * state of the environment after each header files.
ae4735db
C
957 *
958 *
91eba41f
C
959 * For sparse its makes the annotating speed goes from 9s to 4s
960 * For Linux the speedup is even better, from ??? to ???.
ae4735db 961 *
91eba41f
C
962 * Because There would be some copy paste with annotate_program, it is
963 * better to factorize code hence the just_add_in_env parameter below.
ae4735db 964 *
91eba41f
C
965 * todo? alternative optimisation for the include problem:
966 * - processing all headers files one time and construct big env
967 * - use hashtbl for env (but apparently not biggest problem)
968 *)
ae4735db
C
969
970let rec visit_toplevel ~just_add_in_env ~depth elem =
91eba41f
C
971 let need_annotate_body = not just_add_in_env in
972
ae4735db 973 let bigf = { Visitor_c.default_visitor_c with
91eba41f
C
974
975 (* ------------------------------------------------------------ *)
ae4735db 976 Visitor_c.kcppdirective = (fun (k, bigf) directive ->
91eba41f
C
977 match directive with
978 (* do error messages for type annotater only for the real body of the
979 * file, not inside include.
980 *)
ae4735db
C
981 | Include {i_content = opt} ->
982 opt +> Common.do_option (fun (filename, program) ->
983 Common.save_excursion Flag_parsing_c.verbose_type (fun () ->
91eba41f
C
984 Flag_parsing_c.verbose_type := false;
985
ae4735db 986 (* old: Visitor_c.vk_program bigf program;
91eba41f
C
987 * opti: set the just_add_in_env
988 *)
ae4735db 989 program +> List.iter (fun elem ->
91eba41f 990 visit_toplevel ~just_add_in_env:true ~depth:(depth+1) elem
34e49164 991 )
91eba41f 992 )
34e49164 993 )
91eba41f 994
ae4735db 995 | Define ((s,ii), (defkind, defval)) ->
91eba41f
C
996
997
998 (* even if we are in a just_add_in_env phase, such as when
ae4735db
C
999 * we process include, as opposed to the body of functions,
1000 * with macros we still to type the body of the macro as
91eba41f
C
1001 * the macro has no type and so we infer its type from its
1002 * body (and one day later maybe from its use).
1003 *)
1004 (match defval with
1005 (* can try to optimize and recurse only when the define body
ae4735db 1006 * is simple ?
91eba41f
C
1007 *)
1008
ae4735db 1009 | DefineExpr expr ->
951c7801
C
1010 (* prevent macro-declared variables from leaking out *)
1011 do_in_new_scope (fun () ->
1012 if is_simple_expr expr
91eba41f 1013 (* even if not need_annotate_body, still recurse*)
ae4735db
C
1014 then k directive
1015 else
951c7801
C
1016 if need_annotate_body
1017 then k directive)
ae4735db 1018 | _ ->
951c7801
C
1019 do_in_new_scope (fun () ->
1020 if need_annotate_body
1021 then k directive)
91eba41f
C
1022 );
1023
1024 add_binding (Macro (s, (defkind, defval) )) true;
1025
1026 | Undef _
1027 | PragmaAndCo _ -> ()
34e49164
C
1028 );
1029
91eba41f
C
1030 (* ------------------------------------------------------------ *)
1031 (* main typer code *)
1032 (* ------------------------------------------------------------ *)
1033 Visitor_c.kexpr = annotater_expr_visitor_subpart;
1034
1035 (* ------------------------------------------------------------ *)
ae4735db
C
1036 Visitor_c.kstatement = (fun (k, bigf) st ->
1037 match Ast_c.unwrap_st st with
708f4980 1038 | Compound statxs -> do_in_new_scope (fun () -> k st);
34e49164 1039 | _ -> k st
34e49164 1040 );
91eba41f 1041 (* ------------------------------------------------------------ *)
ae4735db 1042 Visitor_c.kdecl = (fun (k, bigf) d ->
34e49164 1043 (match d with
ae4735db 1044 | (DeclList (xs, ii)) ->
485bce71 1045 xs +> List.iter (fun ({v_namei = var; v_type = t;
978fd7e5
C
1046 v_storage = sto; v_local = local} as x
1047 , iicomma) ->
485bce71 1048
34e49164
C
1049 (* to add possible definition in type found in Decl *)
1050 Visitor_c.vk_type bigf t;
91eba41f
C
1051
1052
1053 let local =
1054 match local with
1055 | Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
978fd7e5 1056 | Ast_c.LocalDecl -> Ast_c.LocalVar (Ast_c.info_of_type t)
91eba41f 1057 in
ae4735db 1058 var +> Common.do_option (fun (name, iniopt) ->
b1b2de81
C
1059 let s = Ast_c.str_of_name name in
1060
ae4735db
C
1061 match sto with
1062 | StoTypedef, _inline ->
34e49164 1063 add_binding (TypeDef (s,Lib.al_type t)) true;
ae4735db 1064 | _ ->
34e49164 1065 add_binding (VarOrFunc (s, (Lib.al_type t, local))) true;
91eba41f 1066
ae4735db 1067 x.v_type_bis :=
978fd7e5 1068 Some (typedef_fix (Lib.al_type t) !_scoped_env);
91eba41f
C
1069
1070 if need_annotate_body then begin
1071 (* int x = sizeof(x) is legal so need process ini *)
ae4735db 1072 iniopt +> Common.do_option (fun (info, ini) ->
91eba41f
C
1073 Visitor_c.vk_ini bigf ini
1074 );
1075 end
34e49164
C
1076 );
1077 );
ae4735db 1078 | MacroDecl _ ->
91eba41f
C
1079 if need_annotate_body
1080 then k d
34e49164 1081 );
ae4735db 1082
34e49164
C
1083 );
1084
91eba41f 1085 (* ------------------------------------------------------------ *)
ae4735db
C
1086 Visitor_c.ktype = (fun (k, bigf) typ ->
1087 (* bugfix: have a 'Lib.al_type typ' before, but because we can
91eba41f 1088 * have enum with possible expression, we don't want to change
ae4735db 1089 * the ref of abstract-lined types, but the real one, so
91eba41f
C
1090 * don't al_type here
1091 *)
708f4980 1092 let (_q, tbis) = typ in
ae4735db
C
1093 match Ast_c.unwrap_typeC typ with
1094 | StructUnion (su, Some s, structType) ->
1095 let structType' = Lib.al_fields structType in
708f4980 1096 let ii = Ast_c.get_ii_typeC_take_care tbis in
91eba41f
C
1097 let ii' = Lib.al_ii ii in
1098 add_binding (StructUnionNameDef (s, ((su, structType'),ii'))) true;
1099
1100 if need_annotate_body
1101 then k typ (* todo: restrict ? new scope so use do_in_scope ? *)
1102
ae4735db 1103 | Enum (sopt, enums) ->
91eba41f 1104
ae4735db 1105 enums +> List.iter (fun ((name, eopt), iicomma) ->
b1b2de81
C
1106
1107 let s = Ast_c.str_of_name name in
91eba41f
C
1108
1109 if need_annotate_body
ae4735db 1110 then eopt +> Common.do_option (fun (ieq, e) ->
91eba41f
C
1111 Visitor_c.vk_expr bigf e
1112 );
1113 add_binding (EnumConstant (s, sopt)) true;
1114 );
34e49164
C
1115
1116
1117 (* TODO: if have a TypeName, then maybe can fill the option
1118 * information.
1119 *)
ae4735db 1120 | _ ->
91eba41f
C
1121 if need_annotate_body
1122 then k typ
ae4735db
C
1123
1124 );
34e49164 1125
91eba41f 1126 (* ------------------------------------------------------------ *)
ae4735db 1127 Visitor_c.ktoplevel = (fun (k, bigf) elem ->
34e49164
C
1128 _notyped_var := Hashtbl.create 100;
1129 match elem with
ae4735db 1130 | Definition def ->
b1b2de81 1131 let {f_name = name;
485bce71
C
1132 f_type = ((returnt, (paramst, b)) as ftyp);
1133 f_storage = sto;
91eba41f
C
1134 f_body = statxs;
1135 f_old_c_style = oldstyle;
ae4735db 1136 },ii
91eba41f 1137 = def
34e49164 1138 in
ae4735db
C
1139 let (i1, i2) =
1140 match ii with
1141 (* what is iifunc1? it should be a type. jll
002099fc
C
1142 * pad: it's the '(' in the function definition. The
1143 * return type is part of f_type.
1144 *)
ae4735db 1145 | iifunc1::iifunc2::ibrace1::ibrace2::ifakestart::isto ->
34e49164
C
1146 iifunc1, iifunc2
1147 | _ -> raise Impossible
1148 in
b1b2de81 1149 let funcs = Ast_c.str_of_name name in
91eba41f 1150
ae4735db
C
1151 (match oldstyle with
1152 | None ->
1153 let typ' =
708f4980 1154 Lib.al_type (Ast_c.mk_ty (FunctionType ftyp) [i1;i2]) in
91eba41f 1155
ae4735db 1156 add_binding (VarOrFunc (funcs, (typ',islocal i1.Ast_c.pinfo)))
91eba41f
C
1157 false;
1158
1159 if need_annotate_body then
ae4735db
C
1160 do_in_new_scope (fun () ->
1161 paramst +> List.iter (fun ({p_namei= nameopt; p_type= t},_)->
1162 match nameopt with
b1b2de81
C
1163 | Some name ->
1164 let s = Ast_c.str_of_name name in
978fd7e5 1165 let local = Ast_c.LocalVar (Ast_c.info_of_type t) in
91eba41f 1166 add_binding (VarOrFunc (s,(Lib.al_type t,local))) true
ae4735db 1167 | None ->
91eba41f
C
1168 pr2 "no type, certainly because Void type ?"
1169 );
1170 (* recurse *)
1171 k elem
1172 );
ae4735db 1173 | Some oldstyle ->
91eba41f
C
1174 (* generate regular function type *)
1175
ae4735db 1176 pr2 "TODO generate type for function";
91eba41f
C
1177 (* add bindings *)
1178 if need_annotate_body then
ae4735db 1179 do_in_new_scope (fun () ->
91eba41f 1180 (* recurse. should naturally call the kdecl visitor and
ae4735db 1181 * add binding
91eba41f
C
1182 *)
1183 k elem;
1184 );
1185
34e49164 1186 );
ae4735db 1187 | CppTop x ->
708f4980 1188 (match x with
ae4735db 1189 | Define ((s,ii), (DefineVar, DefineType t)) ->
708f4980
C
1190 add_binding (TypeDef (s,Lib.al_type t)) true;
1191 | _ -> k elem
ae4735db 1192 )
708f4980 1193
91eba41f
C
1194 | Declaration _
1195
708f4980
C
1196
1197
91eba41f 1198 | IfdefTop _
ae4735db 1199 | MacroTop _
91eba41f
C
1200 | EmptyDef _
1201 | NotParsedCorrectly _
1202 | FinalDef _
ae4735db 1203 ->
91eba41f 1204 k elem
34e49164 1205 );
ae4735db 1206 }
34e49164 1207 in
91eba41f 1208 if just_add_in_env
ae4735db
C
1209 then
1210 if depth > 1
91eba41f 1211 then Visitor_c.vk_toplevel bigf elem
ae4735db
C
1212 else
1213 Common.profile_code "TAC.annotate_only_included" (fun () ->
91eba41f
C
1214 Visitor_c.vk_toplevel bigf elem
1215 )
1216 else Visitor_c.vk_toplevel bigf elem
1217
1218(*****************************************************************************)
1219(* Entry point *)
1220(*****************************************************************************)
1221(* catch all the decl to grow the environment *)
1222
1223
ae4735db 1224let rec (annotate_program2 :
91eba41f
C
1225 environment -> toplevel list -> (toplevel * environment Common.pair) list) =
1226 fun env prog ->
1227
ae4735db 1228 (* globals (re)initialialisation *)
91eba41f
C
1229 _scoped_env := env;
1230 _notyped_var := (Hashtbl.create 100);
34e49164 1231
ae4735db 1232 prog +> List.map (fun elem ->
34e49164 1233 let beforeenv = !_scoped_env in
91eba41f 1234 visit_toplevel ~just_add_in_env:false ~depth:0 elem;
34e49164
C
1235 let afterenv = !_scoped_env in
1236 (elem, (beforeenv, afterenv))
1237 )
1238
91eba41f
C
1239
1240
1241
1242(*****************************************************************************)
1243(* Annotate test *)
1244(*****************************************************************************)
1245
ae4735db 1246(* julia: for coccinelle *)
34e49164
C
1247let annotate_test_expressions prog =
1248 let rec propagate_test e =
1249 let ((e_term,info),_) = e in
1250 let (ty,_) = !info in
1251 info := (ty,Test);
1252 match e_term with
1253 Binary(e1,Logical(AndLog),e2)
1254 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1255 | Unary(e1,Not) -> propagate_test e1
1256 | ParenExpr(e) -> propagate_test e
1257 | _ -> () in
1258
1259 let bigf = { Visitor_c.default_visitor_c with
1260 Visitor_c.kexpr = (fun (k,bigf) expr ->
708f4980
C
1261 (match unwrap_expr expr with
1262 CondExpr(e,_,_) -> propagate_test e
d6a55602
C
1263 | Binary(e1,Logical(AndLog),e2)
1264 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1265 | Unary(e1,Not) -> propagate_test e1
1266 | _ -> ()
91eba41f
C
1267 );
1268 k expr
1269 );
34e49164 1270 Visitor_c.kstatement = (fun (k, bigf) st ->
ae4735db 1271 match unwrap_st st with
34e49164
C
1272 Selection(s) ->
1273 (match s with If(e1,s1,s2) -> propagate_test e1 | _ -> ());
1274 k st;
1275 | Iteration(i) ->
1276 (match i with
1277 While(e,s) -> propagate_test e
1278 | DoWhile(s,e) -> propagate_test e
1279 | For(_,es,_,_) ->
1280 (match unwrap es with Some e -> propagate_test e | None -> ())
1281 | _ -> ());
1282 k st
91eba41f 1283 | _ -> k st
ae4735db 1284 )
91eba41f 1285 } in
ae4735db 1286 (prog +> List.iter (fun elem ->
34e49164
C
1287 Visitor_c.vk_toplevel bigf elem
1288 ))
1289
91eba41f
C
1290
1291
1292(*****************************************************************************)
1293(* Annotate types *)
1294(*****************************************************************************)
ae4735db 1295let annotate_program env prog =
91eba41f
C
1296 Common.profile_code "TAC.annotate_program"
1297 (fun () ->
1298 let res = annotate_program2 env prog in
34e49164 1299 annotate_test_expressions prog;
91eba41f
C
1300 res
1301 )
1302
ae4735db 1303let annotate_type_and_localvar env prog =
91eba41f
C
1304 Common.profile_code "TAC.annotate_type"
1305 (fun () -> annotate_program2 env prog)
1306
1307
1308(*****************************************************************************)
1309(* changing default typing environment, do concatenation *)
ae4735db 1310let init_env filename =
91eba41f
C
1311 pr2 ("init_env: " ^ filename);
1312 let (ast2, _stat) = Parse_c.parse_c_and_cpp filename in
1313 let ast = Parse_c.program_of_program2 ast2 in
1314
1315 let res = annotate_type_and_localvar !initial_env ast in
1316 match List.rev res with
1317 | [] -> pr2 "empty environment"
ae4735db 1318 | (_top,(env1,env2))::xs ->
91eba41f
C
1319 initial_env := !initial_env ++ env2;
1320 ()
1321