coccinelle release 0.2.5
[bpt/coccinelle.git] / engine / cocci_vs_c.ml
index 80a1586..08e4251 100644 (file)
  *)
 
 
-(* Yoann Padioleau, Julia Lawall
- *
- * Copyright (C) 2006, 2007, 2008 Ecole des Mines de Nantes
- * Copyright (C) 2009, 2010 DIKU, INRIA, LIP6
- *
- * 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
- * file license.txt for more details.
- *
- * This file was part of Coccinelle.
- *)
-
 open Common
 
 module A = Ast_cocci
@@ -55,6 +38,14 @@ let pr2, pr2_once = Common.mk_pr2_wrappers Flag_matcher.verbose_matcher
 
 let (+++) a b = match a with Some x -> Some x | None -> b
 
+let error ii str =
+  match ii with
+    [] -> failwith str
+  | ii::_ ->
+      failwith
+       (Printf.sprintf "%s: %d: %s"
+          (Ast_c.file_of_info ii) (Ast_c.line_of_info ii) str)
+
 (*****************************************************************************)
 (* Helpers *)
 (*****************************************************************************)
@@ -283,6 +274,8 @@ let equal_metavarval valu valu' =
       Lib_parsing_c.al_declaration a =*= Lib_parsing_c.al_declaration b
   | Ast_c.MetaFieldVal a, Ast_c.MetaFieldVal b ->
       Lib_parsing_c.al_field a =*= Lib_parsing_c.al_field b
+  | Ast_c.MetaFieldListVal a, Ast_c.MetaFieldListVal b ->
+      Lib_parsing_c.al_fields a =*= Lib_parsing_c.al_fields b
   | Ast_c.MetaStmtVal a, Ast_c.MetaStmtVal b ->
       Lib_parsing_c.al_statement a =*= Lib_parsing_c.al_statement b
   | Ast_c.MetaInitVal a, Ast_c.MetaInitVal b ->
@@ -312,7 +305,8 @@ let equal_metavarval valu valu' =
        l1
 
   | (B.MetaPosValList _|B.MetaListlenVal _|B.MetaPosVal _|B.MetaStmtVal _
-      |B.MetaDeclVal _ |B.MetaFieldVal _ |B.MetaTypeVal _ |B.MetaInitVal _
+      |B.MetaDeclVal _ |B.MetaFieldVal _ |B.MetaFieldListVal _ 
+      |B.MetaTypeVal _ |B.MetaInitVal _
       |B.MetaParamListVal _|B.MetaParamVal _|B.MetaExprListVal _
       |B.MetaExprVal _|B.MetaLocalFuncVal _|B.MetaFuncVal _|B.MetaIdVal _
     ), _
@@ -344,6 +338,8 @@ let equal_inh_metavarval valu valu'=
       Lib_parsing_c.al_inh_declaration a =*= Lib_parsing_c.al_inh_declaration b
   | Ast_c.MetaFieldVal a, Ast_c.MetaFieldVal b ->
       Lib_parsing_c.al_inh_field a =*= Lib_parsing_c.al_inh_field b
+  | Ast_c.MetaFieldListVal a, Ast_c.MetaFieldListVal b ->
+      Lib_parsing_c.al_inh_field_list a =*= Lib_parsing_c.al_inh_field_list b
   | Ast_c.MetaStmtVal a, Ast_c.MetaStmtVal b ->
       Lib_parsing_c.al_inh_statement a =*= Lib_parsing_c.al_inh_statement b
   | Ast_c.MetaInitVal a, Ast_c.MetaInitVal b ->
@@ -373,7 +369,8 @@ let equal_inh_metavarval valu valu'=
        l1
 
   | (B.MetaPosValList _|B.MetaListlenVal _|B.MetaPosVal _|B.MetaStmtVal _
-      |B.MetaDeclVal _ |B.MetaFieldVal _ |B.MetaTypeVal _ |B.MetaInitVal _
+      |B.MetaDeclVal _ |B.MetaFieldVal _ |B.MetaFieldListVal _
+      |B.MetaTypeVal _ |B.MetaInitVal _
       |B.MetaParamListVal _|B.MetaParamVal _|B.MetaExprListVal _
       |B.MetaExprVal _|B.MetaLocalFuncVal _|B.MetaFuncVal _|B.MetaIdVal _
     ), _
