From a296e8ebc3ca23b5223bf88f34db3b57b56f2aa0 Mon Sep 17 00:00:00 2001
From: Virgile Prevosto <virgile.prevosto@m4x.org>
Date: Fri, 23 Feb 2024 14:53:53 +0100
Subject: [PATCH] [cabs2cil] yet more locations

---
 src/kernel_internals/typing/cabs2cil.ml | 80 ++++++++++++++-----------
 1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml
index 478ba276373..84899e26934 100644
--- a/src/kernel_internals/typing/cabs2cil.ml
+++ b/src/kernel_internals/typing/cabs2cil.ml
@@ -127,8 +127,12 @@ let typeForInsertedVar: (Cil_types.typ -> Cil_types.typ) ref = ref (fun t -> t)
 
 let cabs_exp loc node = { expr_loc = loc; expr_node = node }
 
-let abort_context msg =
-  let start_pos,end_pos = Cil.CurrentLoc.get() in
+let abort_context ?loc msg =
+  let loc = match loc with
+    | None -> Cil.CurrentLoc.get()
+    | Some loc -> loc
+  in
+  let start_pos,end_pos = loc in
   let append fmt =
     Format.pp_print_newline fmt ();
     Errorloc.pp_context_from_file ~start_pos fmt end_pos
@@ -5823,7 +5827,7 @@ and doExp local_env
                   let t, _, inl, attrs = spec_res in
                   t, Static, inl, attrs
                 in
-                ignore (createGlobal local_env.is_ghost None spec_res'
+                ignore (createGlobal loc local_env.is_ghost None spec_res'
                           ((newvar, dt', [], loc), ie'));
                 (unspecified_chunk empty)
               end else
@@ -7897,7 +7901,7 @@ and doFullExp local_env const e what =
   (* there is a sequence point after a full exp *)
   empty @@@ (se', ghost), e',t
 
-and doInitializer local_env (vi: varinfo) (inite: Cabs.init_expression)
+and doInitializer loc local_env (vi: varinfo) (inite: Cabs.init_expression)
   (* Return the accumulated chunk, the initializer and the new type (might be
    * different for arrays), together with the lvals read during evaluation of
    * the initializer (for local intialization)
@@ -7923,7 +7927,7 @@ and doInitializer local_env (vi: varinfo) (inite: Cabs.init_expression)
   let acc, preinit, restl =
     let so = makeSubobj vi vi.vtype NoOffset in
     let asconst = if vi.vglob then CConst else CNoConst in
-    doInit local_env asconst Extlib.nop NoInitPre so
+    doInit loc local_env asconst Extlib.nop NoInitPre so
       (unspecified_chunk empty) [ (Cabs.NEXT_INIT, inite) ]
   in
   if restl <> [] then
@@ -7962,7 +7966,8 @@ and doInitializer local_env (vi: varinfo) (inite: Cabs.init_expression)
    – preinit corresponding to the complete initialization
    – the list of unused initializers if any (should be empty most of the time)
 *)
-and doInit local_env asconst add_implicit_ensures preinit so acc initl =
+and doInit loc local_env asconst add_implicit_ensures preinit so acc initl =
+  let source = fst loc in
   let ghost = local_env.is_ghost in
   let whoami fmt = Cil_printer.pp_lval fmt (Var so.host, so.soOff) in
   let initl1 =
@@ -8064,14 +8069,14 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
     so'.stack <- [InArray(so'.curOff, bt, leno, ref 0)];
     normalSubobj so';
     let acc', preinit', initl' =
-      doInit local_env asconst add_implicit_ensures preinit so' acc charinits in
+      doInit loc local_env asconst add_implicit_ensures preinit so' acc charinits in
     if initl' <> [] then
-      Kernel.warning ~current:true
+      Kernel.warning ~source
         "Too many initializers for character array %t" whoami;
     (* Advance past the array *)
     advanceSubobj so;
     (* Continue *)
-    doInit local_env asconst add_implicit_ensures preinit' so acc' restil
+    doInit loc local_env asconst add_implicit_ensures preinit' so acc' restil
   (* If we are at an array of WIDE characters and the initializer is a
    * WIDE string literal (optionally enclosed in braces) then explore
    * the WIDE string into characters *)
@@ -8137,7 +8142,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
     so'.stack <- [InArray(so'.curOff, bt, leno, ref 0)];
     normalSubobj so';
     let acc', preinit', initl' =
