Release coccinelle-0.2.5-rc2
[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 649 | Ident (ident) ->
91eba41f 650 (* recurse *)
ae4735db 651 args +> List.iter (fun (e,ii) ->
91eba41f
C
652 (* could typecheck if arguments agree with prototype *)
653 Visitor_c.vk_argument bigf e
654 );
b1b2de81 655 let s = Ast_c.str_of_name ident in
91eba41f 656 (match lookup_opt_env lookup_var s with
ae4735db
C
657 | Some ((typ,local),_nextenv) ->
658
91eba41f
C
659 (* set type for ident *)
660 let tyinfo = make_info_fix (typ, local) in
661 Ast_c.set_type_expr e1 tyinfo;
662
663 (match unwrap_unfold_env typ with
664 | FunctionType (ret, params) -> make_info_def ret
665
ae4735db 666 (* can be function pointer, C have an iso for that,
91eba41f
C
667 * same pfn() syntax than regular function call.
668 *)
ae4735db 669 | Pointer (typ2) ->
91eba41f
C
670 (match unwrap_unfold_env typ2 with
671 | FunctionType (ret, params) -> make_info_def ret
672 | _ -> Type_c.noTypeHere
673 )
674 | _ -> Type_c.noTypeHere
675 )
ae4735db 676 | None ->
91eba41f
C
677
678 (match lookup_opt_env lookup_macro s with
ae4735db 679 | Some ((defkind, defval), _nextenv) ->
91eba41f 680 (match defkind, defval with
ae4735db 681 | DefineFunc _, DefineExpr e ->
91eba41f
C
682 let rettype = Ast_c.get_onlytype_expr e in
683
684 (* todo: could also set type for ident ?
685 have return type and at least type of concrete
686 parameters so can generate a fake FunctionType
687 *)
ae4735db 688 let macrotype_opt =
91eba41f
C
689 Type_c.fake_function_type rettype args
690 in
691
ae4735db 692 macrotype_opt +> Common.do_option (fun t ->
91eba41f
C
693 pr2 ("Type_annotater: generate fake function type" ^
694 "for macro: " ^ s);
695 let tyinfo = make_info_def_fix t in
696 Ast_c.set_type_expr e1 tyinfo;
697 );
698
699 Ast_c.get_type_expr e
ae4735db 700 | DefineVar, _ ->
91eba41f
C
701 pr2 ("Type_annoter: not a macro-func: " ^ s);
702 Type_c.noTypeHere
3a314143
C
703 | Undef, _ ->
704 pr2 ("Type_annoter: not a macro-func: " ^ s);
705 Type_c.noTypeHere
ae4735db 706 | DefineFunc _, _ ->
3a314143 707 (* normally the FunCall case should have caught it *)
91eba41f
C
708 pr2 ("Type_annoter: not a macro-func-expr: " ^ s);
709 Type_c.noTypeHere
710 )
ae4735db 711 | None ->
0708f913 712 pr2_once ("type_annotater: no type for function ident: " ^ s);
91eba41f
C
713 Type_c.noTypeHere
714 )
715 )
34e49164 716
34e49164 717
ae4735db 718 | _e ->
91eba41f 719 k expr;
ae4735db
C
720
721 (Ast_c.get_type_expr e1) +> Type_c.do_with_type (fun typ ->
722 (* copy paste of above *)
91eba41f
C
723 (match unwrap_unfold_env typ with
724 | FunctionType (ret, params) -> make_info_def ret
ae4735db 725 | Pointer (typ) ->
91eba41f
C
726 (match unwrap_unfold_env typ with
727 | FunctionType (ret, params) -> make_info_def ret
728 | _ -> Type_c.noTypeHere
729 )
730 | _ -> Type_c.noTypeHere
34e49164 731 )
91eba41f 732 )
708f4980 733 )
91eba41f
C
734
735
736 (* -------------------------------------------------- *)
ae4735db 737 | Ident (ident) ->
b1b2de81 738 let s = Ast_c.str_of_name ident in
91eba41f 739 (match lookup_opt_env lookup_var s with
ae4735db 740 | Some ((typ,local),_nextenv) ->
91eba41f 741 make_info_fix (typ,local)
ae4735db 742 | None ->
91eba41f 743 (match lookup_opt_env lookup_macro s with
ae4735db 744 | Some ((defkind, defval), _nextenv) ->
91eba41f 745 (match defkind, defval with
ae4735db 746 | DefineVar, DefineExpr e ->
91eba41f 747 Ast_c.get_type_expr e
ae4735db 748 | DefineVar, _ ->
91eba41f
C
749 pr2 ("Type_annoter: not a expression: " ^ s);
750 Type_c.noTypeHere
ae4735db 751 | DefineFunc _, _ ->
91eba41f
C
752 (* normally the FunCall case should have catch it *)
753 pr2 ("Type_annoter: not a macro-var: " ^ s);
754 Type_c.noTypeHere
3a314143
C
755 | Undef, _ ->
756 pr2 ("Type_annoter: not a expression: " ^ s);
757 Type_c.noTypeHere
91eba41f 758 )
ae4735db 759 | None ->
91eba41f 760 (match lookup_opt_env lookup_enum s with
ae4735db
C
761 | Some (_, _nextenv) ->
762 make_info_def (type_of_s "int")
763 | None ->
91eba41f 764 if not (s =~ "[A-Z_]+") (* if macro then no warning *)
ae4735db
C
765 then
766 if !Flag_parsing_c.check_annotater then
91eba41f 767 if not (Hashtbl.mem !_notyped_var s)
ae4735db 768 then begin
002099fc 769 pr2 ("Type_annoter: no type found for: " ^ s);
91eba41f
C
770 Hashtbl.add !_notyped_var s true;
771 end
772 else ()
ae4735db 773 else
002099fc 774 pr2 ("Type_annoter: no type found for: " ^ s)
91eba41f
C
775 ;
776 Type_c.noTypeHere
777 )
778 )
779 )
ae4735db 780
91eba41f
C
781 (* -------------------------------------------------- *)
782 (* C isomorphism on type on array and pointers *)
783 | Unary (e, DeRef)
784 | ArrayAccess (e, _) ->
785 k expr; (* recurse to set the types-ref of sub expressions *)
786
ae4735db 787 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
91eba41f
C
788 (* todo: maybe not good env !! *)
789 match unwrap_unfold_env t with
ae4735db
C
790 | Pointer x
791 | Array (_, x) ->
91eba41f
C
792 make_info_def_fix x
793 | _ -> Type_c.noTypeHere
794
795 )
796
ae4735db 797 | Unary (e, GetRef) ->
91eba41f
C
798 k expr; (* recurse to set the types-ref of sub expressions *)
799
ae4735db
C
800 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
801 (* must generate an element so that '=' can be used
91eba41f
C
802 * to compare type ?
803 *)
804 let fake = Ast_c.fakeInfo Common.fake_parse_info in
805 let fake = Ast_c.rewrap_str "*" fake in
ae4735db 806
708f4980 807 let ft = Ast_c.mk_ty (Pointer t) [fake] in
91eba41f
C
808 make_info_def_fix ft
809 )
810
811
812 (* -------------------------------------------------- *)
813 (* fields *)
ae4735db
C
814 | RecordAccess (e, namefld)
815 | RecordPtAccess (e, namefld) as x ->
b1b2de81
C
816
817 let fld = Ast_c.str_of_name namefld in
34e49164 818
91eba41f 819 k expr; (* recurse to set the types-ref of sub expressions *)
91eba41f 820
ae4735db
C
821 (Ast_c.get_type_expr e) +> Type_c.do_with_type (fun t ->
822
823 let topt =
91eba41f
C
824 match x with
825 | RecordAccess _ -> Some t
ae4735db
C
826 | RecordPtAccess _ ->
827 (match unwrap_unfold_env t with
91eba41f
C
828 | Pointer (t) -> Some t
829 | _ -> None
34e49164 830 )
91eba41f 831 | _ -> raise Impossible
ae4735db 832
91eba41f
C
833 in
834 (match topt with
835 | None -> Type_c.noTypeHere
ae4735db 836 | Some t ->
91eba41f 837 match unwrap_unfold_env t with
ae4735db
C
838 | StructUnion (su, sopt, fields) ->
839 (try
91eba41f 840 (* todo: which env ? *)
ae4735db 841 make_info_def_fix
91eba41f 842 (Type_c.type_field fld (su, fields))
ae4735db
C
843 with
844 | Not_found ->
845 pr2 (spf
91eba41f
C
846 "TYPE-ERROR: field '%s' does not belong in struct %s"
847 fld (match sopt with Some s -> s |_ -> "<anon>"));
848 Type_c.noTypeHere
ae4735db 849 | Multi_found ->
91eba41f
C
850 pr2 "TAC:MultiFound";
851 Type_c.noTypeHere
852 )
853 | _ -> Type_c.noTypeHere
34e49164 854 )
91eba41f 855 )
ae4735db 856
91eba41f
C
857
858
859 (* -------------------------------------------------- *)
ae4735db 860 | Cast (t, e) ->
91eba41f
C
861 k expr;
862 (* todo: if infer, can "push" info ? add_types_expr [t] e ? *)
863 make_info_def_fix (Lib.al_type t)
864
865 (* todo? lub, hmm maybe not, cos type must be e1 *)
ae4735db
C
866 | Assignment (e1, op, e2) ->
867 k expr;
c491d8ee
C
868 (* value of an assignment is the value of the RHS expression, but its
869 type is the type of the lhs expression. Use the rhs exp if no
870 information is available *)
871 (match Ast_c.get_type_expr e1 with
872 (None,_) -> Ast_c.get_type_expr e2
873 | (Some ty,t) -> (Some ty,t))
ae4735db
C
874 | Sequence (e1, e2) ->
875 k expr;
91eba41f 876 Ast_c.get_type_expr e2
ae4735db
C
877
878 | Binary (e1, Logical _, e2) ->
708f4980
C
879 k expr;
880 make_info_def (type_of_s "int")
881
91eba41f 882 (* todo: lub *)
ae4735db 883 | Binary (e1, Arith op, e2) ->
91eba41f 884 k expr;
708f4980 885 Type_c.lub op (Type_c.get_opt_type e1) (Type_c.get_opt_type e2)
91eba41f 886
ae4735db 887 | CondExpr (cond, e1opt, e2) ->
91eba41f
C
888 k expr;
889 Ast_c.get_type_expr e2
34e49164 890
34e49164 891
ae4735db 892 | ParenExpr e ->
91eba41f
C
893 k expr;
894 Ast_c.get_type_expr e
895
ae4735db 896 | Infix (e, op) | Postfix (e, op) ->
91eba41f
C
897 k expr;
898 Ast_c.get_type_expr e
ae4735db 899
91eba41f 900 (* pad: julia wrote this ? *)
ae4735db 901 | Unary (e, UnPlus) ->
91eba41f
C
902 k expr; (* recurse to set the types-ref of sub expressions *)
903 make_info_def (type_of_s "int")
904 (* todo? can convert from unsigned to signed if UnMinus ? *)
ae4735db 905 | Unary (e, UnMinus) ->
91eba41f
C
906 k expr; (* recurse to set the types-ref of sub expressions *)
907 make_info_def (type_of_s "int")
ae4735db
C
908
909 | SizeOfType _|SizeOfExpr _ ->
91eba41f 910 k expr; (* recurse to set the types-ref of sub expressions *)
1eddfd50 911 make_info_def (type_of_s "size_t")
ae4735db
C
912
913 | Constructor (ft, ini) ->
91eba41f
C
914 k expr; (* recurse to set the types-ref of sub expressions *)
915 make_info_def (Lib.al_type ft)
ae4735db
C
916
917 | Unary (e, Not) ->
91eba41f 918 k expr; (* recurse to set the types-ref of sub expressions *)
5636bb2c
C
919 (* the result of ! is always 0 or 1, not the argument type *)
920 make_info_def (type_of_s "int")
ae4735db 921 | Unary (e, Tilde) ->
91eba41f
C
922 k expr; (* recurse to set the types-ref of sub expressions *)
923 Ast_c.get_type_expr e
ae4735db 924
91eba41f
C
925 (* -------------------------------------------------- *)
926 (* todo *)
ae4735db 927 | Unary (_, GetRefLabel) ->
91eba41f
C
928 k expr; (* recurse to set the types-ref of sub expressions *)
929 pr2_once "Type annotater:not handling GetRefLabel";
930 Type_c.noTypeHere
931 (* todo *)
ae4735db 932 | StatementExpr _ ->
91eba41f 933 k expr; (* recurse to set the types-ref of sub expressions *)
951c7801 934 pr2_once "Type annotater:not handling StatementExpr";
91eba41f
C
935 Type_c.noTypeHere
936 (*
937 | _ -> k expr; Type_c.noTypeHere
938 *)
ae4735db 939
91eba41f
C
940 in
941 Ast_c.set_type_expr expr ty
942
943)
944
ae4735db 945
91eba41f
C
946(*****************************************************************************)
947(* Visitor *)
948(*****************************************************************************)
949
950(* Processing includes that were added after a cpp_ast_c makes the
951 * type annotater quite slow, especially when the depth of cpp_ast_c is
952 * big. But for such includes the only thing we really want is to modify
953 * the environment to have enough type information. We don't need
954 * to type the expressions inside those includes (they will be typed
ae4735db 955 * when we process the include file directly). Here the goal is
91eba41f 956 * to not recurse.
ae4735db 957 *
91eba41f
C
958 * Note that as usually header files contain mostly structure
959 * definitions and defines, that means we still have to do lots of work.
ae4735db 960 * We only win on function definition bodies, but usually header files
91eba41f
C
961 * have just prototypes, or inline function definitions which anyway have
962 * usually a small body. But still, we win. It also makes clearer
963 * that when processing include as we just need the environment, the caller
ae4735db 964 * of this module can do further optimisations such as memorising the
91eba41f 965 * state of the environment after each header files.
ae4735db
C
966 *
967 *
91eba41f
C
968 * For sparse its makes the annotating speed goes from 9s to 4s
969 * For Linux the speedup is even better, from ??? to ???.
ae4735db 970 *
91eba41f
C
971 * Because There would be some copy paste with annotate_program, it is
972 * better to factorize code hence the just_add_in_env parameter below.
ae4735db 973 *
91eba41f
C
974 * todo? alternative optimisation for the include problem:
975 * - processing all headers files one time and construct big env
976 * - use hashtbl for env (but apparently not biggest problem)
977 *)
ae4735db
C
978
979let rec visit_toplevel ~just_add_in_env ~depth elem =
91eba41f
C
980 let need_annotate_body = not just_add_in_env in
981
ae4735db 982 let bigf = { Visitor_c.default_visitor_c with
91eba41f
C
983
984 (* ------------------------------------------------------------ *)
ae4735db 985 Visitor_c.kcppdirective = (fun (k, bigf) directive ->
91eba41f
C
986 match directive with
987 (* do error messages for type annotater only for the real body of the
988 * file, not inside include.
989 *)
ae4735db
C
990 | Include {i_content = opt} ->
991 opt +> Common.do_option (fun (filename, program) ->
992 Common.save_excursion Flag_parsing_c.verbose_type (fun () ->
91eba41f
C
993 Flag_parsing_c.verbose_type := false;
994
ae4735db 995 (* old: Visitor_c.vk_program bigf program;
91eba41f
C
996 * opti: set the just_add_in_env
997 *)
ae4735db 998 program +> List.iter (fun elem ->
91eba41f 999 visit_toplevel ~just_add_in_env:true ~depth:(depth+1) elem
34e49164 1000 )
91eba41f 1001 )
34e49164 1002 )
91eba41f 1003
ae4735db 1004 | Define ((s,ii), (defkind, defval)) ->
91eba41f
C
1005
1006
1007 (* even if we are in a just_add_in_env phase, such as when
ae4735db
C
1008 * we process include, as opposed to the body of functions,
1009 * with macros we still to type the body of the macro as
91eba41f
C
1010 * the macro has no type and so we infer its type from its
1011 * body (and one day later maybe from its use).
1012 *)
1013 (match defval with
1014 (* can try to optimize and recurse only when the define body
ae4735db 1015 * is simple ?
91eba41f
C
1016 *)
1017
ae4735db 1018 | DefineExpr expr ->
951c7801
C
1019 (* prevent macro-declared variables from leaking out *)
1020 do_in_new_scope (fun () ->
1021 if is_simple_expr expr
91eba41f 1022 (* even if not need_annotate_body, still recurse*)
ae4735db
C
1023 then k directive
1024 else
951c7801
C
1025 if need_annotate_body
1026 then k directive)
ae4735db 1027 | _ ->
951c7801
C
1028 do_in_new_scope (fun () ->
1029 if need_annotate_body
1030 then k directive)
91eba41f
C
1031 );
1032
1033 add_binding (Macro (s, (defkind, defval) )) true;
1034
91eba41f 1035 | PragmaAndCo _ -> ()
34e49164
C
1036 );
1037
91eba41f
C
1038 (* ------------------------------------------------------------ *)
1039 (* main typer code *)
1040 (* ------------------------------------------------------------ *)
1041 Visitor_c.kexpr = annotater_expr_visitor_subpart;
1042
1043 (* ------------------------------------------------------------ *)
ae4735db
C
1044 Visitor_c.kstatement = (fun (k, bigf) st ->
1045 match Ast_c.unwrap_st st with
708f4980 1046 | Compound statxs -> do_in_new_scope (fun () -> k st);
34e49164 1047 | _ -> k st
34e49164 1048 );
91eba41f 1049 (* ------------------------------------------------------------ *)
ae4735db 1050 Visitor_c.kdecl = (fun (k, bigf) d ->
34e49164 1051 (match d with
ae4735db 1052 | (DeclList (xs, ii)) ->
485bce71 1053 xs +> List.iter (fun ({v_namei = var; v_type = t;
978fd7e5
C
1054 v_storage = sto; v_local = local} as x
1055 , iicomma) ->
485bce71 1056
34e49164
C
1057 (* to add possible definition in type found in Decl *)
1058 Visitor_c.vk_type bigf t;
91eba41f
C
1059
1060
1061 let local =
1062 match local with
1063 | Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
978fd7e5 1064 | Ast_c.LocalDecl -> Ast_c.LocalVar (Ast_c.info_of_type t)
91eba41f 1065 in
ae4735db 1066 var +> Common.do_option (fun (name, iniopt) ->
b1b2de81
C
1067 let s = Ast_c.str_of_name name in
1068
ae4735db
C
1069 match sto with
1070 | StoTypedef, _inline ->
34e49164 1071 add_binding (TypeDef (s,Lib.al_type t)) true;
ae4735db 1072 | _ ->
34e49164 1073 add_binding (VarOrFunc (s, (Lib.al_type t, local))) true;
91eba41f 1074
ae4735db 1075 x.v_type_bis :=
978fd7e5 1076 Some (typedef_fix (Lib.al_type t) !_scoped_env);
91eba41f
C
1077
1078 if need_annotate_body then begin
1079 (* int x = sizeof(x) is legal so need process ini *)
ae4735db 1080 iniopt +> Common.do_option (fun (info, ini) ->
91eba41f
C
1081 Visitor_c.vk_ini bigf ini
1082 );
1083 end
34e49164
C
1084 );
1085 );
ae4735db 1086 | MacroDecl _ ->
91eba41f
C
1087 if need_annotate_body
1088 then k d
34e49164 1089 );
ae4735db 1090
34e49164
C
1091 );
1092
91eba41f 1093 (* ------------------------------------------------------------ *)
ae4735db
C
1094 Visitor_c.ktype = (fun (k, bigf) typ ->
1095 (* bugfix: have a 'Lib.al_type typ' before, but because we can
91eba41f 1096 * have enum with possible expression, we don't want to change
ae4735db 1097 * the ref of abstract-lined types, but the real one, so
91eba41f
C
1098 * don't al_type here
1099 *)
708f4980 1100 let (_q, tbis) = typ in
ae4735db
C
1101 match Ast_c.unwrap_typeC typ with
1102 | StructUnion (su, Some s, structType) ->
1103 let structType' = Lib.al_fields structType in
708f4980 1104 let ii = Ast_c.get_ii_typeC_take_care tbis in
91eba41f
C
1105 let ii' = Lib.al_ii ii in
1106 add_binding (StructUnionNameDef (s, ((su, structType'),ii'))) true;
1107
1108 if need_annotate_body
1109 then k typ (* todo: restrict ? new scope so use do_in_scope ? *)
1110
ae4735db 1111 | Enum (sopt, enums) ->
91eba41f 1112
ae4735db 1113 enums +> List.iter (fun ((name, eopt), iicomma) ->
b1b2de81
C
1114
1115 let s = Ast_c.str_of_name name in
91eba41f
C
1116
1117 if need_annotate_body
ae4735db 1118 then eopt +> Common.do_option (fun (ieq, e) ->
91eba41f
C
1119 Visitor_c.vk_expr bigf e
1120 );
1121 add_binding (EnumConstant (s, sopt)) true;
1122 );
34e49164
C
1123
1124
1125 (* TODO: if have a TypeName, then maybe can fill the option
1126 * information.
1127 *)
ae4735db 1128 | _ ->
91eba41f
C
1129 if need_annotate_body
1130 then k typ
ae4735db
C
1131
1132 );
34e49164 1133
91eba41f 1134 (* ------------------------------------------------------------ *)
ae4735db 1135 Visitor_c.ktoplevel = (fun (k, bigf) elem ->
34e49164
C
1136 _notyped_var := Hashtbl.create 100;
1137 match elem with
ae4735db 1138 | Definition def ->
b1b2de81 1139 let {f_name = name;
485bce71
C
1140 f_type = ((returnt, (paramst, b)) as ftyp);
1141 f_storage = sto;
91eba41f
C
1142 f_body = statxs;
1143 f_old_c_style = oldstyle;
ae4735db 1144 },ii
91eba41f 1145 = def
34e49164 1146 in
ae4735db
C
1147 let (i1, i2) =
1148 match ii with
1149 (* what is iifunc1? it should be a type. jll
002099fc
C
1150 * pad: it's the '(' in the function definition. The
1151 * return type is part of f_type.
1152 *)
ae4735db 1153 | iifunc1::iifunc2::ibrace1::ibrace2::ifakestart::isto ->
34e49164
C
1154 iifunc1, iifunc2
1155 | _ -> raise Impossible
1156 in
b1b2de81 1157 let funcs = Ast_c.str_of_name name in
91eba41f 1158
ae4735db
C
1159 (match oldstyle with
1160 | None ->
1161 let typ' =
708f4980 1162 Lib.al_type (Ast_c.mk_ty (FunctionType ftyp) [i1;i2]) in
91eba41f 1163
ae4735db 1164 add_binding (VarOrFunc (funcs, (typ',islocal i1.Ast_c.pinfo)))
91eba41f
C
1165 false;
1166
1167 if need_annotate_body then
ae4735db
C
1168 do_in_new_scope (fun () ->
1169 paramst +> List.iter (fun ({p_namei= nameopt; p_type= t},_)->
1170 match nameopt with
b1b2de81
C
1171 | Some name ->
1172 let s = Ast_c.str_of_name name in
978fd7e5 1173 let local = Ast_c.LocalVar (Ast_c.info_of_type t) in
91eba41f 1174 add_binding (VarOrFunc (s,(Lib.al_type t,local))) true
ae4735db 1175 | None ->
91eba41f
C
1176 pr2 "no type, certainly because Void type ?"
1177 );
1178 (* recurse *)
1179 k elem
1180 );
ae4735db 1181 | Some oldstyle ->
91eba41f
C
1182 (* generate regular function type *)
1183
ae4735db 1184 pr2 "TODO generate type for function";
91eba41f
C
1185 (* add bindings *)
1186 if need_annotate_body then
ae4735db 1187 do_in_new_scope (fun () ->
91eba41f 1188 (* recurse. should naturally call the kdecl visitor and
ae4735db 1189 * add binding
91eba41f
C
1190 *)
1191 k elem;
1192 );
1193
34e49164 1194 );
ae4735db 1195 | CppTop x ->
708f4980 1196 (match x with
ae4735db 1197 | Define ((s,ii), (DefineVar, DefineType t)) ->
708f4980
C
1198 add_binding (TypeDef (s,Lib.al_type t)) true;
1199 | _ -> k elem
ae4735db 1200 )
708f4980 1201
91eba41f
C
1202 | Declaration _
1203
708f4980
C
1204
1205
91eba41f 1206 | IfdefTop _
ae4735db 1207 | MacroTop _
91eba41f
C
1208 | EmptyDef _
1209 | NotParsedCorrectly _
1210 | FinalDef _
ae4735db 1211 ->
91eba41f 1212 k elem
34e49164 1213 );
ae4735db 1214 }
34e49164 1215 in
91eba41f 1216 if just_add_in_env
ae4735db
C
1217 then
1218 if depth > 1
91eba41f 1219 then Visitor_c.vk_toplevel bigf elem
ae4735db
C
1220 else
1221 Common.profile_code "TAC.annotate_only_included" (fun () ->
91eba41f
C
1222 Visitor_c.vk_toplevel bigf elem
1223 )
1224 else Visitor_c.vk_toplevel bigf elem
1225
1226(*****************************************************************************)
1227(* Entry point *)
1228(*****************************************************************************)
1229(* catch all the decl to grow the environment *)
1230
1231
ae4735db 1232let rec (annotate_program2 :
91eba41f
C
1233 environment -> toplevel list -> (toplevel * environment Common.pair) list) =
1234 fun env prog ->
1235
ae4735db 1236 (* globals (re)initialialisation *)
91eba41f
C
1237 _scoped_env := env;
1238 _notyped_var := (Hashtbl.create 100);
34e49164 1239
ae4735db 1240 prog +> List.map (fun elem ->
34e49164 1241 let beforeenv = !_scoped_env in
91eba41f 1242 visit_toplevel ~just_add_in_env:false ~depth:0 elem;
34e49164
C
1243 let afterenv = !_scoped_env in
1244 (elem, (beforeenv, afterenv))
1245 )
1246
91eba41f
C
1247
1248
1249
1250(*****************************************************************************)
1251(* Annotate test *)
1252(*****************************************************************************)
1253
ae4735db 1254(* julia: for coccinelle *)
34e49164
C
1255let annotate_test_expressions prog =
1256 let rec propagate_test e =
1257 let ((e_term,info),_) = e in
1258 let (ty,_) = !info in
1259 info := (ty,Test);
1260 match e_term with
1261 Binary(e1,Logical(AndLog),e2)
1262 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1263 | Unary(e1,Not) -> propagate_test e1
1264 | ParenExpr(e) -> propagate_test e
3a314143
C
1265 | FunCall(e,args) -> (* not very nice, but so painful otherwise *)
1266 (match (unwrap e,args) with
1267 ((Ident(i),_),[(Left a,_)]) ->
1268 let nm = str_of_name i in
1269 if List.mem nm ["likely";"unlikely"]
1270 then propagate_test a
1271 else ()
1272 | _ -> ())
34e49164
C
1273 | _ -> () in
1274
1275 let bigf = { Visitor_c.default_visitor_c with
1276 Visitor_c.kexpr = (fun (k,bigf) expr ->
708f4980
C
1277 (match unwrap_expr expr with
1278 CondExpr(e,_,_) -> propagate_test e
d6a55602
C
1279 | Binary(e1,Logical(AndLog),e2)
1280 | Binary(e1,Logical(OrLog),e2) -> propagate_test e1; propagate_test e2
1281 | Unary(e1,Not) -> propagate_test e1
1282 | _ -> ()
91eba41f
C
1283 );
1284 k expr
1285 );
34e49164 1286 Visitor_c.kstatement = (fun (k, bigf) st ->
ae4735db 1287 match unwrap_st st with
34e49164
C
1288 Selection(s) ->
1289 (match s with If(e1,s1,s2) -> propagate_test e1 | _ -> ());
1290 k st;
1291 | Iteration(i) ->
1292 (match i with
1293 While(e,s) -> propagate_test e
1294 | DoWhile(s,e) -> propagate_test e
1295 | For(_,es,_,_) ->
1296 (match unwrap es with Some e -> propagate_test e | None -> ())
1297 | _ -> ());
1298 k st
91eba41f 1299 | _ -> k st
ae4735db 1300 )
91eba41f 1301 } in
ae4735db 1302 (prog +> List.iter (fun elem ->
34e49164
C
1303 Visitor_c.vk_toplevel bigf elem
1304 ))
1305
91eba41f
C
1306
1307
1308(*****************************************************************************)
1309(* Annotate types *)
1310(*****************************************************************************)
ae4735db 1311let annotate_program env prog =
91eba41f
C
1312 Common.profile_code "TAC.annotate_program"
1313 (fun () ->
1314 let res = annotate_program2 env prog in
34e49164 1315 annotate_test_expressions prog;
91eba41f
C
1316 res
1317 )
1318
ae4735db 1319let annotate_type_and_localvar env prog =
91eba41f
C
1320 Common.profile_code "TAC.annotate_type"
1321 (fun () -> annotate_program2 env prog)
1322
1323
1324(*****************************************************************************)
1325(* changing default typing environment, do concatenation *)
ae4735db 1326let init_env filename =
91eba41f
C
1327 pr2 ("init_env: " ^ filename);
1328 let (ast2, _stat) = Parse_c.parse_c_and_cpp filename in
1329 let ast = Parse_c.program_of_program2 ast2 in
1330
1331 let res = annotate_type_and_localvar !initial_env ast in
1332 match List.rev res with
1333 | [] -> pr2 "empty environment"
ae4735db 1334 | (_top,(env1,env2))::xs ->
91eba41f
C
1335 initial_env := !initial_env ++ env2;
1336 ()
1337