@@ -414,8 +411,8 @@ let split_signb_baseb_ii (baseb, ii) =
        | B.CInt, ["",i1] -> (* no type is specified at all *)
            (match i1.B.pinfo with
              B.FakeTok(_,_) -> []
-           | _ -> failwith ("unrecognized signed int: "^
-                            (String.concat " "(List.map fst iis))))
+           | _ -> error [i1] ("unrecognized signed int: "^
+                             (String.concat " "(List.map fst iis))))
 
        | B.CChar2, ["char",i2] -> [i2]
 
@@ -429,11 +426,19 @@ let split_signb_baseb_ii (baseb, ii) =
        | B.CLongLong, ["long",i1;"long",i2;"int",i3] -> [i1;i2;i3]
 
        | _ ->
-         failwith ("strange type1, maybe because of weird order: "^
-                   (String.concat " " (List.map fst iis))) in
+           error (List.map snd iis)
+             ("strange type1, maybe because of weird order: "^
+              (String.concat " " (List.map fst iis))) in
       (signed,base_res)
-  | _ -> failwith ("strange type2, maybe because of weird order: "^
-                  (String.concat " " (List.map fst iis)))
+
+  | B.SizeType, ["size_t",i1] -> None, [i1]
+  | B.SSizeType, ["ssize_t",i1] -> None, [i1]
+  | B.PtrDiffType, ["ptrdiff_t",i1] -> None, [i1]
+
+  | _ ->
+      error (List.map snd iis)
+       ("strange type2, maybe because of weird order: "^
+        (String.concat " " (List.map fst iis)))
 
 (*---------------------------------------------------------------------------*)
 
@@ -457,8 +462,8 @@ let resplit_initialiser ibs iicomma =
   | [], [] -> []
   | [], _ ->
       failwith "should have a iicomma, do you generate fakeInfo in parser?"
-  | _, [] ->
-      failwith "shouldn't have a iicomma"
+  | iicommas, [] ->
+      error iicommas "shouldn't have a iicomma"
   | [iicomma], x::xs ->
       let elems = List.map fst (x::xs) in
       let commas = List.map snd (x::xs) +> List.flatten in
@@ -505,6 +510,41 @@ let structdef_to_struct_name ty =
   | _ -> raise Impossible
 
 (*---------------------------------------------------------------------------*)
+let one_initialisation_to_affectation x =
+  let ({B.v_namei = var;
+         B.v_type = returnType;
+         B.v_type_bis = tybis;
+         B.v_storage = storage;
+         B.v_local = local},
+       iisep) = x in
+  match var with
+  | Some (name, iniopt) ->
+      (match iniopt with
+      | B.ValInit (iini, (B.InitExpr e, ii_empty2)) ->
+         let local =
+           match local with
+             Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
+           | Ast_c.LocalDecl ->
+               Ast_c.LocalVar (Ast_c.info_of_type returnType) in
+          let typexp =
+                    (* old: Lib_parsing_c.al_type returnType
+                       * but this type has not the typename completed so
+                       * instead try to use tybis
+                    *)
+            match !tybis with
+            | Some ty_with_typename_completed -> ty_with_typename_completed
+            | None -> raise Impossible
+          in
+         
+          let typ = ref (Some (typexp,local), Ast_c.NotTest) in
+          let ident = name in
+          let idexpr = Ast_c.mk_e_bis (B.Ident ident) typ Ast_c.noii in
+          let assign =
+            Ast_c.mk_e (B.Assignment (idexpr,B.SimpleAssign, e)) [iini] in
+          Some assign
+      | _ -> None)
+  | _ -> None  
+    
 let initialisation_to_affectation decl =
   match decl with
   | B.MacroDecl _ -> F.Decl decl
@@ -513,68 +553,23 @@ let initialisation_to_affectation decl =
       (* todo?: should not do that if the variable is an array cos
        *  will have x[] = , mais de toute facon ca sera pas un InitExp
        *)
