Release coccinelle-0.2.1-rc1
[bpt/coccinelle.git] / parsing_c / type_c.ml
index 29bc3d1..c3c65a3 100644 (file)
@@ -1,11 +1,12 @@
 (* Yoann Padioleau, Julia Lawall
  *
+ * Copyright (C) 2010, University of Copenhagen DIKU and INRIA.
  * Copyright (C) 2007, 2008, 2009 University of Urbana Champaign and DIKU
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License (GPL)
  * version 2 as published by the Free Software Foundation.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -39,15 +40,15 @@ let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_type
  * field that we need that information, but the type_annotater has
  * already done this job so no need in the parent expression to know
  * the full definition of the structure. But for typedef, this is different.
- * 
+ *
  * So really the finalType we want, the completed_type notion below,
  * corresponds to a type we think is useful enough to work on, to do
  * pattern matching on, and one where we have all the needed information
  * and we don't need to look again somewhere else to get the information.
  *
- * 
- * 
- * 
+ *
+ *
+ *
  * todo? define a new clean fulltype ? as julia did with type_cocci.ml
  * without the parsing info, with some normalization (for instance have
  * only structUnionName and enumName, and remove the ParenType), some
@@ -56,9 +57,9 @@ let pr2, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_type
  * or PartialFunctionType (when don't have type of return when infer
  * the type of function call not based on type of function but on the
  * type of its arguments).
- * 
- * 
- * 
+ *
+ *
+ *
  *)
 
 type finalType = Ast_c.fullType
@@ -68,11 +69,11 @@ type completed_and_simplified = Ast_c.fullType
 type completed_typedef = Ast_c.fullType
 type removed_typedef = Ast_c.fullType
 
-(* move in ast_c ? 
- * use Ast_c.nQ, Ast_c.defaultInt, Ast_c.emptyAnnotCocci, 
+(* move in ast_c ?
+ * use Ast_c.nQ, Ast_c.defaultInt, Ast_c.emptyAnnotCocci,
  * Ast_c.emptyMetavarsBinding, Ast_c.emptyComments
 *)
-let (int_type: Ast_c.fullType) = 
+let (int_type: Ast_c.fullType) =
   (* Lib_parsing_c.al_type   (Parse_c.type_of_string "int")*)
   Ast_c.mk_ty
    (Ast_c.BaseType (Ast_c.IntType (Ast_c.Si (Ast_c.Signed, Ast_c.CInt))))
@@ -81,9 +82,9 @@ let (int_type: Ast_c.fullType) =
      Ast_c.OriginTok
       {Common.str = "int"; Common.charpos = 0; Common.line = -1;
        Common.column = -1; Common.file = ""};
-    Ast_c.cocci_tag = 
+    Ast_c.cocci_tag =
      {contents = Some (Ast_cocci.CONTEXT (Ast_cocci.NoPos, Ast_cocci.NOTHING), [])};
-    Ast_c.comments_tag = {contents = 
+    Ast_c.comments_tag = {contents =
         {Ast_c.mbefore = []; Ast_c.mafter = [];
          Ast_c.mbefore2 = []; Ast_c.mafter2 = []
         }}}]
@@ -94,54 +95,54 @@ let (int_type: Ast_c.fullType) =
 (* normally if the type annotated has done a good job, this should always
  * return true. Cf type_annotater_c.typedef_fix.
  *)
-let rec is_completed_and_simplified ty = 
-  match Ast_c.unwrap_typeC ty with 
+let rec is_completed_and_simplified ty =
+  match Ast_c.unwrap_typeC ty with
   | BaseType x  -> true
   | Pointer t -> is_completed_and_simplified t
   | Array (e, t) -> is_completed_and_simplified t