-      doInit local_env asconst add_implicit_ensures preinit so' acc charinits
+      doInit loc local_env asconst add_implicit_ensures preinit so' acc charinits
     in
     if initl' <> [] then
       (* sm: see above regarding ISO 6.7.8 para 14, which is not implemented
@@ -8148,7 +8153,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
     (* Advance past the array *)
     advanceSubobj so;
     (* Continue *)
-    doInit local_env asconst add_implicit_ensures preinit' so acc' restil
+    doInit loc local_env asconst add_implicit_ensures preinit' so acc' restil
   (* If we are at an array and we see a single initializer then it must
    * be one for the first element *)
   | TArray(bt, leno, _), (Cabs.NEXT_INIT, Cabs.SINGLE_INIT _oneinit) :: _restil  ->
@@ -8157,12 +8162,12 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
     so.stack <- InArray(so.soOff, bt, leno, ref 0) :: so.stack;
     normalSubobj so;
     (* Start over with the fields *)
-    doInit local_env asconst add_implicit_ensures preinit so acc allinitl
+    doInit loc local_env asconst add_implicit_ensures preinit so acc allinitl
   (* An incomplete structure with any initializer is an error. *)
   | TComp (comp, _), _ :: restil when comp.cfields = None ->
     Kernel.error ~current:true ~once:true
       "variable `%s' has initializer but incomplete type" so.host.vname;
-    doInit local_env asconst add_implicit_ensures preinit so acc restil
+    doInit loc local_env asconst add_implicit_ensures preinit so acc restil
   (* If we are at a composite and we see a single initializer of the same
    * type as the composite then grab it all. If the type is not the same
    * then we must go on and try to initialize the fields *)
@@ -8180,12 +8185,12 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
       (* Advance to the next subobject *)
       advanceSubobj so;
       let se = acc @@@ (se, ghost) in
-      doInit local_env asconst add_implicit_ensures preinit so se restil
+      doInit loc local_env asconst add_implicit_ensures preinit so se restil
     end else begin (* Try to initialize fields *)
       let toinit = fieldsToInit comp None in
       so.stack <- InComp(so.soOff, comp, toinit) :: so.stack;
       normalSubobj so;
-      doInit local_env asconst add_implicit_ensures preinit so acc allinitl
+      doInit loc local_env asconst add_implicit_ensures preinit so acc allinitl
     end
 
   (* A scalar with a single initializer *)
@@ -8205,7 +8210,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
     (* Move on *)
     advanceSubobj so;
     let se = acc @@@ (se,ghost) in
-    doInit local_env asconst add_implicit_ensures preinit' so se restil
+    doInit loc local_env asconst add_implicit_ensures preinit' so se restil
   (* An array with a compound initializer. The initializer is for the
    * array elements *)
   | TArray (bt, leno, _), (Cabs.NEXT_INIT, Cabs.COMPOUND_INIT initl) :: restil ->
@@ -8228,7 +8233,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
         acc, preinit', []
       | _ ->
         doInit
-          local_env asconst add_implicit_ensures preinit so' acc initl
+          loc local_env asconst add_implicit_ensures preinit so' acc initl
     in
     if initl' <> [] then
       Kernel.warning ~current:true
@@ -8236,7 +8241,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
     (* Advance past the array *)
     advanceSubobj so;
     (* Continue *)
-    doInit local_env asconst add_implicit_ensures preinit' so acc' restil
+    doInit loc local_env asconst add_implicit_ensures preinit' so acc' restil
   (* We have a designator that tells us to select the matching union field.
    * This is to support a GCC extension *)
   | TComp(ci, _) as targ,
@@ -8261,14 +8266,14 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
     (* If this is a cast from union X to union X *)
     if Typ.equal t'noattr (Cil.typeDeepDropAllAttributes targ) then
       doInit
-        local_env asconst add_implicit_ensures preinit so acc
+        loc local_env asconst add_implicit_ensures preinit so acc
         [(Cabs.NEXT_INIT, Cabs.SINGLE_INIT oneinit)]
     else
       (* If this is a GNU extension with field-to-union cast find the field *)
       let fi = findField (Option.value ~default:[] ci.cfields) in
       (* Change the designator and redo *)
       doInit
-        local_env asconst add_implicit_ensures preinit so acc
+        loc local_env asconst add_implicit_ensures preinit so acc
         [Cabs.INFIELD_INIT (fi.fname, Cabs.NEXT_INIT), Cabs.SINGLE_INIT oneinit]
 
   (* A structure with a composite initializer. We initialize the fields*)
@@ -8286,14 +8291,14 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
         let preinit' = setOneInit preinit so'.curOff (empty_preinit()) in
         acc, preinit', []
       | _ ->
-        doInit local_env asconst add_implicit_ensures preinit so' acc initl
+        doInit loc local_env asconst add_implicit_ensures preinit so' acc initl
     in
     if initl' <> [] then
       Kernel.warning ~current:true "Too many initializers for structure";
     (* Advance past the structure *)
     advanceSubobj so;
     (* Continue *)
-    doInit local_env asconst add_implicit_ensures preinit' so acc' restil
+    doInit loc local_env asconst add_implicit_ensures preinit' so acc' restil
   (* A scalar with a initializer surrounded by a number of braces *)
   | t, (Cabs.NEXT_INIT, next) :: restil ->
     begin
@@ -8315,7 +8320,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
         (* Move on *)
         advanceSubobj so;
         let se = acc @@@ (se, ghost) in
-        doInit local_env asconst add_implicit_ensures preinit' so se restil
+        doInit loc local_env asconst add_implicit_ensures preinit' so se restil
       with Not_found ->
         abort_context
           "scalar value (of type %a) initialized by compound initializer"
@@ -8427,11 +8432,11 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
             :: loop (i + 1)
         in
         doInit
-          local_env asconst add_implicit_ensures preinit so acc (loop first)
+          loc local_env asconst add_implicit_ensures preinit so acc (loop first)
       | Cabs.NEXT_INIT -> (* We have not found any RANGE *)
         let acc' = addressSubobj so what acc in
         doInit
-          local_env asconst add_implicit_ensures preinit so acc'
+          loc local_env asconst add_implicit_ensures preinit so acc'
           ((Cabs.NEXT_INIT, ie) :: restil)
     in
     expandRange (fun x -> x) what
@@ -8440,7 +8445,7 @@ and doInit local_env asconst add_implicit_ensures preinit so acc initl =
 
 (* Create and add to the file (if not already added) a global. Return the
  * varinfo *)
-and createGlobal ghost logic_spec ((t,s,b,attr_list) : (typ * storage * bool * Cabs.attribute list))
+and createGlobal loc ghost logic_spec ((t,s,b,attr_list) : (typ * storage * bool * Cabs.attribute list))
     (((n,ndt,a,cloc), inite) : Cabs.init_name) : varinfo =
   Kernel.debug ~dkey:Kernel.dkey_typing_global "createGlobal: %s" n;
   (* If the global is a Frama-C builtin, set the generated flag *)
@@ -8492,7 +8497,9 @@ and createGlobal ghost logic_spec ((t,s,b,attr_list) : (typ * storage * bool * C
     if inite = Cabs.NO_INIT then
       None
     else
-      let se, ie', et, _ = doInitializer (ghost_local_env ghost) vi inite in
+      let se, ie', et, _ =
+        doInitializer loc (ghost_local_env ghost) vi inite
+      in
       (* Maybe we now have a better type?  Use the type of the
        * initializer only if it really differs from the type of
        * the variable. *)
@@ -8726,7 +8733,7 @@ and createLocal ghost ((_, sto, _, _) as specs)
   (* Maybe we have a function prototype in local scope. Make it global. We
    * do this even if the storage is Static *)
   | _ when isProto ndt ->
-    let vi = createGlobal ghost None specs init_name in
+    let vi = createGlobal loc ghost None specs init_name in
     (* Add it to the environment to shadow previous decls *)
     addLocalToEnv ghost n (EnvVar vi);
     LocalFuncHook.apply vi;
@@ -8771,7 +8778,9 @@ and createLocal ghost ((_, sto, _, _) as specs)
       if inite = Cabs.NO_INIT then
         None
       else begin
-        let se, ie', et, _ = doInitializer (ghost_local_env ghost) vi inite in
+        let se, ie', et, _ =
+          doInitializer loc (ghost_local_env ghost) vi inite
+        in
         (* Maybe we now have a better type?  Use the type of the
          * initializer only if it really differs from the type of
          * the variable. *)
@@ -8800,7 +8809,7 @@ and createLocal ghost ((_, sto, _, _) as specs)
     then
       Kernel.error ~current:true
         "\'extern\' local variable cannot have an initializer";
-    let vi = createGlobal ghost None specs init_name in
+    let vi = createGlobal loc ghost None specs init_name in
     (* Add it to the local environment to ensure that it shadows previous
      * local variables *)
     addLocalToEnv ghost n (EnvVar vi);
@@ -8930,7 +8939,9 @@ and createLocal ghost ((_, sto, _, _) as specs)
       (* TODO: if vi occurs in se4, this is not a real initialization. *)
       vi.vdefined <- true;
       contains_temp_subarray := false;
-      let se4, ie', et, r = doInitializer (ghost_local_env ghost) vi inite in
+      let se4, ie', et, r =
+        doInitializer loc (ghost_local_env ghost) vi inite
+      in
       let se4 = cleanup_autoreference vi se4 in
       (* Fix the length *)
       if Cil.isUnsizedArrayType vi.vtype && Cil.isSizedArrayType et
@@ -9018,7 +9029,8 @@ and doAliasFun ghost vtype (thisname:string) (othername:string)
 (* Do one declaration *)
 and doDecl local_env (isglobal: bool) : Cabs.definition -> chunk = function
   | Cabs.DECDEF (logic_spec, (s, nl), loc) ->
-    CurrentLoc.set (convLoc loc);
+    let cloc = convLoc loc in
+    CurrentLoc.set cloc;
     (* Do the specifiers exactly once *)
     let sugg =
       match nl with
@@ -9037,14 +9049,14 @@ and doDecl local_env (isglobal: bool) : Cabs.definition -> chunk = function
             (AttrName false) bt (Cabs.PARENTYPE(attrs, ndt, a)) in
         (match filterAttributes "alias" nattr with
          | [] -> (* ordinary prototype. *)
-           ignore (createGlobal local_env.is_ghost logic_spec spec_res name)
+           ignore (createGlobal cloc local_env.is_ghost logic_spec spec_res name)
          (*  E.log "%s is not aliased\n" name *)
          | [Attr("alias", [AStr othername])] ->
            if not (isFunctionType vtype) || local_env.is_ghost then begin
              Kernel.warning ~current:true
                "%a: CIL only supports attribute((alias)) for C functions."
                Cil_printer.pp_location (CurrentLoc.get ());
-             ignore (createGlobal ghost logic_spec spec_res name)
+             ignore (createGlobal cloc ghost logic_spec spec_res name)
            end else
              doAliasFun ghost vtype n othername (s, (n,ndt,a,l)) loc
          | _ ->
-- 
GitLab