-      (match xs with
-      | [] -> raise Impossible
-      | [x] ->
-          let ({B.v_namei = var;
-                B.v_type = returnType;
-                B.v_type_bis = tybis;
-                B.v_storage = storage;
-                B.v_local = local},
-              iisep) = x in
-
-
-
-          (match var with
-          | Some (name, iniopt) ->
-              (match iniopt with
-              | Some (iini, (B.InitExpr e, ii_empty2)) ->
-
-                 let local =
-                   match local with
-                     Ast_c.NotLocalDecl -> Ast_c.NotLocalVar
-                   | Ast_c.LocalDecl ->
-                       Ast_c.LocalVar (Ast_c.info_of_type returnType) in
-
-                  let typexp =
-                    (* old: Lib_parsing_c.al_type returnType
-                     * but this type has not the typename completed so
-                     * instead try to use tybis
-                     *)
-                    match !tybis with
-                    | Some ty_with_typename_completed ->
-                        ty_with_typename_completed
-                    | None -> raise Impossible
-                  in
-
-                  let typ =
-                   ref (Some (typexp,local),
-                              Ast_c.NotTest) in
-                  let ident = name in
-                  let idexpr =
-                    Ast_c.mk_e_bis (B.Ident (ident)) typ Ast_c.noii
-                  in
-                  let assign =
-                    Ast_c.mk_e
-                      (B.Assignment (idexpr,B.SimpleAssign, e)) [iini] in
-                  F.DefineExpr assign
-
-              | _ -> F.Decl decl
-              )
-          | _ -> F.Decl decl
-          )
-      | x::xs ->
-          pr2_once "TODO: initialisation_to_affectation for multi vars";
-          (* todo? do a fold_left and generate 'x = a, y = b' etc, use
-           * the Sequence expression operator of C and make an
-           * ExprStatement from that.
-           *)
-          F.Decl decl
-      )
-
-
-
-
+      let possible_assignment =
+       List.fold_left
+         (function prev ->
+           function x ->
+             match prev,one_initialisation_to_affectation x with
+               _,None -> prev
+             | None,Some x -> Some x
+             | Some prev,Some x ->
+                 (* [] is clearly an invalid ii value for a sequence.
+                    hope that no one looks at it, since nothing will
+                    match the sequence.  Fortunately, SmPL doesn't
+                    support , expressions. *)
+                 Some (Ast_c.mk_e (Ast_c.Sequence (prev, x)) []))
+         None xs in
+      match possible_assignment with
+       Some x -> F.DefineExpr x
+      |        None -> F.Decl decl
 
 (*****************************************************************************)
 (* Functor parameter combinators *)
@@ -693,7 +688,6 @@ module type PARAM =
     val optional_qualifier_flag : (bool -> tin -> 'x tout) -> (tin -> 'x tout)
     val value_format_flag: (bool -> tin -> 'x tout) -> (tin -> 'x tout)
 
-
   end
 
 (*****************************************************************************)
@@ -1383,6 +1377,8 @@ let rec (expression: (A.expression, Ast_c.expression) matcher) =
   | _, ((B.Sequence _,_),_)
   | _, ((B.StatementExpr _,_),_)
   | _, ((B.Constructor _,_),_)
+  | _, ((B.New _,_),_)
+  | _, ((B.Delete _,_),_)
     -> fail
 
 
@@ -1420,7 +1416,7 @@ and (ident_cpp: info_ident -> (A.ident, B.name) matcher) =
         fail
 
 and (ident: info_ident -> (A.ident, string * Ast_c.info) matcher) =
- fun infoidb ida ((idb, iib)) -> (* (idb, iib) as ib *)
+ fun infoidb ida ((idb, iib) as ib) -> (* (idb, iib) as ib *)
    let check_constraints constraints idb =
      let meta_id_val l x = Ast_c.MetaIdVal(x,l) in
      match constraints with
@@ -1500,6 +1496,10 @@ and (ident: info_ident -> (A.ident, string * Ast_c.info) matcher) =
       | DontKnow -> failwith "MetaLocalFunc, need more semantic info about id"
       )
 
