Release coccinelle-0.2.4rc5
[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 *)
5626f154
C
614 | Constant (String (s,kind)) -> make_info_def (type_of_s "char []")
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;
c491d8ee
C
863 (* value of an assignment is the value of the RHS expression, but its
864 type is the type of the lhs expression. Use the rhs exp if no
865 information is available *)
866 (match Ast_c.get_type_expr e1 with
867 (None,_) -> Ast_c.get_type_expr e2
868 | (Some ty,t) -> (Some ty,t))
ae4735db
C
869 | Sequence (e1, e2) ->
870 k expr;
91eba41f 871 Ast_c.get_type_expr e2
ae4735db
C
872
873 | Binary (e1, Logical _, e2) ->
708f4980
C
874 k expr;
875 make_info_def (type_of_s "int")
876
91eba41f 877 (* todo: lub *)
ae4735db 878 | Binary (e1, Arith op, e2) ->
91eba41f 879 k expr;
708f4980 880 Type_c.lub op (Type_c.get_opt_type e1) (Type_c.get_opt_type e2)
91eba41f 881
ae4735db 882 | CondExpr (cond, e1opt, e2) ->
91eba41f
C
883 k expr;
884 Ast_c.get_type_expr e2
34e49164 885
34e49164 886
ae4735db 887 | ParenExpr e ->
91eba41f
C
888 k expr;
889 Ast_c.get_type_expr e
890
ae4735db 891 | Infix (e, op) | Postfix (e, op) ->
91eba41f
C
892 k expr;
893 Ast_c.get_type_expr e
ae4735db 894
91eba41f 895 (* pad: julia wrote this ? *)
ae4735db 896 | Unary (e, UnPlus) ->
91eba41f
C
897 k expr; (* recurse to set the types-ref of sub expressions *)
898 make_info_def (type_of_s "int")
899 (* todo? can convert from unsigned to signed if UnMinus ? *)
ae4735db 900 | Unary (e, UnMinus) ->
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 | SizeOfType _|SizeOfExpr _ ->
91eba41f
C
905 k expr; (* recurse to set the types-ref of sub expressions *)
906 make_info_def (type_of_s "int")
ae4735db
C
907
908 | Constructor (ft, ini) ->
91eba41f
C
909 k expr; (* recurse to set the types-ref of sub expressions *)
910 make_info_def (Lib.al_type ft)
ae4735db
C
911
912 | Unary (e, Not) ->
91eba41f 913 k expr; (* recurse to set the types-ref of sub expressions *)
5636bb2c
C
914 (* the result of ! is always 0 or 1, not the argument type *)
915 make_info_def (type_of_s "int")
ae4735db 916 | Unary (e, Tilde) ->
91eba41f
C
917 k expr; (* recurse to set the types-ref of sub expressions *)
918 Ast_c.get_type_expr e
ae4735db 919
91eba41f
C
920 (* -------------------------------------------------- *)
921 (* todo *)
ae4735db 922 | Unary (_, GetRefLabel) ->
91eba41f
C
923 k expr; (* recurse to set the types-ref of sub expressions *)
924 pr2_once "Type annotater:not handling GetRefLabel";
925 Type_c.noTypeHere
926 (* todo *)
ae4735db 927 | StatementExpr _ ->
91eba41f 928 k expr; (* recurse to set the types-ref of sub expressions *)
951c7801 929 pr2_once "Type annotater:not handling StatementExpr";
91eba41f
C
930 Type_c.noTypeHere
931 (*
932 | _ -> k expr; Type_c.noTypeHere
933 *)
ae4735db 934
91eba41f
C
935 in
936 Ast_c.set_type_expr expr ty
937
938)
939
ae4735db 940
91eba41f
C
941(*****************************************************************************)
942(* Visitor *)
943(*****************************************************************************)
944
945(* Processing includes that were added after a cpp_ast_c makes the
946 * type annotater quite slow, especially when the depth of cpp_ast_c is
947 * big. But for such includes the only thing we really want is to modify
948 * the environment to have enough type information. We don't need
949 * to type the expressions inside those includes (they will be typed
ae4735db 950 * when we process the include file directly). Here the goal is
91eba41f 951 * to not recurse.
ae4735db 952 *
91eba41f
C
953 * Note that as usually header files contain mostly structure
954 * definitions and defines, that means we still have to do lots of work.
ae4735db 955 * We only win on function definition bodies, but usually header files
91eba41f
C
956 * have just prototypes, or inline function definitions which anyway have
957 * usually a small body. But still, we win. It also makes clearer
958 * that when processing include as we just need the environment, the caller
ae4735db 959 * of this module can do further optimisations such as memorising the
91eba41f 960 * state of the environment after each header files.
ae4735db
C
961 *
962 *
91eba41f
C
963 * For sparse its makes the annotating speed goes from 9s to 4s
964 * For Linux the speedup is even better, from ??? to ???.
ae4735db 965 *
91eba41f
C
966 * Because There would be some copy paste with annotate_program, it is
967 * better to factorize code hence the just_add_in_env parameter below.
ae4735db 968 *
91eba41f
C
969 * todo? alternative optimisation for the include problem:
970 * - processing all headers files one time and construct big env
971 * - use hashtbl for env (but apparently not biggest problem)
972 *)
ae4735db
C
973
974let rec visit_toplevel ~just_add_in_env ~depth elem =
91eba41f
C
975 let need_annotate_body = not just_add_in_env in
976
ae4735db 977 let bigf = { Visitor_c.default_visitor_c with
91eba41f
C
978
979 (* ------------------------------------------------------------ *)
ae4735db 980 Visitor_c.kcppdirective = (fun (k, bigf) directive ->
91eba41f
C
981 match directive with
982 (* do error messages for type annotater only for the real body of the
983 * file, not inside include.
984 *)
ae4735db
C
985 | Include {i_content = opt} ->
986 opt +> Common.do_option (fun (filename, program) ->
987 Common.save_excursion Flag_parsing_c.verbose_type (fun () ->
91eba41f
C
988 Flag_parsing_c.verbose_type := false;
989
ae4735db 990 (* old: Visitor_c.vk_program bigf program;
91eba41f
C
991 * opti: set the just_add_in_env
992 *)
ae4735db 993 program +> List.iter (fun elem ->
91eba41f 994 visit_toplevel ~just_add_in_env:true ~depth:(depth+1) elem
34e49164 995 )
91eba41f 996 )
34e49164 997 )
91eba41f 998
ae4735db 999 | Define ((s,ii), (defkind, defval)) ->
91eba41f
C
1000
1001
1002 (* even if we are in a just_add_in_env phase, such as when
ae4735db
C
1003 * we process include, as opposed to the body of functions,
1004 * with macros we still to type the body of the macro as
91eba41f
C
1005 * the macro has no type and so we infer its type from its
1006 * body (and one day later maybe from its use).
1007 *)
1008 (match defval with
1009 (* can try to optimize and recurse only when the define body
ae4735db 1010 * is simple ?
91eba41f
C
1011 *)
1012
ae4735db 1013 | DefineExpr expr ->
951c7801
C
1014 (* prevent macro-declared variables from leaking out *)
1015 do_in_new_scope (fun () ->
1016 if is_simple_expr expr
91eba41f 1017 (* even if not need_annotate_body, still recurse*)
ae4735db
C
1018 then k directive
1019 else
951c7801
C
1020 if need_annotate_body
1021 then k directive)
ae4735db 1022 | _ ->
951c7801
C
1023 do_in_new_scope (fun () ->
1024 if need_annotate_body
1025 then k directive)
91eba41f
C
1026 );
1027
1028 add_binding (Macro (s, (defkind, defval) )) true;
1029
1030 | Undef _
1031 | PragmaAndCo _ -> ()
34e49164
C
1032 );
1033
91eba41f
C
1034 (* ------------------------------------------------------------ *)
1035 (* main typer code *)
1036 (* ------------------------------------------------------------ *)
1037 Visitor_c.kexpr = annotater_expr_visitor_subpart;
1038
1039 (* ------------------------------------------------------------ *)
ae4735db
C
1040 Visitor_c.kstatement = (fun (k, bigf) st ->
1041 match Ast_c.unwrap_st st with
708f4980 1042 | Compound statxs -> do_in_new_scope (fun () -> k st);
34e49164 1043 | _ -> k st
34e49164 1044 );
91eba41f 1045 (* ------------------------------------------------------------ *)
ae4735db 1046 Visitor_c.kdecl = (fun (k, bigf) d ->
34e49164 1047 (match d with
ae4735db 1048 | (DeclList (xs, ii)) ->
485bce71 1049 xs +> List.iter (fun ({v_namei = var; v_type = t;
978fd7e5
C
1050 v_storage = sto; v_local = local} as x
1051 , iicomma) ->
485bce71 1052
34e49164
C
1053 (* to add possible definition in type found in Decl *)
1054 Visitor_c.vk_type bigf t;
91eba41f
C
1055
1056
1057 let local =
1058 match local with
1059 | Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
978fd7e5 1060 | Ast_c.LocalDecl -> Ast_c.LocalVar (Ast_c.info_of_type t)
91eba41f 1061 in
ae4735db 1062 var +> Common.do_option (fun (name, iniopt) ->
b1b2de81
C
1063 let s = Ast_c.str_of_name name in
1064
ae4735db
C
1065 match sto with
1066 | StoTypedef, _inline ->
34e49164 1067 add_binding (TypeDef (s,Lib.al_type t)) true;
ae4735db 1068 | _ ->
34e49164 1069 add_binding (VarOrFunc (s, (Lib.al_type t, local))) true;
91eba41f 1070
ae4735db 1071 x.v_type_bis :=
978fd7e5 1072 Some (typedef_fix (Lib.al_type t) !_scoped_env);
91eba41f
C
1073
1074 if need_annotate_body then begin
1075 (* int x = sizeof(x) is legal so need process ini *)
ae4735db 1076 iniopt +> Common.do_option (fun (info, ini) ->
91eba41f
C
1077 Visitor_c.vk_ini bigf ini
1078 );
1079 end
34e49164
C
1080 );
1081 );
ae4735db 1082 | MacroDecl _ ->
91eba41f
C
1083 if need_annotate_body
1084 then k d
34e49164 1085 );
ae4735db 1086
34e49164
C
1087 );
1088
91eba41f 1089 (* ------------------------------------------------------------ *)
ae4735db
C
1090 Visitor_c.ktype = (fun (k, bigf) typ ->
1091 (* bugfix: have a 'Lib.al_type typ' before, but because we can
91eba41f 1092 * have enum with possible expression, we don't want to change
ae4735db 1093 * the ref of abstract-lined types, but the real one, so
91eba41f
C
1094 * don't al_type here
1095 *)
708f4980 1096 let (_q, tbis) = typ in
ae4735db
C
1097 match Ast_c.unwrap_typeC typ with
1098 | StructUnion (su, Some s, structType) ->
1099 let structType' = Lib.al_fields structType in
708f4980 1100 let ii = Ast_c.get_ii_typeC_take_care tbis in
91eba41f
C
1101 let ii' = Lib.al_ii ii in
1102 add_binding (StructUnionNameDef (s, ((su, structType'),ii'))) true;
1103
1104 if need_annotate_body
1105 then k typ (* todo: restrict ? new scope so use do_in_scope ? *)
1106
ae4735db 1107 | Enum (sopt, enums) ->
91eba41f 1108
ae4735db 1109 enums +> List.iter (fun ((name, eopt), iicomma) ->
b1b2de81
C
1110
1111 let s = Ast_c.str_of_name name in
91eba41f
C
1112
1113 if need_annotate_body
ae4735db 1114 then eopt +> Common.do_option (fun (ieq, e) ->
91eba41f
C
1115 Visitor_c.vk_expr bigf e
1116 );
1117 add_binding (EnumConstant (s, sopt)) true;
1118 );
34e49164
C
1119
1120
1121 (* TODO: if have a TypeName, then maybe can fill the option
1122 * information.
1123 *)
ae4735db 1124 | _ ->
91eba41f
C
1125 if need_annotate_body
1126 then k typ
ae4735db
C
1127
1128 );
34e49164 1129
91eba41f 1130 (* ------------------------------------------------------------ *)
ae4735db 1131 Visitor_c.ktoplevel = (fun (k, bigf) elem ->
34e49164
C
1132 _notyped_var := Hashtbl.create 100;
1133 match elem with
ae4735db 1134 | Definition def ->
b1b2de81 1135 let {f_name = name;
485bce71
C
1136 f_type = ((returnt, (paramst, b)) as ftyp);
1137 f_storage = sto;
91eba41f
C
1138 f_body = statxs;
1139 f_old_c_style = oldstyle;
ae4735db 1140 },ii
91eba41f 1141 = def
34e49164 1142 in
ae4735db
C
1143 let (i1, i2) =
1144 match ii with
1145 (* what is iifunc1? it should be a type. jll
002099fc
C
1146 * pad: it's the '(' in the function definition. The
1147 * return type is part of f_type.
1148 *)
ae4735db 1149 | iifunc1::iifunc2::ibrace1::ibrace2::ifakestart::isto ->
34e49164
C
1150 iifunc1, iifunc2
1151 | _ -> raise Impossible
1152 in
b1b2de81 1153 let funcs = Ast_c.str_of_name name in
91eba41f 1154
ae4735db
C
1155 (match oldstyle with
1156 | None ->
1157 let typ' =
708f4980 1158 Lib.al_type (Ast_c.mk_ty (FunctionType ftyp) [i1;i2]) in
91eba41f 1159
ae4735db 1160 add_binding (VarOrFunc (funcs, (typ',islocal i1.Ast_c.pinfo)))
91eba41f
C
1161 false;
1162
1163 if need_annotate_body then
ae4735db
C
1164 do_in_new_scope (fun () ->
1165 paramst +> List.iter (fun ({p_namei= nameopt; p_type= t},_)->
1166 match nameopt with
b1b2de81
C
1167 | Some name ->
1168 let s = Ast_c.str_of_name name in
978fd7e5 1169 let local = Ast_c.LocalVar (Ast_c.info_of_type t) in
91eba41f 1170 add_binding (VarOrFunc (s,(Lib.al_type t,local))) true
ae4735db 1171 | None ->
91eba41f
C
1172 pr2 "no type, certainly because Void type ?"
1173 );
1174 (* recurse *)
1175 k elem
1176 );
ae4735db 1177 | Some oldstyle ->
91eba41f
C
1178 (* generate regular function type *)
1179
ae4735db 1180 pr2 "TODO generate type for function";
91eba41f
C
1181 (* add bindings *)
1182 if need_annotate_body then
ae4735db 1183 do_in_new_scope (fun () ->
91eba41f 1184 (* recurse. should naturally call the kdecl visitor and
ae4735db 1185 * add binding
91eba41f
C
1186 *)
1187 k elem;
1188 );
1189
34e49164 1190 );
ae4735db 1191 | CppTop x ->
708f4980 1192 (match x with
ae4735db 1193 | Define ((s,ii), (DefineVar, DefineType t)) ->
708f4980
C
1194 add_binding (TypeDef (s,Lib.al_type t)) true;
1195 | _ -> k elem
ae4735db 1196 )
708f4980 1197
91eba41f
C
1198 | Declaration _
1199
708f4980
C
1200
1201
91eba41f 1202 | IfdefTop _
ae4735db 1203 | MacroTop _
91eba41f
C
1204 | EmptyDef _
1205 | NotParsedCorrectly _
1206 | FinalDef _
ae4735db 1207 ->
91eba41f 1208 k elem
34e49164 1209 );
ae4735db 1210 }
34e49164 1211 in
91eba41f 1212 if just_add_in_env
ae4735db
C
1213 then
1214 if depth > 1
91eba41f 1215 then Visitor_c.vk_toplevel bigf elem
ae4735db
C
1216 else
1217 Common.profile_code "TAC.annotate_only_included" (fun () ->
91eba41f
C
1218 Visitor_c.vk_toplevel bigf elem
1219 )
1220 else Visitor_c.vk_toplevel bigf elem
1221
1222(*****************************************************************************)
1223(* Entry point *)
1224(*****************************************************************************)
1225(* catch all the decl to grow the environment *)
1226
1227
ae4735db 1228let rec (annotate_program2 :
91eba41f
C
1229 environment -> toplevel list -> (toplevel * environment Common.pair) list) =
1230 fun env prog ->
1231
ae4735db 1232 (* globals (re)initialialisation *)
91eba41f
C
1233 _scoped_env := env;
1234 _notyped_var := (Hashtbl.create 100);
34e49164 1235
ae4735db 1236 prog +> List.map (fun elem ->
34e49164 1237 let beforeenv = !_scoped_env in
91eba41f 1238 visit_toplevel ~just_add_in_env:false ~depth:0 elem;
34e49164
C
1239 let afterenv = !_scoped_env in
1240 (elem, (beforeenv, afterenv))
1241 )
1242
91eba41f
C
1243
1244
1245
1246(*****************************************************************************)
1247(* Annotate test *)
1248(*****************************************************************************)
1249
ae4735db 1250(* julia: for coccinelle *)
34e49164
C
1251let annotate_test_expressions prog =
1252 let rec propagate_test e =
1253 let ((e_term,info),_) = e in
1254 let (ty,_) = !info in
1255 info := (ty,Test);
1256 match e_term with
1257 Binary(e1,Logical(AndLog),e2)
1258 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1259 | Unary(e1,Not) -> propagate_test e1
1260 | ParenExpr(e) -> propagate_test e
1261 | _ -> () in
1262
1263 let bigf = { Visitor_c.default_visitor_c with
1264 Visitor_c.kexpr = (fun (k,bigf) expr ->
708f4980
C
1265 (match unwrap_expr expr with
1266 CondExpr(e,_,_) -> propagate_test e
d6a55602
C
1267 | Binary(e1,Logical(AndLog),e2)
1268 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1269 | Unary(e1,Not) -> propagate_test e1
1270 | _ -> ()
91eba41f
C
1271 );
1272 k expr
1273 );
34e49164 1274 Visitor_c.kstatement = (fun (k, bigf) st ->
ae4735db 1275 match unwrap_st st with
34e49164
C
1276 Selection(s) ->
1277 (match s with If(e1,s1,s2) -> propagate_test e1 | _ -> ());
1278 k st;
1279 | Iteration(i) ->
1280 (match i with
1281 While(e,s) -> propagate_test e
1282 | DoWhile(s,e) -> propagate_test e
1283 | For(_,es,_,_) ->
1284 (match unwrap es with Some e -> propagate_test e | None -> ())
1285 | _ -> ());
1286 k st
91eba41f 1287 | _ -> k st
ae4735db 1288 )
91eba41f 1289 } in
ae4735db 1290 (prog +> List.iter (fun elem ->
34e49164
C
1291 Visitor_c.vk_toplevel bigf elem
1292 ))
1293
91eba41f
C
1294
1295
1296(*****************************************************************************)
1297(* Annotate types *)
1298(*****************************************************************************)
ae4735db 1299let annotate_program env prog =
91eba41f
C
1300 Common.profile_code "TAC.annotate_program"
1301 (fun () ->
1302 let res = annotate_program2 env prog in
34e49164 1303 annotate_test_expressions prog;
91eba41f
C
1304 res
1305 )
1306
ae4735db 1307let annotate_type_and_localvar env prog =
91eba41f
C
1308 Common.profile_code "TAC.annotate_type"
1309 (fun () -> annotate_program2 env prog)
1310
1311
1312(*****************************************************************************)
1313(* changing default typing environment, do concatenation *)
ae4735db 1314let init_env filename =
91eba41f
C
1315 pr2 ("init_env: " ^ filename);
1316 let (ast2, _stat) = Parse_c.parse_c_and_cpp filename in
1317 let ast = Parse_c.program_of_program2 ast2 in
1318
1319 let res = annotate_type_and_localvar !initial_env ast in
1320 match List.rev res with
1321 | [] -> pr2 "empty environment"
ae4735db 1322 | (_top,(env1,env2))::xs ->
91eba41f
C
1323 initial_env := !initial_env ++ env2;
1324 ()
1325