-  | StructUnion (su, sopt, fields) -> 
-      (* recurse fields ? Normally actually don't want, 
+  | StructUnion (su, sopt, fields) ->
+      (* recurse fields ? Normally actually don't want,
        * prefer to have a StructUnionName when it's possible *)
       (match sopt with
       | None -> true
       | Some _ -> false (* should have transformed it in a StructUnionName *)
       )
-  | FunctionType ft -> 
+  | FunctionType ft ->
       (* todo? return type is completed ? params completed ? *)
       true
-  | Enum  (s, enumt) -> 
+  | Enum  (s, enumt) ->
       true
-  | EnumName s -> 
+  | EnumName s ->
       true
 
   (* we prefer StructUnionName to StructUnion when it comes to typed metavar *)
   | StructUnionName (su, s) -> true
 
   (* should have completed with more information *)
-  | TypeName (_name, typ) -> 
+  | TypeName (_name, typ) ->
       (match typ with
       | None -> false
-      | Some t -> 
+      | Some t ->
           (* recurse cos what if it's an alias of an alias ? *)
           is_completed_and_simplified t
       )
 
   (* should have removed paren, for better matching with typed metavar.
    * kind of iso again *)
-  | ParenType t -> 
+  | ParenType t ->
       false
   (* same *)
-  | TypeOfType t -> 
+  | TypeOfType t ->
       false
 
-  | TypeOfExpr e -> 
+  | TypeOfExpr e ->
       true (* well we don't handle it, so can't really say it's completed *)
 
 
-let is_completed_typedef_fullType x = raise Todo  
+let is_completed_typedef_fullType x = raise Todo
 
 let is_removed_typedef_fullType x = raise Todo
-  
+
 (*****************************************************************************)
 (* more "virtual" fulltype, the fullType_with_no_typename *)
 (*****************************************************************************)
@@ -151,31 +152,31 @@ let remove_typedef x = raise Todo
 (* expression exp_info annotation vs finalType *)
 (*****************************************************************************)
 
-(* builders, needed because julia added gradually more information in 
+(* builders, needed because julia added gradually more information in
  * the expression reference annotation in ast_c.
  *)
 
-let make_info x = 
+let make_info x =
   (Some x, Ast_c.NotTest)
 
-let make_exp_type t = 
+let make_exp_type t =
   (t, Ast_c.NotLocalVar)
 
-let make_info_def t = 
+let make_info_def t =
   make_info (make_exp_type t)
 
 
 
-let noTypeHere = 
+let noTypeHere =
   (None, Ast_c.NotTest)
 
 
-let do_with_type f (t,_test) = 
+let do_with_type f (t,_test) =
   match t with
   | None -> noTypeHere
   | Some (t,_local) -> f t
 
-let get_opt_type e = 
+let get_opt_type e =
   match Ast_c.get_type_expr e with
   | Some (t,_), _test -> Some t
   | None, _test -> None
@@ -187,16 +188,16 @@ let get_opt_type e =
 (*****************************************************************************)
 
 
-let structdef_to_struct_name ty = 
+let structdef_to_struct_name ty =
   let (qu, tybis) = ty in
-  match Ast_c.unwrap_typeC ty with 
-  | (StructUnion (su, sopt, fields)) -> 
+  match Ast_c.unwrap_typeC ty with
+  | (StructUnion (su, sopt, fields)) ->
       let iis = Ast_c.get_ii_typeC_take_care tybis in
       (match sopt, iis with
       (* todo? but what if correspond to a nested struct def ? *)
-      | Some s , [i1;i2;i3;i4] -> 
+      | Some s , [i1;i2;i3;i4] ->
           qu, Ast_c.mk_tybis (StructUnionName (su, s)) [i1;i2]
-      | None, _ -> 
+      | None, _ ->
           ty
       | x -> raise Impossible
       )
@@ -208,8 +209,8 @@ let structdef_to_struct_name ty =
 (*****************************************************************************)
 
 
-let type_of_function (def,ii) = 
-  let ftyp = def.f_type in 
+let type_of_function (def,ii) =
+  let ftyp = def.f_type in
 
   (* could use the info in the 'ii' ? *)
 
@@ -222,41 +223,41 @@ let type_of_function (def,ii) =
 
 
 (* pre: only a single variable *)
-let type_of_decl decl = 
+let type_of_decl decl =
   match decl with
-  | Ast_c.DeclList (xs,ii1) -> 
+  | Ast_c.DeclList (xs,ii1) ->
       (match xs with
       | [] -> raise Impossible
-          
+
       (* todo? for other xs ? *)
-      | (x,ii2)::xs -> 
+      | (x,ii2)::xs ->
           let {v_namei = _var; v_type = v_type;
                v_storage = (_storage,_inline)} = x in
 
           (* TODO normalize ? what if nested structure definition ? *)
           v_type
       )
-  | Ast_c.MacroDecl _ -> 
+  | Ast_c.MacroDecl _ ->
       pr2_once "not handling MacroDecl type yet";
       raise Todo
 
 
 
 (* pre: it is indeed a struct def decl, and only a single variable *)
-let structdef_of_decl decl = 
+let structdef_of_decl decl =
 
   match decl with
-  | Ast_c.DeclList (xs,ii1) -> 
+  | Ast_c.DeclList (xs,ii1) ->
       (match xs with
       | [] -> raise Impossible
-          
+
       (* todo? for other xs ? *)
-      | (x,ii2)::xs -> 
+      | (x,ii2)::xs ->
           let {v_namei = var; v_type = v_type;
                v_storage = (storage,inline)} = x in
-          
+
           (match Ast_c.unwrap_typeC v_type with
-          | Ast_c.StructUnion (su, _must_be_some, fields) -> 
+          | Ast_c.StructUnion (su, _must_be_some, fields) ->
               (su, fields)
           | _ -> raise Impossible
           )
@@ -270,8 +271,8 @@ let structdef_of_decl decl =
 (* Type builder  *)
 (*****************************************************************************)
 
-let (fake_function_type: 
-   fullType option -> argument wrap2 list -> fullType option) = 
+let (fake_function_type:
+   fullType option -> argument wrap2 list -> fullType option) =
  fun rettype args ->
 
   let fake = Ast_c.fakeInfo (Common.fake_parse_info) in
@@ -279,13 +280,13 @@ let (fake_function_type:
   let fake = Ast_c.fakeInfo (Common.fake_parse_info) in
   let fake_cparen = Ast_c.rewrap_str ")" fake in
 
-  let (tyargs: parameterType wrap2 list) = 
-    args +> Common.map_filter (fun (arg,ii) -> 
+  let (tyargs: parameterType wrap2 list) =
+    args +> Common.map_filter (fun (arg,ii) ->
       match arg with
-      | Left e -> 
+      | Left e ->
           (match Ast_c.get_onlytype_expr e with
-          | Some ft -> 
-              let paramtype = 
+          | Some ft ->
+              let paramtype =
                 { Ast_c.p_namei = None;
                   p_register = false, Ast_c.noii;
                   p_type = ft;
@@ -300,9 +301,9 @@ let (fake_function_type:
   if List.length args <> List.length tyargs
   then None
   else
-    rettype +> Common.map_option (fun rettype -> 
+    rettype +> Common.map_option (fun rettype ->
       let (ftyp: functionType) = (rettype, (tyargs, (false,[]))) in
-      let (t: fullType) = 
+      let (t: fullType) =
         Ast_c.mk_ty (FunctionType ftyp) [fake_oparen;fake_cparen]
       in
       t
@@ -316,35 +317,35 @@ let (fake_function_type:
 
 (* todo: the rules are far more complex, but I prefer to simplify for now.
  * todo: should take operator as a parameter.
- * 
+ *
  * todo: Also need handle pointer arithmetic! the type of 'pt + 2'
  * is still the type of pt. cf parsing_cocci/type_infer.ml
- * 
+ *
  * (* pad: in pointer arithmetic, as in ptr+1, the lub must be ptr *)
  * | (T.Pointer(ty1),T.Pointer(ty2)) ->
  * T.Pointer(loop(ty1,ty2))
  * | (ty1,T.Pointer(ty2)) -> T.Pointer(ty2)
  * | (T.Pointer(ty1),ty2) -> T.Pointer(ty1)
- * 
+ *
 *)
 let lub op t1 t2 =
-  let ftopt = 
+  let ftopt =
     match t1, t2 with
     | None, None -> None
     | Some t, None -> Some t
     | None, Some t -> Some t
-    (* check equal ? no cos can have pointer arithmetic so t2 can be <> t1 
-     * 
-     * todo: right now I favor the first term because usually pointer 
+    (* check equal ? no cos can have pointer arithmetic so t2 can be <> t1
+     *
+     * todo: right now I favor the first term because usually pointer
      * arithmetic are written with the pointer in the first position.
-     * 
-     * Also when an expression contain a typedef, as in 
+     *
+     * Also when an expression contain a typedef, as in
      * 'dma_addr + 1' where dma_addr was declared as a varialbe
      * of type dma_addr_t, then again I want to have in the lub
      * the typedef and it is often again in the first position.
-     * 
+     *
     *)
-    | Some t1, Some t2 -> 
+    | Some t1, Some t2 ->
         let t1bis = Ast_c.unwrap_typeC t1 in
         let t2bis = Ast_c.unwrap_typeC t2 in
        (* a small attempt to do better, no consideration of typedefs *)
@@ -409,65 +410,65 @@ let lub op t1 t2 =
 (* type lookup *)
 (*****************************************************************************)
 
-(* old: was using some nested find_some, but easier use ref 
+(* old: was using some nested find_some, but easier use ref
  * update: handling union (used a lot in sparse)
- * note: it is independent of the environment. 
+ * note: it is independent of the environment.
 *)
-let (type_field: 
-  string -> (Ast_c.structUnion * Ast_c.structType) -> Ast_c.fullType) = 
- fun fld (su, fields) -> 
+let (type_field:
+  string -> (Ast_c.structUnion * Ast_c.structType) -> Ast_c.fullType) =
+ fun fld (su, fields) ->
 
   let res = ref [] in
-    
-  let rec aux_fields fields = 
-    fields +> List.iter (fun x -> 
+
+  let rec aux_fields fields =
+    fields +> List.iter (fun x ->
       match x with
-      | DeclarationField (FieldDeclList (onefield_multivars, iiptvirg)) -> 
-          onefield_multivars +> List.iter (fun (fieldkind, iicomma) -> 
+      | DeclarationField (FieldDeclList (onefield_multivars, iiptvirg)) ->
+          onefield_multivars +> List.iter (fun (fieldkind, iicomma) ->
             match fieldkind with
-            | Simple (Some name, t) | BitField (Some name, t, _, _) -> 
+            | Simple (Some name, t) | BitField (Some name, t, _, _) ->
                 let s = Ast_c.str_of_name name in
-                if s =$= fld 
+                if s =$= fld
                 then Common.push2 t res
                 else ()
-                  
-            | Simple (None, t) -> 
+
+            | Simple (None, t) ->
                 (match Ast_c.unwrap_typeC t with
 
                 (* union *)
-                | StructUnion (Union, _, fields) -> 
+                | StructUnion (Union, _, fields) ->
                     aux_fields fields
-                      
-                (* Special case of nested structure definition inside 
-                 * structure without associated field variable as in 
+
+                (* Special case of nested structure definition inside
+                 * structure without associated field variable as in
                  * struct top = { ... struct xx { int subfield1; ... }; ... }
                  * cf sparse source, where can access subfields directly.
                  * It can also be used in conjunction with union.
                  *)
-                | StructUnion (Struct, _, fields) -> 
+                | StructUnion (Struct, _, fields) ->
                     aux_fields fields
-                      
+
                 | _ -> ()
                 )
             | _ -> ()
           )
-            
+
       | EmptyField info -> ()
       | MacroDeclField _ -> pr2_once "DeclTodo"; ()
-          
+
       | CppDirectiveStruct _
-      | IfdefStruct _ -> pr2_once "StructCpp"; 
+      | IfdefStruct _ -> pr2_once "StructCpp";
     )
   in
   aux_fields fields;
   match !res with
   | [t] -> t
-  | [] -> 
+  | [] ->
       raise Not_found
-  | x::y::xs -> 
+  | x::y::xs ->
       pr2 ("MultiFound field: " ^ fld) ;
       x
-    
+
 
 
 (*****************************************************************************)
@@ -477,23 +478,23 @@ let (type_field:
 
 (* was in aliasing_function_c.ml before*)
 
-(* assume normalized/completed ? so no ParenType handling to do ? 
+(* assume normalized/completed ? so no ParenType handling to do ?
 *)
-let rec is_function_type x = 
+let rec is_function_type x =
   match Ast_c.unwrap_typeC x with
   | FunctionType _ -> true
   | _ -> false
 
 
 (* assume normalized/completed ? so no ParenType handling to do ? *)
-let rec function_pointer_type_opt x = 
+let rec function_pointer_type_opt x =
   match Ast_c.unwrap_typeC x with
-  | Pointer y -> 
+  | Pointer y ->
       (match Ast_c.unwrap_typeC y with
       | FunctionType ft -> Some ft
 
       (* fix *)
-      | TypeName (_name, Some ft2) -> 
+      | TypeName (_name, Some ft2) ->
           (match Ast_c.unwrap_typeC ft2 with
           | FunctionType ft -> Some ft
           | _ -> None
@@ -501,14 +502,14 @@ let rec function_pointer_type_opt x =
 
       | _ -> None
       )
-  (* bugfix: for many fields in structure, the field is a typename 
-   * like irq_handler_t to a function pointer 
+  (* bugfix: for many fields in structure, the field is a typename
+   * like irq_handler_t to a function pointer
    *)
-  | TypeName (_name, Some ft) -> 
+  | TypeName (_name, Some ft) ->
       function_pointer_type_opt ft
   (* bugfix: in field, usually it has some ParenType *)
 
-  | ParenType ft -> 
+  | ParenType ft ->
       function_pointer_type_opt ft
 
   | _ -> None