+  (* not clear why disj things are needed, after disjdistr? *)
+  | A.DisjId ias ->
+      ias +> List.fold_left (fun acc ia -> acc >|+|> (ident infoidb ia ib)) fail
+
   | A.OptIdent _ | A.UniqueIdent _ ->
       failwith "not handling Opt/Unique for ident"
     
@@ -1741,21 +1741,34 @@ and (declaration: (A.mcodekind * bool * A.declaration,B.declaration) matcher) =
             (B.DeclList ([var], iiptvirgb::iifakestart::iisto))
           )))
 
-  | _, (B.DeclList (xs, iiptvirgb::iifakestart::iisto)) ->
-      if X.mode =*= PatternMode
+  | _, (B.DeclList (xs, ((iiptvirgb::iifakestart::iisto) as ii))) ->
+      let indexify l =
+       let rec loop n = function
+           [] -> []
+         | x::xs -> (n,x)::(loop (n+1) xs) in
+       loop 0 l in
+      let rec repln n vl cur = function
+         [] -> []
+       | x::xs ->
+           if n = cur then vl :: xs else x :: (repln n vl (cur+1) xs) in
+      if X.mode =*= PatternMode || A.get_safe_decl decla
       then
-        xs +> List.fold_left (fun acc var ->
-          acc >||> (
+        (indexify xs) +> List.fold_left (fun acc (n,var) ->
+         (* consider all possible matches *)
+          acc >||> (function tin -> (
             X.tokenf_mck mckstart iifakestart >>= (fun mckstart iifakestart ->
               onedecl allminus decla (var, iiptvirgb, iisto) >>=
                 (fun decla (var, iiptvirgb, iisto) ->
                   return (
                     (mckstart, allminus, decla),
-                    (B.DeclList ([var], iiptvirgb::iifakestart::iisto))
-                  )))))
+                   (* adjust the variable that was chosen *)
+                    (B.DeclList (repln n var 0 xs,
+                                iiptvirgb::iifakestart::iisto))
+                  )))) tin))
           fail
       else
-        failwith "More that one variable in decl. Have to split to transform."
+        error ii
+         "More than one variable in the declaration, and so it cannot be transformed.  Check that there is no transformation on the type or the ;"
 
   | A.MacroDecl (sa,lpa,eas,rpa,enda), B.MacroDecl ((sb,ebs),ii) ->
       let (iisb, lpb, rpb, iiendb, iifakestart, iistob) =
@@ -1796,7 +1809,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
   *)
 
  | A.TyDecl (tya0, ptvirga),
