From 02306a1ea4a89890a4a4ea7d565251e27a144235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr> Date: Thu, 31 Oct 2019 15:20:23 +0100 Subject: [PATCH] [kernel/volatile] better handling of const --- .../ast_queries/logic_typing.ml | 46 ++++++++++--------- tests/spec/oracle/volatile_const.res.oracle | 24 ++++++++++ tests/spec/volatile_const.i | 18 ++++++++ 3 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 tests/spec/oracle/volatile_const.res.oracle create mode 100644 tests/spec/volatile_const.i diff --git a/src/kernel_services/ast_queries/logic_typing.ml b/src/kernel_services/ast_queries/logic_typing.ml index 44868650b2f..5b964ffa994 100644 --- a/src/kernel_services/ast_queries/logic_typing.ml +++ b/src/kernel_services/ast_queries/logic_typing.ml @@ -4216,33 +4216,39 @@ struct List.map (term_lval_assignable ctxt ~accept_formal ~accept_const env) tsets in - let checks_tsets_type fct ctyp = + let checks_tsets_type ~reads fct ctyp = List.iter - (fun t -> - let check t = match Logic_utils.unroll_type t with - | Ctype ctyp' -> Cil_datatype.Typ.equal ctyp ctyp' - | _ -> false - in - if not (Logic_const.plain_or_set check t.term_type) then - C.error t.term_loc "incompatible prototype of '%s' with %a" - fct Cil_printer.pp_term t ) - tsets + begin fun t -> + let check t = match Logic_utils.unroll_type t with + | Ctype ctyp' -> + ( reads || not (Cil.isConstType ctyp') ) + && Cil_datatype.Typ.equal ctyp + (Cil.type_remove_qualifier_attributes ctyp') + | _ -> false + in + if not (Logic_const.plain_or_set check t.term_type) then + C.error t.term_loc + "@[<hov 0>can not use '%s' to %s volatile @[<hov 2>'%a'@]" + fct (if reads then "read" else "write") + Cil_printer.pp_term t + end tsets in let prototype_error s fct = C.error loc "incompatible prototype of '%s' with volatile %s declaration" fct s in - let volatile_type ret_typ arg1 error = + let volatile_type ~reads ret_typ arg1 error = (* note: type pointed to by arg1 may differ from the return type with respect to qualifiers *) if not (isPointerType arg1) then error (); let vol_typ = typeOf_pointed arg1 in - if not (Cil.isVolatileType vol_typ - && Cil_datatype.Typ.equal ret_typ - (Cil.type_remove_qualifier_attributes vol_typ)) + let base_typ = Cil.type_remove_qualifier_attributes vol_typ in + if not (Cil.isVolatileType vol_typ && + ( reads || not (Cil.isConstType vol_typ) ) && + Cil_datatype.Typ.equal ret_typ base_typ) then error (); - vol_typ + base_typ in let checks_reads_fct fct ty = let error () = prototype_error "reads" fct @@ -4254,10 +4260,8 @@ struct | Some [_,arg1,_] when (not (isVoidType ret || is_varg_arg)) -> (* matching prototype: T fct (volatile T *arg1) *) - let vol_typ = volatile_type ret arg1 error in - if Cil.isConstType vol_typ then - Kernel.warning ~current:true "Access function '%s' writes to volatile const locations" fct; - checks_tsets_type fct vol_typ (* tsets should have type: volatile T *) + let vol_typ = volatile_type ~reads:true ret arg1 error in + checks_tsets_type ~reads:true fct vol_typ (* tsets should have type: volatile T *) | _ -> error () in @@ -4272,8 +4276,8 @@ struct (not (isVoidType ret || is_varg_arg)) && Cil_datatype.Typ.equal ret (Cil.type_remove_qualifier_attributes arg2) -> (* matching prototype: T fct (volatile T *arg1, T arg2) *) - let vol_typ = volatile_type ret arg1 error in - checks_tsets_type fct vol_typ (* tsets should have type: volatile T *) + let vol_typ = volatile_type ~reads:false ret arg1 error in + checks_tsets_type ~reads:false fct vol_typ (* tsets should have type: volatile T *) | _ -> error () in diff --git a/tests/spec/oracle/volatile_const.res.oracle b/tests/spec/oracle/volatile_const.res.oracle new file mode 100644 index 00000000000..26c96973298 --- /dev/null +++ b/tests/spec/oracle/volatile_const.res.oracle @@ -0,0 +1,24 @@ +[kernel] Parsing tests/spec/volatile_const.i (no preprocessing) +[kernel:annot-error] tests/spec/volatile_const.i:16: Warning: + incompatible prototype of 'wr_const' with volatile writes declaration. Ignoring global annotation +[kernel:annot-error] tests/spec/volatile_const.i:17: Warning: + incompatible prototype of 'wr_const' with volatile writes declaration. Ignoring global annotation +[kernel:annot-error] tests/spec/volatile_const.i:18: Warning: + can not use 'wr' to write volatile 'd_ro'. Ignoring global annotation +/* Generated by Frama-C */ +int volatile a_rw; +int volatile b_rw; +int const volatile c_ro; +int const volatile d_ro; +int rd(int volatile *p); + +int rd_const(int const volatile *p); + +int wr(int volatile *p, int v); + +/*@ volatile a_rw reads rd; */ +/*@ volatile b_rw reads rd_const; */ +/*@ volatile c_ro reads rd_const; */ +/*@ volatile d_ro reads rd; */ +/*@ volatile a_rw writes wr; */ + diff --git a/tests/spec/volatile_const.i b/tests/spec/volatile_const.i new file mode 100644 index 00000000000..e6ecc39b5a8 --- /dev/null +++ b/tests/spec/volatile_const.i @@ -0,0 +1,18 @@ +volatile int a_rw,b_rw ; +volatile const int c_ro,d_ro ; + +int rd(volatile int *p); +int rd_const(volatile const int *p); + +int wr(volatile int *p,int v); +int wr_const(volatile const int *p,int v); + +//@ volatile a_rw reads rd ; // OK +//@ volatile b_rw reads rd_const ; // OK +//@ volatile c_ro reads rd_const ; // OK +//@ volatile d_ro reads rd ; // OK + +//@ volatile a_rw writes wr ; // OK +//@ volatile b_rw writes wr_const ; // KO +//@ volatile c_ro writes wr_const ; // KO +//@ volatile d_ro writes wr ; // KO -- GitLab