-   ({B.v_namei = Some (nameidb, None);
+   ({B.v_namei = Some (nameidb, B.NoInit);
      B.v_type = typb0;
      B.v_storage = (B.StoTypedef, inl);
      B.v_local = local;
@@ -1860,7 +1873,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
 
                      return (
                      (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
-                     (({B.v_namei = Some (nameidb, None);
+                     (({B.v_namei = Some (nameidb, B.NoInit);
                         B.v_type = typb0;
                         B.v_storage = (B.StoTypedef, inl);
                         B.v_local = local;
@@ -1889,7 +1902,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
 
                    return (
                      (A.TyDecl (tya0, ptvirga)) +> A.rewrap decla,
-                     (({B.v_namei = Some (nameidb, None);
+                     (({B.v_namei = Some (nameidb, B.NoInit);
                         B.v_type = typb0;
                         B.v_storage = (B.StoTypedef, inl);
                         B.v_local = local;
@@ -1921,14 +1934,13 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
 
     (* could handle iso here but handled in standard.iso *)
    | A.UnInit (stoa, typa, ida, ptvirga),
-     ({B.v_namei = Some (nameidb, None);
+     ({B.v_namei = Some (nameidb, B.NoInit);
        B.v_type = typb;
        B.v_storage = stob;
        B.v_local = local;
        B.v_attr = attrs;
        B.v_type_bis = typbbis;
      }, iivirg) ->
-
        tokenf ptvirga iiptvirgb >>= (fun ptvirga iiptvirgb ->
        fullType typa typb >>= (fun typa typb ->
        ident_cpp DontKnow ida nameidb >>= (fun ida nameidb ->
@@ -1936,7 +1948,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
         (fun stoa (stob, iistob) ->
          return (
            (A.UnInit (stoa, typa, ida, ptvirga)) +>  A.rewrap decla,
-           (({B.v_namei = Some (nameidb, None);
+           (({B.v_namei = Some (nameidb, B.NoInit);
               B.v_type = typb;
               B.v_storage = stob;
               B.v_local = local;
@@ -1947,7 +1959,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
          )))))
 
    | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
-     ({B.v_namei = Some(nameidb, Some (iieqb, inib));
+     ({B.v_namei = Some(nameidb, B.ValInit (iieqb, inib));
        B.v_type = typb;
        B.v_storage = stob;
        B.v_local = local;
@@ -1964,7 +1976,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
        initialiser inia inib >>= (fun inia inib ->
          return (
            (A.Init (stoa, typa, ida, eqa, inia, ptvirga)) +> A.rewrap decla,
-           (({B.v_namei = Some(nameidb, Some (iieqb, inib));
+           (({B.v_namei = Some(nameidb, B.ValInit (iieqb, inib));
               B.v_type = typb;
               B.v_storage = stob;
               B.v_local = local;
@@ -1974,6 +1986,16 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
            iiptvirgb,iistob)
          )))))))
 
+   | A.Init (stoa, typa, ida, eqa, inia, ptvirga),
+     ({B.v_namei = Some(nameidb, B.ConstrInit _);
+       B.v_type = typb;
+       B.v_storage = stob;
+       B.v_local = local;
+       B.v_attr = attrs;
+       B.v_type_bis = typbbis;
+     },iivirg)
+       -> fail (* C++ constructor declaration not supported in SmPL *)
+
    (* do iso-by-absence here ? allow typedecl and var ? *)
    | A.TyDecl (typa, ptvirga),
      ({B.v_namei = None; B.v_type = typb;
@@ -2001,7 +2023,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
 
 
    | A.Typedef (stoa, typa, ida, ptvirga),
-     ({B.v_namei = Some (nameidb, None);
+     ({B.v_namei = Some (nameidb, B.NoInit);
        B.v_type = typb;
        B.v_storage = (B.StoTypedef,inline);
        B.v_local = local;
@@ -2016,7 +2038,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
            tokenf stoa iitypedef >>= (fun stoa iitypedef ->
              return (stoa, [iitypedef])
            )
-       | _ -> failwith "weird, have both typedef and inline or nothing";
+       | _ -> error iistob "weird, have both typedef and inline or nothing";
        ) >>= (fun stoa iistob ->
        (match A.unwrap ida with
        | A.MetaType(_,_,_) ->
@@ -2054,7 +2076,7 @@ and onedecl = fun allminus decla (declb, iiptvirgb, iistob) ->
        ) >>= (fun ida nameidb ->
          return (
            (A.Typedef (stoa, typa, ida, ptvirga)) +> A.rewrap decla,
-           (({B.v_namei = Some (nameidb, None);
+           (({B.v_namei = Some (nameidb, B.NoInit);
               B.v_type = typb;
               B.v_storage = (B.StoTypedef,inline);
               B.v_local = local;
@@ -2360,9 +2382,17 @@ and (struct_fields: (A.declaration list, B.field list) matcher) =
   let build_dots (mcode, optexpr) = A.Ddots(mcode, optexpr) in
   let match_comma ea = None in
   let build_comma ia1 = failwith "not possible" in
-  let match_metalist ea = None in
-  let build_metalist (ida,leninfo,keep,inherited) = failwith "not possible" in
-  let mktermval v = failwith "not possible" in
+  let match_metalist ea =
+    match A.unwrap ea with
+      A.MetaFieldList(ida,leninfo,keep,inherited) ->
+       Some(ida,leninfo,keep,inherited)
+    | _ -> None in
+  let build_metalist (ida,leninfo,keep,inherited) =
+    A.MetaFieldList(ida,leninfo,keep,inherited) in
+  let mktermval v =
+    (* drop empty ii information, because nothing between elements *)
+    let v = List.map Ast_c.unwrap v in
+    Ast_c.MetaFieldListVal v in
   let special_cases ea eas ebs = None in
   let no_ii x = failwith "not possible" in
   let make_ebs ebs = List.map (function x -> Left x) ebs in
@@ -2410,7 +2440,7 @@ and (struct_field: (A.declaration, B.field) matcher) = fun fa fb ->
           let iisto = [] in
           let stob = B.NoSto, false in
           let fake_var =
-            ({B.v_namei = Some (nameidb, None);
+            ({B.v_namei = Some (nameidb, B.NoInit);
               B.v_type = typb;
               B.v_storage = stob;
               B.v_local = Ast_c.NotLocalDecl;
@@ -2425,7 +2455,7 @@ and (struct_field: (A.declaration, B.field) matcher) = fun fa fb ->
             (fun fa (var,iiptvirgb,iisto) ->
 
               match fake_var with
-              | ({B.v_namei = Some (nameidb, None);
+              | ({B.v_namei = Some (nameidb, B.NoInit);
                   B.v_type = typb;
                   B.v_storage = stob;
                 }, iivirg) ->
@@ -2615,9 +2645,12 @@ and simulate_signed ta basea stringsa signaopt tb baseb ii rebuilda =
       (* handle some iso on type ? (cf complex C rule for possible implicit
         casting) *)
       match basea, baseb with
-      | A.VoidType,  B.Void
-      | A.FloatType, B.FloatType (B.CFloat)
-      | A.DoubleType, B.FloatType (B.CDouble) ->
+      | A.VoidType,   B.Void
+      | A.FloatType,  B.FloatType (B.CFloat)
+      | A.DoubleType, B.FloatType (B.CDouble)
+      |        A.SizeType,   B.SizeType
+      |        A.SSizeType,  B.SSizeType
+      |        A.PtrDiffType,B.PtrDiffType ->
            assert (signaopt =*= None);
           let stringa = tuple_of_list1 stringsa in
            let (ibaseb) = tuple_of_list1 ii in
@@ -2703,7 +2736,8 @@ and simulate_signed ta basea stringsa signaopt tb baseb ii rebuilda =
             "warning: long double not handled by ast_cocci";
           fail
 
-      | _, (B.Void|B.FloatType _|B.IntType _) -> fail
+      | _, (B.Void|B.FloatType _|B.IntType _
+           |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
 
 and simulate_signed_meta ta basea signaopt tb baseb ii rebuilda =
       (* In ii there is a list, sometimes of length 1 or 2 or 3.
@@ -2742,7 +2776,8 @@ and simulate_signed_meta ta basea signaopt tb baseb ii rebuilda =
 
           )
 
-      | (B.Void|B.FloatType _|B.IntType _) -> fail
+      | (B.Void|B.FloatType _|B.IntType _
+         |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
 
 and (typeC: (A.typeC, Ast_c.typeC) matcher) =
   fun ta tb ->
@@ -2911,7 +2946,7 @@ and (typeC: (A.typeC, Ast_c.typeC) matcher) =
         match ii with
           [iisub; lbb; rbb] -> (Common.Left iisub,lbb,rbb)
         | [iisub; iisb; lbb; rbb] -> (Common.Right (iisub,iisb),lbb,rbb)
-        | _ -> failwith "list of length 3 or 4 expected" in
+        | _ -> error ii "list of length 3 or 4 expected" in
 
        let process_type =
          match (sbopt,ii_sub_sb) with
@@ -2992,6 +3027,7 @@ and (typeC: (A.typeC, Ast_c.typeC) matcher) =
         )
 
 
+    | _, (B.NoType, ii) -> fail
     | _, (B.TypeOfExpr e, ii) -> fail
     | _, (B.TypeOfType e, ii) -> fail
 
@@ -3014,7 +3050,7 @@ and (typeC: (A.typeC, Ast_c.typeC) matcher) =
             (Common.Left iisub,lbb,rbb,comma_opt)
         | [iisub; iisb; lbb; rbb; comma_opt] ->
             (Common.Right (iisub,iisb),lbb,rbb,comma_opt)
-        | _ -> failwith "list of length 4 or 5 expected" in
+        | _ -> error ii "list of length 4 or 5 expected" in
 
        let process_type =
          match (sbopt,ii_sub_sb) with
@@ -3224,7 +3260,10 @@ and compatible_base_type a signa b =
   let ok  = return ((),()) in
 
   match a, b with
-  | Type_cocci.VoidType, B.Void ->
+  | Type_cocci.VoidType,    B.Void
+  | Type_cocci.SizeType,    B.SizeType
+  | Type_cocci.SSizeType,   B.SSizeType
+  | Type_cocci.PtrDiffType, B.PtrDiffType ->
       assert (signa =*= None);
       ok
   | Type_cocci.CharType, B.IntType B.CChar when signa =*= None ->
@@ -3251,7 +3290,8 @@ and compatible_base_type a signa b =
       fail
   | Type_cocci.BoolType, _ -> failwith "no booltype in C"
 
-  | _, (B.Void|B.FloatType _|B.IntType _) -> fail
+  | _, (B.Void|B.FloatType _|B.IntType _
+        |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
 
 and compatible_base_type_meta a signa qua b ii local =
   match a, b with
@@ -3269,13 +3309,16 @@ and compatible_base_type_meta a signa qua b ii local =
       pr2_once "no longdouble in cocci";
       fail
 
-  | _, (B.Void|B.FloatType _|B.IntType _) -> fail
+  | _, (B.Void|B.FloatType _|B.IntType _
+        |B.SizeType|B.SSizeType|B.PtrDiffType) -> fail
 
 
 and compatible_type a (b,local) =
   let ok  = return ((),()) in
 
   let rec loop = function
+    | _, (qua, (B.NoType, _)) ->
+       failwith "compatible_type: matching with NoType"
     | Type_cocci.BaseType a, (qua, (B.BaseType b,ii)) ->
        compatible_base_type a None b
 
@@ -3560,8 +3603,7 @@ let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
   | _, F.EndStatement _ | _, F.CaseNode _
   | _, F.TrueNode | _, F.FalseNode | _, F.AfterNode
   | _, F.FallThroughNode | _, F.LoopFallThroughNode
-  | _, F.InLoopNode
-    -> fail2()
+  | _, F.InLoopNode -> fail2()
 
   (* really ? diff between pattern.ml and transformation.ml *)
   | _, F.Fake -> fail2()
@@ -3977,6 +4019,15 @@ let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
           )))
       else fail
 
+  | A.Undef(undefa,ida), F.DefineHeader ((idb, ii), B.Undef) ->
+      let (defineb, iidb, ieol) = tuple_of_list3 ii in
+      ident DontKnow ida (idb, iidb) >>= (fun ida (idb, iidb) ->
+      tokenf undefa defineb >>= (fun undefa defineb ->
+        return (
+         A.Undef(undefa,ida),
+          F.DefineHeader ((idb,[defineb;iidb;ieol]),B.Undef)
+        ))
+      )
 
 
   | A.DefineHeader(definea,ida,params), F.DefineHeader ((idb, ii), defkind) ->
@@ -4076,7 +4127,8 @@ let rec (rule_elem_node: (A.rule_elem, Control_flow_c.node) matcher) =
     (F.Label (_, _, _)|F.Break (_, _)|F.Continue (_, _)|F.Default (_, _)|
     F.Case (_, _)|F.Include _|F.Goto _|F.ExprStatement _|
     F.DefineType _|F.DefineExpr _|F.DefineTodo|
-    F.DefineHeader (_, _)|F.ReturnExpr (_, _)|F.Return (_, _)|F.MacroIterHeader (_, _)|
+    F.DefineHeader (_, _)|F.ReturnExpr (_, _)|F.Return (_, _)|
+    F.MacroIterHeader (_, _)|
     F.SwitchHeader (_, _)|F.ForHeader (_, _)|F.DoWhileTail _|F.DoHeader (_, _)|
     F.WhileHeader (_, _)|F.Else _|F.IfHeader (_, _)|
     F.SeqEnd (_, _)|F.SeqStart (_, _, _)|