diff --git a/src/kernel_internals/parsing/cparser.mly b/src/kernel_internals/parsing/cparser.mly index ed1934a750d6bc7465fa4ad1f8aa9dce0e3aa9e4..0da0b7020349f1bf7f3646cddf230055b094af86 100644 --- a/src/kernel_internals/parsing/cparser.mly +++ b/src/kernel_internals/parsing/cparser.mly @@ -79,9 +79,9 @@ exception NoProto (* Go through all the parameter names and mark them as identifiers *) let rec findProto = function - PROTO (d, args, _) when isJUSTBASE d -> + PROTO (d, args, _,_) when isJUSTBASE d -> List.iter (fun (_, (an, _, _, _)) -> !Lexerhack.add_identifier an) args - | PROTO (d, _, _) -> findProto d + | PROTO (d, _,_, _) -> findProto d | PARENTYPE (_, d, _) -> findProto d | PTR (_, d) -> findProto d | ARRAY (d, _, _) -> findProto d @@ -251,8 +251,8 @@ let transformOffsetOf (speclist, dtype) member = ARRAY (addPointer dtype, attrs, expr) | PTR (attrs, dtype) -> PTR (attrs, addPointer dtype) - | PROTO (dtype, names, variadic) -> - PROTO (addPointer dtype, names, variadic) + | PROTO (dtype, names, gnames, variadic) -> + PROTO (addPointer dtype, names, gnames,variadic) in let nullType = (speclist, addPointer dtype) in let nullExpr = mk_expr (CONSTANT (CONST_INT "0")) in @@ -484,13 +484,13 @@ global: let pardecl, isva = doOldParDecl $3 $5 in (* Make the function declarator *) doDeclaration None loc [] - [(($1, PROTO(JUSTBASE, pardecl,isva), + [(($1, PROTO(JUSTBASE, pardecl,[],isva), ["FC_OLDSTYLEPROTO",[]], loc), NO_INIT)] } | IDENT LPAREN RPAREN SEMICOLON { let loc = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1) in doDeclaration None loc [] - [(($1, PROTO(JUSTBASE,[],false), + [(($1, PROTO(JUSTBASE,[],[],false), ["FC_OLDSTYLEPROTO",[]], loc), NO_INIT)] } ; @@ -524,7 +524,7 @@ postfix_expression: /*(* 6.5.2 *)*/ | primary_expression { $1 } | postfix_expression bracket_comma_expression {make_expr (INDEX ($1, smooth_expression $2))} -| postfix_expression LPAREN arguments RPAREN {make_expr (CALL ($1, $3))} +| postfix_expression LPAREN arguments RPAREN ghost_arguments_opt {make_expr (CALL ($1, $3, $5))} | BUILTIN_VA_ARG LPAREN expression COMMA type_name RPAREN { let b, d = $5 in let loc = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 5, Parsing.rhs_end_pos 5) in @@ -534,7 +534,7 @@ postfix_expression: /*(* 6.5.2 *)*/ ({ expr_loc = loc_f; expr_node = VARIABLE "__builtin_va_arg"}, [$3; { expr_loc = loc; - expr_node = TYPE_SIZEOF (b, d)}])) + expr_node = TYPE_SIZEOF (b, d)}],[])) } | BUILTIN_TYPES_COMPAT LPAREN type_name COMMA type_name RPAREN { let b1,d1 = $3 in @@ -547,7 +547,7 @@ postfix_expression: /*(* 6.5.2 *)*/ ({expr_loc = loc_f; expr_node = VARIABLE "__builtin_types_compatible_p"}, [ { expr_loc = loc1; expr_node = TYPE_SIZEOF(b1,d1)}; - { expr_loc = loc2; expr_node = TYPE_SIZEOF(b2,d2)}])) + { expr_loc = loc2; expr_node = TYPE_SIZEOF(b2,d2)}],[])) } | BUILTIN_OFFSETOF LPAREN type_name COMMA offsetof_member_designator RPAREN { transformOffsetOf $3 $5 } @@ -795,6 +795,13 @@ gcc_init_designators: /*(* GCC supports these strange things *)*/ id_or_typename COLON { INFIELD_INIT($1, NEXT_INIT) } ; +ghost_arguments_opt: + /* empty */ { [] } +| ghost_arguments { $1 } + +ghost_arguments: + LGHOST LPAREN arguments RPAREN RGHOST { $3 } + arguments: /* empty */ { [] } | comma_expression { $1 } @@ -1022,6 +1029,15 @@ for_clause: | declaration { FC_DECL $1 } ; +ghost_parameter_opt: + /* empty */ {[]} + | ghost_parameter {$1} +; + +ghost_parameter: + LGHOST parameter_list_startscope rest_par_list RPAREN RGHOST { let (l, _) = $3 in l } +; + declaration: /* ISO 6.7.*/ decl_spec_list init_declarator_list SEMICOLON { doDeclaration None ((snd $1)) (fst $1) $2 } @@ -1218,14 +1234,15 @@ direct_decl: /* (* ISO 6.7.5 *) */ { let (n, decl) = $1 in let (attrs, size) = $3 in (n, ARRAY(decl, attrs, size)) } -| direct_decl LPAREN RPAREN { - let (n,decl) = $1 in (n, PROTO(decl,[],false)) +| direct_decl LPAREN RPAREN ghost_parameter_opt { + let (n,decl) = $1 in (n, PROTO(decl,[],$4,false)) } -| direct_decl parameter_list_startscope rest_par_list RPAREN +| direct_decl parameter_list_startscope rest_par_list RPAREN ghost_parameter_opt { let (n, decl) = $1 in let (params, isva) = $3 in + let ghost = $5 in !Lexerhack.pop_context (); - (n, PROTO(decl, params, isva)) + (n, PROTO(decl, params, ghost, isva)) } ; parameter_list_startscope: @@ -1266,14 +1283,14 @@ direct_old_proto_decl: | direct_decl LPAREN old_parameter_list_ne RPAREN old_pardef_list { let par_decl, isva = doOldParDecl $3 $5 in let n, decl = $1 in - (n, PROTO(decl, par_decl, isva), ["FC_OLDSTYLEPROTO",[]]) + (n, PROTO(decl, par_decl, [],isva), ["FC_OLDSTYLEPROTO",[]]) } /* (* appears sometimesm but generates a shift-reduce conflict. *) | LPAREN STAR direct_decl LPAREN old_parameter_list_ne RPAREN RPAREN LPAREN RPAREN old_pardef_list { let par_decl, isva = doOldParDecl $5 $10 in - let n, decl = $3 in (n, PROTO(decl, par_decl, isva), []) + let n, decl = $3 in (n, PROTO(decl, par_decl,[], isva), []) } */ ; @@ -1336,9 +1353,9 @@ abs_direct_decl: /* (* ISO 6.7.6. We do not support optional declarator for | abs_direct_decl parameter_list_startscope rest_par_list RPAREN { let (params, isva) = $3 in !Lexerhack.pop_context (); - PROTO ($1, params, isva) + PROTO ($1, params,[], isva) } -| abs_direct_decl LPAREN RPAREN { PROTO ($1, [], false) } +| abs_direct_decl LPAREN RPAREN { PROTO ($1, [],[], false) } ; abs_direct_decl_opt: @@ -1382,11 +1399,12 @@ function_def_start: /* (* ISO 6.9.1 *) */ (snd $1, fst $1, $2) } /* (* New-style function that does not have a return type *) */ -| IDENT parameter_list_startscope rest_par_list RPAREN +| IDENT parameter_list_startscope rest_par_list RPAREN ghost_parameter_opt { let (params, isva) = $3 in + let ghost = $5 in let loc = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1) in let fdec = - ($1, PROTO(JUSTBASE, params, isva), [], loc) in + ($1, PROTO(JUSTBASE, params, ghost, isva), [], loc) in announceFunctionName fdec; (* Default is int type *) let defSpec = [SpecType Tint] in (loc, defSpec, fdec) @@ -1398,15 +1416,15 @@ function_def_start: /* (* ISO 6.9.1 *) */ let pardecl, isva = doOldParDecl $3 $5 in let loc = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1) in (* Make the function declarator *) - let fdec = ($1, PROTO(JUSTBASE, pardecl,isva), [], loc) in + let fdec = ($1, PROTO(JUSTBASE, pardecl,[],isva), [], loc) in announceFunctionName fdec; (* Default is int type *) (loc, [SpecType Tint], fdec) } -| IDENT LPAREN RPAREN +| IDENT LPAREN RPAREN ghost_parameter_opt { let loc = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_start_pos 1) in - let fdec = ($1, PROTO(JUSTBASE,[],false),[],loc) in + let fdec = ($1, PROTO(JUSTBASE,[],$4,false),[],loc) in announceFunctionName fdec; (loc, [SpecType Tint], fdec) } @@ -1538,20 +1556,20 @@ postfix_attr: primary_attr { $1 } | id_or_typename_as_id paren_attr_list_ne { let loc = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1) in - make_expr (CALL({ expr_loc = loc; expr_node = VARIABLE $1}, $2)) } + make_expr (CALL({ expr_loc = loc; expr_node = VARIABLE $1}, $2,[])) } /* (* use a VARIABLE "" so that the parentheses are printed *) */ | id_or_typename_as_id LPAREN RPAREN { let loc1 = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1) in let loc2 = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 2, Parsing.rhs_end_pos 3) in let f = { expr_node = VARIABLE $1; expr_loc = loc1 } in let arg = { expr_node = VARIABLE ""; expr_loc = loc2 } in - make_expr (CALL(f, [arg])) + make_expr (CALL(f, [arg],[])) } /* (* use a VARIABLE "" so that the parameters are printed without * parentheses nor comma *) */ | basic_attr param_attr_list_ne { let loc = Cil_datatype.Location.of_lexing_loc (Parsing.rhs_start_pos 1, Parsing.rhs_end_pos 1) in - make_expr (CALL({ expr_node = VARIABLE ""; expr_loc = loc}, $1::$2)) } + make_expr (CALL({ expr_node = VARIABLE ""; expr_loc = loc}, $1::$2,[])) } | postfix_attr ARROW id_or_typename { make_expr (MEMBEROFPTR ($1, $3))} | postfix_attr DOT id_or_typename { make_expr (MEMBEROF ($1, $3)) } diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index 3137c53e5a21baab52734c1af0bbd3abc3009467..8481d90b3a09bc2957a0ecd56b8f2a4de304763d 100644 --- a/src/kernel_internals/typing/cabs2cil.ml +++ b/src/kernel_internals/typing/cabs2cil.ml @@ -1163,21 +1163,22 @@ end let constFoldType (t:typ) : typ = visitCilType constFoldTypeVisitor t -let get_temp_name () = +let get_temp_name ?(ghost=false) () = let undolist = ref [] in let data = CurrentLoc.get() in + let name = if ghost then "g_tmp" else "tmp" in let name, _ = - Alpha.newAlphaName ~alphaTable ~undolist ~lookupname:"tmp" ~data + Alpha.newAlphaName ~alphaTable ~undolist ~lookupname:name ~data in let undolist = !undolist in Alpha.undoAlphaChanges ~alphaTable ~undolist; name (* Create a new temporary variable *) -let newTempVar descr (descrpure:bool) typ = +let newTempVar ~ghost descr (descrpure:bool) typ = let t' = (!typeForInsertedVar) typ in - let name = get_temp_name () in - let vi = makeVarinfo ~temp:true false false name t' in + let name = get_temp_name ~ghost () in + let vi = makeVarinfo ~ghost ~temp:true false false name t' in vi.vdescr <- Some descr; vi.vdescrpure <- descrpure; alphaConvertVarAndAddToEnv false vi @@ -1565,7 +1566,7 @@ struct match Cil_datatype.Varinfo.Hashtbl.find_opt replacements vi with | None -> let vi' = - newTempVar (vi.vname ^ " initialization") true vi.vtype + newTempVar (vi.vname ^ " initialization") ~ghost true vi.vtype in Cil_datatype.Varinfo.Hashtbl.add replacements vi vi'; vars := vi' :: !vars; @@ -2619,11 +2620,15 @@ let rec combineTypes (what: combineWhat) (oldt: typ) (t: typ) : typ = let newargs, olda' = if oldargs = None then args, olda else if args = None then oldargs, olda else - let oldargslist = argsToList oldargs in - let argslist = argsToList args in + let (oldargslist, oldghostargslist) = argsToPairOfLists oldargs in + let (argslist, ghostargslist) = argsToPairOfLists args in if List.length oldargslist <> List.length argslist then raise (Cannot_combine "different number of arguments") + else if List.length oldghostargslist <> List.length ghostargslist then + raise (Cannot_combine "different number of ghost arguments") else begin + let oldargslist = oldargslist @ oldghostargslist in + let argslist = argslist @ ghostargslist in (* Construct a mapping between old and new argument names. *) let map = H.create 5 in List.iter2 @@ -3034,8 +3039,11 @@ let makeGlobalVarinfo (isadef: bool) (vi: varinfo) : varinfo * bool = (try let old_formals_env = getFormalsDecl oldvi in List.iter2 - (fun old (name,typ,attr) -> - if name <> "" then begin + (fun old ((name,typ,attr) as decl) -> + let new_ghost = Cil.isGhostFormalVarDecl decl in + if old.vghost <> new_ghost then + raise (Invalid_argument "Incompatible ghost status") + else if name <> "" then begin Kernel.debug ~dkey:Kernel.dkey_typing_global "replacing formal %s with %s" old.vname name; old.vname <- name; @@ -3961,6 +3969,8 @@ let empty_local_env = } let ghost_local_env ghost = {empty_local_env with is_ghost = ghost } +let add_ghost_to_local_env env ghost = + { env with is_ghost = env.is_ghost || ghost } let paren_local_env env = { env with is_paren = true } let no_paren_local_env env = { env with is_paren = false } @@ -4709,12 +4719,11 @@ and makeVarInfoCabs Kernel.error ~once:true ~current:true "inline for a non-function: %s" n; checkRestrictQualifierDeep vtype; (* log "Looking at %s(%b): (%a)@." n isformal d_attrlist nattr;*) - let vi = makeVarinfo ~referenced ~temp:isgenerated isglobal isformal n vtype + let vi = makeVarinfo ~ghost ~referenced ~temp:isgenerated isglobal isformal n vtype in vi.vstorage <- sto; vi.vattr <- nattr; vi.vdecl <- ldecl; - vi.vghost <- ghost; vi.vdefined <- not (isFunctionType vtype) && isglobal && (sto = NoStorage || sto = Static); @@ -4783,7 +4792,7 @@ and doAttr ghost (a: A.attribute) : attribute list = end | A.CONSTANT (A.CONST_FLOAT str) -> ACons ("__fc_float", [AStr str]) - | A.CALL({expr_node = A.VARIABLE n}, args) -> begin + | A.CALL({expr_node = A.VARIABLE n}, args, []) -> begin let n' = if strip then stripUnderscore n else n in let ae' = List.map ae args in ACons(n', ae') @@ -5026,7 +5035,7 @@ and doType (ghost:bool) isFuncArg function argument"; doDeclType (TArray(bt, lo, empty_size_cache (), al')) acc d - | A.PROTO (d, args, isva) -> + | A.PROTO (d, args, ghost_args, isva) -> (* Start a scope for the parameter names *) enterScope (); (* Intercept the old-style use of varargs.h. On GCC this means that @@ -5053,9 +5062,9 @@ and doType (ghost:bool) isFuncArg (args', !newisva) end else (args, isva) in - let argl_length = List.length args' in (* Make the argument as for a formal *) - let doOneArg (s, (n, ndt, a, cloc)) : varinfo = + let doOneArg argl_length is_ghost (s, (n, ndt, a, cloc)) : varinfo = + let ghost = is_ghost || ghost in let s' = doSpecList ghost n s in let vi = makeVarInfoCabs ~ghost ~isformal:true ~isglobal:false (convLoc cloc) s' (n,ndt,a) in @@ -5073,13 +5082,31 @@ and doType (ghost:bool) isFuncArg addLocalToEnv vi.vname (EnvVar vi); vi in + let make_noopt_targs ghost args = + let argl_length = List.length args in + List.map (doOneArg argl_length ghost) args + in + let noopt_targs = make_noopt_targs false args' in + let noopt_ghost_targs = make_noopt_targs true ghost_args in let targs : varinfo list option = - match List.map doOneArg args' with + match noopt_targs with | [] -> None (* No argument list *) + | [t] when isVoidType t.vtype -> Some [] + | l -> Some l + in + let ghost_targs : varinfo list = + match noopt_ghost_targs with | [t] when isVoidType t.vtype -> - Some [] - | l -> - Some l + Kernel.error ~once:true ~current:true + "ghost parameters list cannot be void" ; + [] + | l -> l + in + let all_targs = + match targs, ghost_targs with + | None, [] -> None + | None, g -> Some g + | Some ng, g -> Some (ng @ g) in exitScope (); (* Turn [] types into pointers in the arguments and the result type. @@ -5134,11 +5161,19 @@ and doType (ghost:bool) isFuncArg fixupArgumentTypes (argidx + 1) args' in let args = - match targs with + match all_targs with | None -> None | Some argl -> fixupArgumentTypes 0 argl; - Some (List.map (fun a -> (a.vname, a.vtype, a.vattr)) argl) + let arg_type_from_vi vi = + let attrs = + if vi.vghost then + cabsAddAttributes [Attr (frama_c_ghost_formal, [])] vi.vattr + else + vi.vattr + in (vi.vname, vi.vtype, attrs) + in + Some (List.map arg_type_from_vi argl) in let tres = match unrollType bt with @@ -5180,7 +5215,7 @@ and isVariableSizedArray ghost (dt: A.decl_type) | PTR (al, dt) -> PTR (al, findArray dt) | JUSTBASE -> JUSTBASE | PARENTYPE (prea, dt, posta) -> PARENTYPE (prea, findArray dt, posta) - | PROTO (dt, f, a) -> PROTO (findArray dt, f, a) + | PROTO (dt, f, g, a) -> PROTO (findArray dt, f, g, a) in let dt' = findArray dt in match !res with @@ -6034,7 +6069,7 @@ and doExp local_env doExp local_env asconst (cabs_exp loc (A.CALL (cabs_exp loc (A.VARIABLE "__builtin_next_arg"), - [cabs_exp loc (A.CONSTANT (A.CONST_INT "0"))]))) + [cabs_exp loc (A.CONSTANT (A.CONST_INT "0"))],[]))) what end @@ -6141,7 +6176,7 @@ and doExp local_env Format.asprintf "%a%s" Cil_descriptive_printer.pp_exp e' (if uop = A.POSINCR then "++" else "--") in - let tmp = newTempVar descr true t in + let tmp = newTempVar ~ghost descr true t in ([var tmp], local_var_chunk se' tmp +++ (mkStmtOneInstr ~ghost:local_env.is_ghost ~valid_sid @@ -6223,7 +6258,7 @@ and doExp local_env let descr = Format.asprintf "%a" Cil_descriptive_printer.pp_lval lv in - let tmp = newTempVar descr true lvt in + let tmp = newTempVar ~ghost descr true lvt in let chunk = i2c (mkStmtOneInstr ~ghost:local_env.is_ghost ~valid_sid @@ -6345,7 +6380,7 @@ and doExp local_env finishExp [] se e' intType | _ -> let tmp = - newTempVar "<boolean expression>" true intType + newTempVar ~ghost "<boolean expression>" true intType in let condChunk = compileCondExp ~ghost ce @@ -6362,7 +6397,7 @@ and doExp local_env intType end - | A.CALL(f, args) -> + | A.CALL(f, args, ghost_args) -> let (rf,sf, f', ft') = match (stripParen f).expr_node with (* Treat the VARIABLE case separate because we might be calling a @@ -6490,14 +6525,14 @@ and doExp local_env in let init_chunk = unspecified_chunk empty in (* Do the arguments. In REVERSE order !!! Both GCC and MSVC do this *) - let rec loopArgs = function + let rec loopArgs ?(are_ghost=false) = function | ([], []) -> (match argTypes, f''.enode with | None, Lval (Var f,NoOffset) -> (* we call a function without prototype with 0 argument. Hence, it really has no parameter. *) - if not isSpecialBuiltin then begin + if not isSpecialBuiltin && not are_ghost then begin warn_no_proto f; let typ = TFun (resType, Some [], false,attrs) in Cil.update_var_type f typ; @@ -6510,16 +6545,18 @@ and doExp local_env | _, [] -> if not isSpecialBuiltin then Kernel.error ~once:true ~current:true - "Too few arguments in call to %a." Cil_printer.pp_exp f' ; + "Too few%s arguments in call to %a." + (if are_ghost then " ghost" else "") Cil_printer.pp_exp f' ; (init_chunk, []) | ((_, at, _) :: atypes, a :: args) -> - let (ss, args') = loopArgs (atypes, args) in + let (ss, args') = loopArgs ~are_ghost (atypes, args) in (* Do not cast as part of translating the argument. We let * the castTo do this work. This was necessary for * test/small1/union5, in which a transparent union is passed * as an argument *) let (sa, a', att) = + let local_env = add_ghost_to_local_env local_env are_ghost in let (r, c, e, t) = doExp (no_paren_local_env local_env) CNoConst a (AExp None) in @@ -6587,7 +6624,8 @@ and doExp local_env if not isvar && argTypes != None && not isSpecialBuiltin then (* Do not give a warning for functions without a prototype*) Kernel.error ~once:true ~current:true - "Too many arguments in call to %a" Cil_printer.pp_exp f'; + "Too many%s arguments in call to %a" + (if are_ghost then " ghost" else "") Cil_printer.pp_exp f'; let rec loop = function [] -> (init_chunk, []) | a :: args -> @@ -6636,7 +6674,18 @@ and doExp local_env *) ) in - let (sargs, args') = loopArgs (argTypesList, args) in + let (argTypes, ghostArgTypes) = + List.partition (fun d -> not (isGhostFormalVarDecl d) || ghost) argTypesList + in + let args = if ghost then args @ ghost_args else args in + + (* Again, we process arguments in REVERSE order. *) + let (sghost, ghosts') = loopArgs ~are_ghost:true (ghostArgTypes, ghost_args) in + let (sargs, args') = loopArgs (argTypes, args) in + + let sargs = sghost @@ (sargs, false) in + + let (sargs, args') = (sargs, args' @ ghosts') in (* Setup some pointer to the elements of the call. We may change * these below *) let s0 = unspecified_chunk empty in @@ -6666,9 +6715,10 @@ and doExp local_env | _ -> e in (* Get the name of the last formal *) - let getNameLastFormal () : string = + let getNameLastNonGhostFormal () : string = match !currentFunctionFDEC.svar.vtype with | TFun(_, Some args, true, _) -> begin + let args, _ = Cil.argsToPairOfLists (Some args) in match List.rev args with | (last_par_name, _, _) :: _ -> last_par_name | _ -> "" @@ -6688,7 +6738,7 @@ and doExp local_env match !pwhat with | ASet (is_real,lv, r, lvt) -> is_real, lv, r, lvt | _ -> - let v = newTempVar "vararg" true resTyp in + let v = newTempVar ~ghost "vararg" true resTyp in locals := v::!locals; false, var v, [], resTyp in @@ -6717,7 +6767,7 @@ and doExp local_env let isOk = match (dropCasts last).enode with | Lval (Var lastv, NoOffset) -> - lastv.vname = getNameLastFormal () + lastv.vname = getNameLastNonGhostFormal () | _ -> false in if not isOk && variad then @@ -6753,7 +6803,7 @@ and doExp local_env let isOk = match (dropCasts last).enode with | Lval (Var lastv, NoOffset) -> - lastv.vname = getNameLastFormal () + lastv.vname = getNameLastNonGhostFormal () | _ -> false in if not isOk then @@ -6792,7 +6842,7 @@ and doExp local_env let isOk = match (dropCasts last).enode with | Lval (Var lastv, NoOffset) -> - lastv.vname = getNameLastFormal () + lastv.vname = getNameLastNonGhostFormal () | _ -> false in if not isOk then @@ -7004,7 +7054,7 @@ and doExp local_env Cil_descriptive_printer.pp_exp) !pargs in - let tmp = newTempVar descr false restype'' in + let tmp = newTempVar ~ghost descr false restype'' in tmp.vdecl <- loc; locals:=tmp::!locals; (* Remember that this variable has been created for this @@ -7144,7 +7194,7 @@ and doExp local_env let descr = Format.asprintf "%a" Cprint.print_expression e1 in - let tmp = newTempVar descr true tresult in + let tmp = newTempVar ~ghost descr true tresult in let tmp_var = var tmp in let tmp_lval = new_exp ~loc:e.expr_loc (Lval (tmp_var)) in let (r1, se1, _, _) = @@ -7213,7 +7263,7 @@ and doExp local_env let descr = Format.asprintf "%a" Cprint.print_expression e1 in - let tmp = newTempVar descr true tresult in + let tmp = newTempVar ~ghost descr true tresult in let tmp_var = var tmp in let tmp_lval = new_exp ~loc:e.expr_loc (Lval (tmp_var)) in let (r1,se1, _, _) = @@ -7242,7 +7292,7 @@ and doExp local_env Cil_descriptive_printer.pp_exp e2' Cil_descriptive_printer.pp_exp e3' in - let tmp = newTempVar descr true tresult in + let tmp = newTempVar ~ghost descr true tresult in false, var tmp, [], tresult, local_var_chunk empty tmp in @@ -7315,7 +7365,7 @@ and doExp local_env let se, e = match se.stmts with | [ { skind = Block b},_, _, _, _ ] -> - let vi = newTempVar "GNU.body" true t in + let vi = newTempVar ~ghost "GNU.body" true t in b.bstmts <- b.bstmts @ [Cil.mkStmtOneInstr ~ghost:local_env.is_ghost ~valid_sid @@ -8514,7 +8564,8 @@ and cleanup_autoreference vi chunk = match !temp with | Some v' -> ChangeTo v' | None -> - let v' = newTempVar (vi.vname ^ " initialization") true vi.vtype in + let ghost = v.vghost in + let v' = newTempVar ~ghost (vi.vname ^ " initialization") true vi.vtype in temp := Some v'; ChangeTo v' end else SkipChildren @@ -8543,8 +8594,8 @@ and createLocal ghost ((_, sto, _, _) as specs) (* Check if we are declaring a function *) let rec isProto (dt: decl_type) : bool = match dt with - | PROTO (JUSTBASE, _, _) -> true - | PROTO (x, _, _) -> isProto x + | PROTO (JUSTBASE, _,_, _) -> true + | PROTO (x, _,_, _) -> isProto x | PARENTYPE (_, x, _) -> isProto x | ARRAY (x, _, _) -> isProto x | PTR (_, x) -> isProto x @@ -8714,7 +8765,7 @@ and createLocal ghost ((_, sto, _, _) as specs) (* do it in two *) let rt, _, _, _ = splitFunctionType alloca.vtype in let tmp = - newTempVar + newTempVar ~ghost (Format.asprintf "alloca(%a)" Cil_printer.pp_exp alloca_size) false rt in @@ -8776,7 +8827,7 @@ and doAliasFun vtype (thisname:string) (othername:string) let args = List.map (fun (n,_,_) -> { expr_loc = loc; expr_node = A.VARIABLE n}) (argsToList formals) in - let call = A.CALL ({expr_loc = loc; expr_node = A.VARIABLE othername}, args) + let call = A.CALL ({expr_loc = loc; expr_node = A.VARIABLE othername}, args,[]) in let stmt = {stmt_ghost = false; stmt_node = if isVoidType rt then @@ -8983,8 +9034,9 @@ and doDecl local_env (isglobal: bool) : A.definition -> chunk = function (* Create the formals and add them to the environment. *) (* sfg: extract tsets for the formals from dt *) - let doFormal (loc : location) (fn, ft, fa) = - let f = makeVarinfo ~temp:false false true fn ft in + let doFormal (loc : location) ((fn, ft, fa) as fd) = + let ghost = ghost || isGhostFormalVarDecl fd in + let f = makeVarinfo ~ghost ~temp:false false true fn ft in (f.vdecl <- loc; f.vattr <- fa; alphaConvertVarAndAddToEnv true f) @@ -9005,7 +9057,7 @@ and doDecl local_env (isglobal: bool) : A.definition -> chunk = function f' :: fl' end in - let fmlocs = (match dt with PROTO(_, fml, _) -> fml | _ -> []) in + let fmlocs = (match dt with PROTO(_, fml, _, _) -> fml | _ -> []) in let formals = doFormals (argsToList formals_t) fmlocs in (* in case of formals referred to in types of others, doType has put dummy varinfos. We need to fix them now that we have proper diff --git a/src/kernel_internals/typing/infer_annotations.ml b/src/kernel_internals/typing/infer_annotations.ml index d4d4103964a90292cadc12908ab670513e9f0b7a..2bc549d5caf779a1dcc81ebca20143fe31af2de7 100644 --- a/src/kernel_internals/typing/infer_annotations.ml +++ b/src/kernel_internals/typing/infer_annotations.ml @@ -56,14 +56,14 @@ let assigns_from_prototype kf = if Cil.isVoidPtrType typ then let const = typeHasAttribute "const" (Cil.typeOf_pointed typ) in let typ' = if const then Cil.charConstPtrType else Cil.charPtrType in - (Logic_utils.mk_cast ~loc typ' t, typ') - else (t, typ) + (vi.vghost, Logic_utils.mk_cast ~loc typ' t, typ') + else (vi.vghost, t, typ) ) pointer_args in (* Generate the term [*(t+(0..))] with the appropriate array bounds (if they are known), and possibly add some [[..]] if v has points to one or more arrays *) - let mk_star (t, typ) = + let mk_star (g, t, typ) = let loc = t.term_loc in let zero = Logic_const.tinteger ~loc 0 in (* Range [0..length-1], or [0..] if length is not known *) @@ -108,14 +108,16 @@ let assigns_from_prototype kf = let t_range = Logic_const.term ~loc t_range_node (if set then make_set_type (Ctype typ) else Ctype typ) in - Logic_const.new_identified_term - (term ~loc (TLval (TMem t_range, offset_arrays)) typ_with_offset) + let t = Logic_const.new_identified_term + (term ~loc (TLval (TMem t_range, offset_arrays)) typ_with_offset) + in + (g, t) in let to_assign = List.map mk_star (List.filter - (fun (_t, typ) -> + (fun (_g, _t, typ) -> let pointed_type = typeOf_pointed typ in not (typeHasAttribute "const" pointed_type) ) @@ -125,28 +127,35 @@ let assigns_from_prototype kf = List.map mk_star pointer_args in let inputs = - (pointer_args_content - @(List.map - (fun v -> - Logic_const.new_identified_term - { term_node = TLval (TVar (cvar_to_lvar v),TNoOffset); - term_type = Ctype v.vtype; - term_name = []; - term_loc = v.vdecl }) - basic_args)) + (pointer_args_content) + @(List.map + (fun v -> + v.vghost, + (Logic_const.new_identified_term + { term_node = TLval (TVar (cvar_to_lvar v),TNoOffset); + term_type = Ctype v.vtype; + term_name = []; + term_loc = v.vdecl }) + ) basic_args) + in + let inputs_no_ghost = List.fold_right + (fun (g, t) acc -> if g then acc else t :: acc) inputs [] in + let inputs = List.map (fun (_g, t) -> t) inputs in let arguments = - List.map (fun content -> content, From inputs) to_assign + List.map + (fun (g, content) -> content, From (if g then inputs else inputs_no_ghost)) + to_assign in match rtyp with | TVoid _ -> (* assigns all pointer args from basic args and content of pointer args *) - arguments + arguments | _ -> (* assigns result from basic args and content of pointer args *) let loc = vi.vdecl in let result = Logic_const.(new_identified_term (tresult ~loc rtyp)) in - (result, From inputs):: arguments + (result, From inputs_no_ghost):: arguments let is_frama_c_builtin name = Ast_info.is_frama_c_builtin name diff --git a/src/kernel_services/ast_printing/cabs_debug.ml b/src/kernel_services/ast_printing/cabs_debug.ml index fc191d8582406f56fdf3e527c994494655181a0d..b5880e1ae7e042ebf564682ae3e75c35da0f8aed 100644 --- a/src/kernel_services/ast_printing/cabs_debug.ml +++ b/src/kernel_services/ast_printing/cabs_debug.ml @@ -117,9 +117,9 @@ and pp_decl_type fmt = function | ARRAY (decl_type, attrs, exp) -> fprintf fmt "@[<hov 2>ARRAY[%a, %a, %a]@]" pp_decl_type decl_type pp_attrs attrs pp_exp exp | PTR (attrs, decl_type) -> fprintf fmt "@[<hov 2>PTR(%a, %a)@]" pp_attrs attrs pp_decl_type decl_type - | PROTO (decl_type, single_names, b) + | PROTO (decl_type, single_names, single_ghost_names, b) -> fprintf fmt "@[<hov 2>PROTO decl_type(%a), single_names(" pp_decl_type decl_type; - List.iter (fun sn -> fprintf fmt ",@ %a" pp_single_name sn) single_names; + List.iter (fun sn -> fprintf fmt ",@ %a" pp_single_name sn) (single_names @ single_ghost_names) ; fprintf fmt "),@ %b@]" b and pp_name_group fmt (spec, names) = @@ -329,11 +329,11 @@ and pp_exp_node fmt = function fprintf fmt "@[<hov 2>QUESTION(%a, %a, %a)@]" pp_exp exp1 pp_exp exp2 pp_exp exp3 | CAST ((spec, decl_type), init_exp) -> fprintf fmt "@[<hov 2>CAST (%a, %a) %a@]" pp_spec spec pp_decl_type decl_type pp_init_exp init_exp - | CALL (exp1, exps) -> + | CALL (exp1, exps, ghosts) -> fprintf fmt "@[<hov 2>CALL %a {" pp_exp exp1; List.iter (fun e -> fprintf fmt ",@ %a" pp_exp e) - exps; + (exps @ ghosts); fprintf fmt "}@]" | COMMA exps -> fprintf fmt "@[<hov 2>COMMA {"; diff --git a/src/kernel_services/ast_printing/cil_printer.ml b/src/kernel_services/ast_printing/cil_printer.ml index adc133983a5b15ff4fa3ea4afa4266fd2d5e5b23..13259d5a56cf1cbc129ac1842053fbaf8d629cec 100644 --- a/src/kernel_services/ast_printing/cil_printer.ml +++ b/src/kernel_services/ast_printing/cil_printer.ml @@ -65,6 +65,7 @@ let register_shallow_attribute s = reserved_attributes:= (Extlib.strip_underscore s)::!reserved_attributes +let () = register_shallow_attribute Cil.frama_c_ghost_formal let () = register_shallow_attribute Cil.frama_c_mutable let () = register_shallow_attribute Cil.frama_c_init_obj @@ -871,10 +872,35 @@ class cil_printer () = object (self) (match e.enode with | Lval(Var _, _) -> self#exp fmt e | _ -> fprintf fmt "(%a)" self#exp e); + + let (_, param_ts, _, _) = Cil.splitFunctionType (Cil.typeOf e) in + let _, g_params_ts = Cil.argsToPairOfLists param_ts in + + let rec break n l = + if n = 0 then [], l + else match l with + | [] -> assert false + | x :: l' -> let (f, s) = break (n-1) l' in x :: f, s + in + let args, ghosts = if is_ghost then + args, [] + else + let n = List.length args - List.length g_params_ts in + break n args + in + (* Now the arguments *) + Format.fprintf fmt "@[" ; Pretty_utils.pp_flowlist ~left:"(" ~sep:"," ~right:")" self#exp fmt args; + (* Now the ghost arguments *) + begin match ghosts with + | [] -> () + | _ -> Pretty_utils.pp_flowlist + ~left:"@;/*@@ ghost (" ~sep:"," ~right:") */" + self#exp fmt ghosts + end ; (* Now the terminator *) - fprintf fmt "%s" instr_terminator + fprintf fmt "@]%s" instr_terminator in match i with | Skip _ -> fprintf fmt ";" @@ -1881,8 +1907,19 @@ class cil_printer () = object (self) else if nameOpt = None then printAttributes fmt a else fprintf fmt "(%a%a)" printAttributes a pname (a <> []) in - let pp_params fmt args pp_args = - fprintf fmt "%t(@[%t@])" name' + let partition_ghosts ghost_arg args = + match args with + | None -> None, [] + | Some l -> + let ghost_args, args = if is_ghost then + [], l + else + List.partition ghost_arg l + in + Some args, ghost_args + in + let pp_params fmt (args, ghost_args) pp_args = + fprintf fmt "%t@[<hv>(@[%t@])%t@]" name' (fun fmt -> match args with | (None | Some []) when isvararg -> fprintf fmt "..." @@ -1891,6 +1928,9 @@ class cil_printer () = object (self) | Some args -> Pretty_utils.pp_list ~sep:",@ " pp_args fmt args; if isvararg then fprintf fmt "@ , ...") + (fun fmt -> + Pretty_utils.pp_list ~pre:"@;/*@@ ghost (@[" ~suf:"@]) */" ~sep:",@ " + pp_args fmt ghost_args) in let pp_params fmt = match fundecl with | None -> @@ -1902,12 +1942,14 @@ class cil_printer () = object (self) (self#typ (Some (fun fmt -> fprintf fmt "%s" aname))) atype self#attributes rest in - pp_params fmt args pp_args + let p = partition_ghosts Cil.isGhostFormalVarDecl args in + pp_params fmt p pp_args | Some fundecl -> let args = try Some (Cil.getFormalsDecl fundecl) with Not_found -> None in - pp_params fmt args self#vdecl + let p = partition_ghosts Cil.isGhostFormalVarinfo args in + pp_params fmt p self#vdecl in self#typ (Some pp_params) fmt restyp diff --git a/src/kernel_services/ast_printing/cprint.ml b/src/kernel_services/ast_printing/cprint.ml index f8169bee15b726553ec0274ce89dfc58465824fd..36b2a4797aae3cf09a6df313fa153a663d157dac 100644 --- a/src/kernel_services/ast_printing/cprint.ml +++ b/src/kernel_services/ast_printing/cprint.ml @@ -251,9 +251,9 @@ and print_decl (n: string) fmt = function | ARRAY (d, al, e) -> fprintf fmt "%a[@[%a%a@]]" (print_decl n) d print_attributes al print_expression e - | PROTO(d, args, isva) -> - fprintf fmt "@[%a@;(%a)@]" - (print_decl n) d print_params (args,isva) + | PROTO(d, args, ghost_args, isva) -> + fprintf fmt "@[%a@;(%a) /*@@@ ghost (%a) */ @]" + (print_decl n) d print_params (args,isva) print_params (ghost_args, false) and print_fields fmt (flds : field_group list) = pp_list ~sep:"@ " print_field_group fmt flds @@ -366,12 +366,12 @@ and print_expression_level (lvl: int) fmt (exp : expression) = fprintf fmt "(@[%a@])@;%a" print_onlytype typ print_cast_expression iexp | CALL ({ expr_node = VARIABLE "__builtin_va_arg"}, - [arg; { expr_node = TYPE_SIZEOF (bt, dt) } ]) -> + [arg; { expr_node = TYPE_SIZEOF (bt, dt) } ], _) -> fprintf fmt "__builtin_va_arg(@[%a,@ %a@])" (print_expression_level 0) arg print_onlytype (bt, dt) - | CALL (exp, args) -> - fprintf fmt "%a(@[@;%a@])" - print_expression exp print_comma_exps args + | CALL (exp, args, ghost_args) -> + fprintf fmt "%a(@[@;%a@]) /*@@@ ghost (@[@;%a@]) */" + print_expression exp print_comma_exps args print_comma_exps ghost_args | CONSTANT (CONST_INT i) -> pp_print_string fmt i | CONSTANT (CONST_FLOAT f) -> pp_print_string fmt f | CONSTANT (CONST_CHAR c) -> fprintf fmt "'%s'" (escape_wstring c) diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml index ef22afcb87bfa37c7133f9e6fdfc8bc8e5ccc7bf..d0c3ac7a37378cb563dcb907b26abac3bb43ced6 100644 --- a/src/kernel_services/ast_queries/cil.ml +++ b/src/kernel_services/ast_queries/cil.ml @@ -302,6 +302,16 @@ let stmt_of_instr_list ?(loc=Location.unknown) = function (**** ATTRIBUTES ****) +(* Attributes are added as they are (e.g. if we add ["__attr"] and then ["attr"] both are added). + When checking for the presence of an attribute [x] or trying to remove it, underscores are + removed at the beginning and the end of the attribute for both the [x] attribute and the + attributes of the list. For example, if have a call: + + dropAttribute "__const" [ Attr("const", []) ; Attr("__const", []) ; Attr("__const__", []) ] + + The result is []. +*) + let bitfield_attribute_name = "FRAMA_C_BITFIELD_SIZE" (** Construct sorted lists of attributes ***) @@ -326,11 +336,12 @@ let addAttributes al0 (al: attributes) : attributes = List.fold_left (fun acc a -> addAttribute a acc) al al0 let dropAttribute (an: string) (al: attributes) = + let an = Extlib.strip_underscore an in List.filter (fun a -> attributeName a <> an) al -let hasAttribute (s: string) (al: attribute list) : bool = - let s = Extlib.strip_underscore s in - List.exists (fun a -> attributeName a = s) al +let hasAttribute (an: string) (al: attribute list) : bool = + let an = Extlib.strip_underscore an in + List.exists (fun a -> attributeName a = an) al let rec dropAttributes (anl: string list) (al: attributes) = match al with @@ -342,13 +353,15 @@ let rec dropAttributes (anl: string list) (al: attributes) = else if q' == q then al (* preserve sharing *) else a :: q' -let filterAttributes (s: string) (al: attribute list) : attribute list = - List.filter (fun a -> attributeName a = s) al +let filterAttributes (an: string) (al: attribute list) : attribute list = + let an = Extlib.strip_underscore an in + List.filter (fun a -> attributeName a = an) al -let findAttribute (s: string) (al: attribute list) : attrparam list = +let findAttribute (an: string) (al: attribute list) : attrparam list = + let an = Extlib.strip_underscore an in List.fold_left (fun acc -> function - | Attr (an, param) when an = s -> param @ acc + | Attr (_, param) as a0 when attributeName a0 = an -> param @ acc | _ -> acc) [] al @@ -555,6 +568,20 @@ let partitionAttributes in loop ([], [], []) attrs +let frama_c_ghost_formal = "__fc_ghost_formal" +let () = registerAttribute frama_c_ghost_formal (AttrName false) +let () = + registerAttribute (Extlib.strip_underscore frama_c_ghost_formal) (AttrName false) + +let frama_c_mutable = "__fc_mutable" +let () = registerAttribute frama_c_mutable (AttrName false) +let () = + registerAttribute (Extlib.strip_underscore frama_c_mutable) (AttrName false) + +let frama_c_init_obj = "__fc_initialized_object" +let () = registerAttribute frama_c_init_obj (AttrName false) +let () = + registerAttribute (Extlib.strip_underscore frama_c_init_obj) (AttrName false) let unrollType (t: typ) : typ = let rec withAttrs (al: attributes) (t: typ) : typ = @@ -573,7 +600,10 @@ let rec unrollTypeSkel = function | x -> x (* Make a varinfo. Used mostly as a helper function below *) -let makeVarinfo ?(source=true) ?(temp=false) ?(referenced=false) global formal name typ = +let makeVarinfo + ?(source=true) ?(temp=false) ?(referenced=false) ?(ghost=false) + global formal name typ + = let vi = { vorig_name = name; vname = name; @@ -591,7 +621,7 @@ let makeVarinfo ?(source=true) ?(temp=false) ?(referenced=false) global formal n vreferenced = referenced; vdescr = None; vdescrpure = true; - vghost = false; + vghost = ghost; vsource = source; vlogic_var_assoc = None } @@ -612,14 +642,22 @@ module FormalsDecl = let selfFormalsDecl = FormalsDecl.self let () = dependency_on_ast selfFormalsDecl -let makeFormalsVarDecl (n,t,a) = - let vi = makeVarinfo ~temp:false false true n t in +let makeFormalsVarDecl ?ghost (n,t,a) = + let vi = makeVarinfo ?ghost ~temp:false false true n t in vi.vattr <- a; vi +let isGhostFormalVarinfo vi = + hasAttribute frama_c_ghost_formal vi.vattr + +let isGhostFormalVarDecl (_name, _type, attr) = + hasAttribute frama_c_ghost_formal attr + let setFormalsDecl vi typ = match unrollType typ with | TFun(_, Some args, _, _) -> + let is_ghost d = vi.vghost || isGhostFormalVarDecl d in + let makeFormalsVarDecl x = makeFormalsVarDecl ~ghost:(is_ghost x) x in FormalsDecl.replace vi (List.map makeFormalsVarDecl args) | TFun(_,None,_,_) -> () | _ -> @@ -3509,17 +3547,6 @@ let typeOf_array_elem t = | TArray (ty_elem, _, _, _) -> ty_elem | _ -> Kernel.fatal "Not an array type %a" !pp_typ_ref t - -let frama_c_mutable = "__fc_mutable" -let () = registerAttribute frama_c_mutable (AttrName false) -let () = - registerAttribute (Extlib.strip_underscore frama_c_mutable) (AttrName false) - -let frama_c_init_obj = "__fc_initialized_object" -let () = registerAttribute frama_c_init_obj (AttrName false) -let () = - registerAttribute (Extlib.strip_underscore frama_c_init_obj) (AttrName false) - let no_op_coerce typ t = match typ with | Lreal -> true @@ -5201,11 +5228,11 @@ let rec findUniqueName ?(suffix="") fdec name = let refresh_local_name fdec vi = let new_name = findUniqueName fdec vi.vname in vi.vname <- new_name -let makeLocal ?(temp=false) ?referenced ?(formal=false) fdec name typ = +let makeLocal ?(temp=false) ?referenced ?ghost ?(formal=false) fdec name typ = (* a helper function *) let name = findUniqueName fdec name in fdec.smaxid <- 1 + fdec.smaxid; - let vi = makeVarinfo ~temp ?referenced false formal name typ in + let vi = makeVarinfo ~temp ?referenced ?ghost false formal name typ in vi (* Make a local variable and add it to a function *) @@ -5275,21 +5302,35 @@ let setMaxId (f: fundec) = * this one. If where = "^" then it is inserted first. If where = "$" then * it is inserted last. Otherwise where must be the name of a formal after * which to insert this. By default it is inserted at the end. *) -let makeFormalVar fdec ?(where = "$") name typ : varinfo = +let makeFormalVar fdec ?(ghost=fdec.svar.vghost) ?(where = "$") name typ : varinfo = + assert ((not fdec.svar.vghost) || ghost) ; + let makeit name = + let vi = makeLocal ~ghost ~formal:true fdec name typ in + if ghost && not fdec.svar.vghost then + vi.vattr <- addAttribute (Attr(frama_c_ghost_formal, [])) vi.vattr ; + vi + in + let error () = Kernel.fatal ~current:true + "makeFormalVar: cannot find insert-after formal %s" where + in (* Search for the insertion place *) - let makeit name = makeLocal ~formal:true fdec name typ in let rec loopFormals acc = function - [] -> + | [] -> + if where = "$" || (ghost && where = "^") then + let vi = makeit name in vi, List.rev (vi :: acc) + else error () + | f :: rest when not ghost && f.vghost -> if where = "$" then - let vi = makeit name in vi, List.rev (vi::acc) - else Kernel.fatal ~current:true - "makeFormalVar: cannot find insert-after formal %s" where - | f :: rest when f.vname = where -> + let vi = makeit name in vi, List.rev_append acc (vi :: f :: rest) + else error () + | f :: rest when f.vname = where && f.vghost = ghost -> let vi = makeit name in vi, List.rev_append acc (f :: vi :: rest) + | f :: rest when ghost && f.vghost && where = "^" -> + let vi = makeit name in vi, List.rev_append acc (vi :: f :: rest) | f :: rest -> loopFormals (f::acc) rest in let vi, newformals = - if where = "^" then let vi = makeit name in vi, vi :: fdec.sformals + if where = "^" && not ghost then let vi = makeit name in vi, vi :: fdec.sformals else loopFormals [] fdec.sformals in @@ -5793,6 +5834,11 @@ let splitFunctionTypeVI (fvi: varinfo) TFun (rt, args, isva, a) -> rt, args, isva, a | _ -> Kernel.abort "Function %s invoked on a non function type" fvi.vname +let argsToPairOfLists args = + List.partition + (fun f -> not(isGhostFormalVarDecl f)) + (argsToList args) + let remove_attributes_for_integral_promotion a = dropAttributes (bitfield_attribute_name :: spare_attributes_for_c_cast) a diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli index 2c60334fc5ed4d032a1d2c3e885049b7ae99a9d2..ac0127f5508893459f4947bb479043bdddf631c1 100644 --- a/src/kernel_services/ast_queries/cil.mli +++ b/src/kernel_services/ast_queries/cil.mli @@ -180,8 +180,11 @@ val setMaxId: fundec -> unit val selfFormalsDecl: State.t (** state of the table associating formals to each prototype. *) -val makeFormalsVarDecl: (string * typ * attributes) -> varinfo - (** creates a new varinfo for the parameter of a prototype. *) +val makeFormalsVarDecl: ?ghost:bool -> (string * typ * attributes) -> varinfo + (** creates a new varinfo for the parameter of a prototype. + By default, this formal variable is not ghost. + @modify 19.0-Potassium+dev adds a parameter for ghost status + *) (** Update the formals of a function declaration from its identifier and its type. For a function definition, use {!Cil.setFormals}. @@ -580,10 +583,17 @@ val isTypeTagType: logic_type -> bool @since Nitrogen-20111001 moved from cabs2cil *) val isVariadicListType: typ -> bool -(** Obtain the argument list ([] if None) *) +(** Obtain the argument list ([] if None). + @since 19.0-Potassium+dev Beware that it contains the ghost arguments. *) val argsToList: (string * typ * attributes) list option -> (string * typ * attributes) list +(** @since 19.0-Potassium+dev + Obtain the argument lists (non-ghost, ghosts) ([], [] if None) *) +val argsToPairOfLists: + (string * typ * attributes) list option -> + (string * typ * attributes) list * (string * typ * attributes) list + (** True if the argument is an array type *) val isArrayType: typ -> bool @@ -648,19 +658,33 @@ val splitFunctionTypeVI: [vsource] . The [referenced] argument defaults to [false], and corresponds to the field [vreferenced] . + The [ghost] argument defaults to [false], and corresponds to the field + [vghost] . The first unnamed argument specifies whether the varinfo is for a global and - the second is for formals. *) + the second is for formals. + @modify 19.0-Potassium adds an optional ghost parameter +*) val makeVarinfo: - ?source:bool -> ?temp:bool -> ?referenced:bool -> bool -> bool -> string -> - typ -> varinfo + ?source:bool -> ?temp:bool -> ?referenced:bool -> ?ghost:bool -> bool -> bool + -> string -> typ -> varinfo (** Make a formal variable for a function declaration. Insert it in both the sformals and the type of the function. You can optionally specify where to insert this one. If where = "^" then it is inserted first. If where = "$" then it is inserted last. Otherwise where must be the name of a formal after which to insert this. By default it is inserted at the end. + + The [ghost] parameter indicates if the variable should be inserted in the + list of formals or ghost formals. By default, it takes the ghost status of + the function where the formal is inserted. Note that: + + - specifying ghost to false if the function is ghost leads to an error + - when [where] is specified, its status must be the same as the formal to + insert (else, it cannot be found in the list of ghost or non ghost formals) + + @modify 19.0-Potassium adds the optional ghost parameter *) -val makeFormalVar: fundec -> ?where:string -> string -> typ -> varinfo +val makeFormalVar: fundec -> ?ghost:bool -> ?where:string -> string -> typ -> varinfo (** Make a local variable and add it to a function's slocals and to the given block (only if insert = true, which is the default). @@ -1171,6 +1195,12 @@ val dropAttribute: string -> attributes -> attributes * Maintains the attributes in sorted order *) val dropAttributes: string list -> attributes -> attributes +(** A varinfo marked with this attribute is known to be a ghost formal. + + @since 19.0-Potassium+dev +*) +val frama_c_ghost_formal: string + (** a field struct marked with this attribute is known to be mutable, i.e. it can be modified even on a const object. @@ -1191,6 +1221,18 @@ val frama_c_init_obj: string *) val is_mutable_or_initialized: lval -> bool +(** [true] if the given varinfo is a ghost formal variable. + + @since 19.0-Potassium+dev +*) +val isGhostFormalVarinfo: varinfo -> bool + +(** [true] if the given formal declaration corresponds to a ghost formal variable. + + @since 19.0-Potassium+dev +*) +val isGhostFormalVarDecl: (string * typ * attributes) -> bool + (** Remove attributes whose name appears in the first argument that are present anywhere in the fully expanded version of the type. @since Oxygen-20120901 diff --git a/src/kernel_services/parsetree/cabs.ml b/src/kernel_services/parsetree/cabs.ml index 8bd397788c5cbdbfe152a59cd224cf720b233e59..462f4edd55adad2feecc6fb1b61de3ddd09ed363 100644 --- a/src/kernel_services/parsetree/cabs.ml +++ b/src/kernel_services/parsetree/cabs.ml @@ -121,7 +121,7 @@ and decl_type = (* Prints "decl [ attrs exp ]". * decl is never a PTR. *) | PTR of attribute list * decl_type (* Prints "* attrs decl" *) - | PROTO of decl_type * single_name list * bool + | PROTO of decl_type * single_name list * single_name list * bool (* Prints "decl (args[, ...])". * decl is never a PTR.*) @@ -299,7 +299,7 @@ and cabsexp = (* There is a special form of CALL in which the function called is __builtin_va_arg and the second argument is sizeof(T). This should be printed as just T *) - | CALL of expression * expression list + | CALL of expression * expression list * expression list | COMMA of expression list | CONSTANT of constant | PAREN of expression diff --git a/src/kernel_services/visitors/cabsvisit.ml b/src/kernel_services/visitors/cabsvisit.ml index d07ddf97c3ecd54d9b6e83be99c9f85a602ae1ba..2237d0abe0a4a9b6e410c3f699d96613d437dc9d 100644 --- a/src/kernel_services/visitors/cabsvisit.ml +++ b/src/kernel_services/visitors/cabsvisit.ml @@ -193,14 +193,17 @@ and childrenDeclType isfundef vis dt = let al' = mapNoCopy (childrenAttribute vis) al in let dt1' = visitCabsDeclType vis isfundef dt1 in if al' != al || dt1' != dt1 then PTR(al', dt1') else dt - | PROTO (dt1, snl, b) -> + | PROTO (dt1, snl, gsnl, b) -> (* Do not propagate isfundef further *) let dt1' = visitCabsDeclType vis false dt1 in let _ = vis#vEnterScope () in let snl' = mapNoCopy (childrenSingleName vis NVar) snl in + let gsnl' = mapNoCopy (childrenSingleName vis NVar) gsnl in (* Exit the scope only if not in a function definition *) let _ = if not isfundef then vis#vExitScope () in - if dt1' != dt1 || snl' != snl then PROTO(dt1', snl', b) else dt + if dt1' != dt1 || snl' != snl || gsnl' != gsnl then + PROTO(dt1', snl', gsnl' , b) + else dt and childrenNameGroup vis (kind: nameKind) ((s, nl) as input) = @@ -430,11 +433,12 @@ and childrenExpression vis e = let ie' = visitCabsInitExpression vis ie in if s' != s || dt' != dt || ie' != ie then { e with expr_node = CAST ((s', dt'), ie')} else e - | CALL (f, el) -> + | CALL (f, el, gl) -> let f' = ve f in let el' = mapNoCopy ve el in + let gl' = mapNoCopy ve gl in if f' != f || el' != el then - { e with expr_node = CALL (f', el')} else e + { e with expr_node = CALL (f', el',gl')} else e | COMMA el -> let el' = mapNoCopy ve el in if el' != el then { e with expr_node = COMMA (el') } else e diff --git a/src/plugins/variadic/extends.ml b/src/plugins/variadic/extends.ml index 3b796f36c97be94451b34b454527c86ec004f633..c838e0a5b4a0b1aa44070f36a322129e79274d40 100644 --- a/src/plugins/variadic/extends.ml +++ b/src/plugins/variadic/extends.ml @@ -35,6 +35,11 @@ module Typ = struct | TFun (_,args,_,_) -> Cil.argsToList args | _ -> invalid_arg "params" + let ghost_partitioned_params typ = + match Cil.unrollType typ with + | TFun (_,args,_,_) -> Cil.argsToPairOfLists args + | _ -> invalid_arg "params" + let params_types typ = List.map (fun (_,typ,_) -> typ) (params typ) diff --git a/src/plugins/variadic/extends.mli b/src/plugins/variadic/extends.mli index 93f8e685daabc9cd856d1c19942679921ba8803f..916c7322a4b20634c4b64fa8294f03b7c01a9b9f 100644 --- a/src/plugins/variadic/extends.mli +++ b/src/plugins/variadic/extends.mli @@ -25,6 +25,9 @@ open Cil_types module Typ : sig val attributes_less_equal : typ -> typ -> bool val params : typ -> (string * typ * attributes) list + val ghost_partitioned_params : typ -> + (string * typ * attributes) list * + (string * typ * attributes) list val params_types : typ -> typ list val params_count : typ -> int val is_variadic : typ -> bool diff --git a/src/plugins/variadic/generic.ml b/src/plugins/variadic/generic.ml index ace7d6b5d8b31e3f93c60628c24609cec8fff14d..af1f6658b94062ea666141de0224163252757e8b 100644 --- a/src/plugins/variadic/generic.ml +++ b/src/plugins/variadic/generic.ml @@ -42,7 +42,9 @@ let translate_type = function | TFun (ret_typ, args, is_variadic, attributes) -> let new_args = if is_variadic - then Some (Cil.argsToList args @ [vpar]) + then + let ng_args, g_args = Cil.argsToPairOfLists args in + Some (ng_args @ [vpar] @ g_args) else args in TFun (ret_typ, new_args, false, attributes) @@ -141,9 +143,12 @@ let translate_call ~fundec block loc mk_call callee pars = Self.result ~current:true ~level:2 "Generic translation of call to variadic function."; - (* Split params into static and variadic part *) - let static_size = List.length (Typ.params (Cil.typeOf callee)) - 1 in - let s_exps, v_exps = List.break static_size pars in + (* Split params into static, variadic and ghost part *) + let ng_params, g_params = Typ.ghost_partitioned_params (Cil.typeOf callee) in + let static_size = List.length ng_params - 1 in + let s_exps, r_exps = List.break static_size pars in + let variadic_size = (List.length r_exps) - (List.length g_params) in + let v_exps, g_exps = List.break variadic_size r_exps in (* Create temporary variables to hold parameters *) let add_var i exp = @@ -168,6 +173,6 @@ let translate_call ~fundec block loc mk_call callee pars = (* Translate the call *) let exp_vargs = Cil.mkAddrOrStartOf ~loc (Cil.var vargs) in let new_arg = Cil.mkCast ~force:false ~e:exp_vargs ~newt:(vpar_typ []) in - let new_args = s_exps @ [new_arg] in + let new_args = s_exps @ [new_arg] @ g_exps in let call = mk_call callee new_args in instrs @ [call] diff --git a/src/plugins/variadic/tests/declared/empty-vpar-with-ghost.i b/src/plugins/variadic/tests/declared/empty-vpar-with-ghost.i new file mode 100644 index 0000000000000000000000000000000000000000..58133079e349be5c8510d3f9d16aa333af62719c --- /dev/null +++ b/src/plugins/variadic/tests/declared/empty-vpar-with-ghost.i @@ -0,0 +1,10 @@ +/*@ behavior bhv: + @ requires c>0; + @ requires a<=42; +*/ +void f(const int a, int, int c,...) /*@ ghost(int x) */; + +int main(){ + f(1, 2, 3) /*@ ghost(4) */; + return 0; +} diff --git a/src/plugins/variadic/tests/declared/empty-vpar.c b/src/plugins/variadic/tests/declared/empty-vpar.i similarity index 100% rename from src/plugins/variadic/tests/declared/empty-vpar.c rename to src/plugins/variadic/tests/declared/empty-vpar.i diff --git a/src/plugins/variadic/tests/declared/function-ptr-with-ghost.i b/src/plugins/variadic/tests/declared/function-ptr-with-ghost.i new file mode 100644 index 0000000000000000000000000000000000000000..0ab1f1a1c0c7e5597794b56a0192ee6cb5cf9206 --- /dev/null +++ b/src/plugins/variadic/tests/declared/function-ptr-with-ghost.i @@ -0,0 +1,8 @@ +void function(void (*p) (int, ...) /*@ ghost (int v) */, int x){ + (*p) (x, 1, 2, 3) /*@ ghost (4) */; +} +void va_f(int, ...) /*@ ghost(int x) */ ; + +int main(void){ + function(va_f, 3); +} \ No newline at end of file diff --git a/src/plugins/variadic/tests/declared/label.c b/src/plugins/variadic/tests/declared/label.i similarity index 100% rename from src/plugins/variadic/tests/declared/label.c rename to src/plugins/variadic/tests/declared/label.i diff --git a/src/plugins/variadic/tests/declared/multi.c b/src/plugins/variadic/tests/declared/multi.i similarity index 100% rename from src/plugins/variadic/tests/declared/multi.c rename to src/plugins/variadic/tests/declared/multi.i diff --git a/src/plugins/variadic/tests/declared/no-va-with-ghost.i b/src/plugins/variadic/tests/declared/no-va-with-ghost.i new file mode 100644 index 0000000000000000000000000000000000000000..695904970b910b711d2c199fcfb88874a50e6fc8 --- /dev/null +++ b/src/plugins/variadic/tests/declared/no-va-with-ghost.i @@ -0,0 +1,5 @@ +int f(int a, int b, int c) /*@ ghost(int x) */; + +int main(){ + return f(1, 2, 3) /*@ ghost(4) */; +} diff --git a/src/plugins/variadic/tests/declared/no-va.c b/src/plugins/variadic/tests/declared/no-va.i similarity index 100% rename from src/plugins/variadic/tests/declared/no-va.c rename to src/plugins/variadic/tests/declared/no-va.i diff --git a/src/plugins/variadic/tests/declared/oracle/empty-vpar-with-ghost.res.oracle b/src/plugins/variadic/tests/declared/oracle/empty-vpar-with-ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..77d342b3dd8113ce3c181cca5993138243e6bbe4 --- /dev/null +++ b/src/plugins/variadic/tests/declared/oracle/empty-vpar-with-ghost.res.oracle @@ -0,0 +1,35 @@ +[variadic] tests/declared/empty-vpar-with-ghost.i:1: + Declaration of variadic function f. +[variadic] tests/declared/empty-vpar-with-ghost.i:8: + Generic translation of call to variadic function. +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[kernel] tests/declared/empty-vpar-with-ghost.i:8: Warning: + No code nor implicit assigns clause for function f, generating default assigns from the prototype +[eva] using specification for function f +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + __retres ∈ {0} +/* Generated by Frama-C */ +/*@ assigns \nothing; + + behavior bhv: + requires c > 0; + requires a ≤ 42; */ +void f(int const a, int, int c, void * const *__va_params) + /*@ ghost (int x) */; + +int main(void) +{ + int __retres; + { + void *__va_args[1] = {(void *)0}; + f(1,2,3,(void * const *)(__va_args)) /*@ ghost (4) */; + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/variadic/tests/declared/oracle/empty-vpar.res.oracle b/src/plugins/variadic/tests/declared/oracle/empty-vpar.res.oracle index 0603bbc1ab9646011fbd050407523a1a8fddf452..c028e9e151d91ac8f3d848668a9ead0863bef9f1 100644 --- a/src/plugins/variadic/tests/declared/oracle/empty-vpar.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/empty-vpar.res.oracle @@ -1,10 +1,10 @@ -[variadic] tests/declared/empty-vpar.c:1: Declaration of variadic function f. -[variadic] tests/declared/empty-vpar.c:8: +[variadic] tests/declared/empty-vpar.i:1: Declaration of variadic function f. +[variadic] tests/declared/empty-vpar.i:8: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel] tests/declared/empty-vpar.c:8: Warning: +[kernel] tests/declared/empty-vpar.i:8: Warning: No code nor implicit assigns clause for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/oracle/function-ptr-with-ghost.res.oracle b/src/plugins/variadic/tests/declared/oracle/function-ptr-with-ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f81ac2a39cfd228c91a75b2f1f0ea81f0c32a683 --- /dev/null +++ b/src/plugins/variadic/tests/declared/oracle/function-ptr-with-ghost.res.oracle @@ -0,0 +1,42 @@ +[variadic] tests/declared/function-ptr-with-ghost.i:4: + Declaration of variadic function va_f. +[variadic] tests/declared/function-ptr-with-ghost.i:2: + Generic translation of call to variadic function. +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[kernel:annot:missing-spec] tests/declared/function-ptr-with-ghost.i:2: Warning: + Neither code nor specification for function va_f, generating default assigns from the prototype +[eva] using specification for function va_f +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function function: + +[eva:final-states] Values at end of function main: + __retres ∈ {0} +/* Generated by Frama-C */ +void function(void (*p)(int , void * const *__va_params) /*@ ghost (int v) */, + int x) +{ + { + int __va_arg0 = 1; + int __va_arg1 = 2; + int __va_arg2 = 3; + void *__va_args[3] = {& __va_arg0, & __va_arg1, & __va_arg2}; + (*p)(x,(void * const *)(__va_args)) /*@ ghost (4) */; + } + return; +} + +/*@ assigns \nothing; */ +void va_f(int, void * const *__va_params) /*@ ghost (int x) */; + +int main(void) +{ + int __retres; + function(& va_f,3); + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/variadic/tests/declared/oracle/label.res.oracle b/src/plugins/variadic/tests/declared/oracle/label.res.oracle index 0c51782917566ef261529445f19a27d6fa5749b2..427868a9c76ae47b935ff087454c0ef2b589dc3d 100644 --- a/src/plugins/variadic/tests/declared/oracle/label.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/label.res.oracle @@ -1,10 +1,10 @@ -[variadic] tests/declared/label.c:4: Declaration of variadic function f. -[variadic] tests/declared/label.c:8: +[variadic] tests/declared/label.i:4: Declaration of variadic function f. +[variadic] tests/declared/label.i:8: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel:annot:missing-spec] tests/declared/label.c:8: Warning: +[kernel:annot:missing-spec] tests/declared/label.i:8: Warning: Neither code nor specification for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/oracle/multi.res.oracle b/src/plugins/variadic/tests/declared/oracle/multi.res.oracle index 58b1c09b3834a3614654b7116de3ec709e16417d..adcbb2b04d43ce39487600c92e43c8f4c6d65a55 100644 --- a/src/plugins/variadic/tests/declared/oracle/multi.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/multi.res.oracle @@ -1,16 +1,16 @@ -[variadic] tests/declared/multi.c:1: Declaration of variadic function f. -[variadic] tests/declared/multi.c:12: Declaration of variadic function g. -[variadic] tests/declared/multi.c:9: +[variadic] tests/declared/multi.i:1: Declaration of variadic function f. +[variadic] tests/declared/multi.i:12: Declaration of variadic function g. +[variadic] tests/declared/multi.i:9: Generic translation of call to variadic function. -[variadic] tests/declared/multi.c:18: +[variadic] tests/declared/multi.i:18: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel] tests/declared/multi.c:18: Warning: +[kernel] tests/declared/multi.i:18: Warning: No code nor implicit assigns clause for function g, generating default assigns from the prototype [eva] using specification for function g -[kernel] tests/declared/multi.c:9: Warning: +[kernel] tests/declared/multi.i:9: Warning: No code nor implicit assigns clause for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/oracle/no-va-with-ghost.res.oracle b/src/plugins/variadic/tests/declared/oracle/no-va-with-ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..71fffe6ce3458de80a11bed3ab9404ef530b1137 --- /dev/null +++ b/src/plugins/variadic/tests/declared/oracle/no-va-with-ghost.res.oracle @@ -0,0 +1,23 @@ +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[kernel:annot:missing-spec] tests/declared/no-va-with-ghost.i:4: Warning: + Neither code nor specification for function f, generating default assigns from the prototype +[eva] using specification for function f +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + +/* Generated by Frama-C */ +/*@ assigns \result; + assigns \result \from a, b, c; */ +int f(int a, int b, int c) /*@ ghost (int x) */; + +int main(void) +{ + int tmp; + tmp = f(1,2,3) /*@ ghost (4) */; + return tmp; +} + + diff --git a/src/plugins/variadic/tests/declared/oracle/no-va.res.oracle b/src/plugins/variadic/tests/declared/oracle/no-va.res.oracle index df93a80eca42e87351c30aa535b2914f7cd8cd48..f00b72688a6be12492c6b91ac8db6c8ab0a43dcc 100644 --- a/src/plugins/variadic/tests/declared/oracle/no-va.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/no-va.res.oracle @@ -1,7 +1,7 @@ [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel:annot:missing-spec] tests/declared/no-va.c:4: Warning: +[kernel:annot:missing-spec] tests/declared/no-va.i:4: Warning: Neither code nor specification for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/oracle/rvalues-with-ghost.res.oracle b/src/plugins/variadic/tests/declared/oracle/rvalues-with-ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9dde9d6d2dfbaa061b976f6f32aa14042c6fa493 --- /dev/null +++ b/src/plugins/variadic/tests/declared/oracle/rvalues-with-ghost.res.oracle @@ -0,0 +1,38 @@ +[variadic] tests/declared/rvalues-with-ghost.i:1: + Declaration of variadic function f. +[variadic] tests/declared/rvalues-with-ghost.i:5: + Generic translation of call to variadic function. +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[kernel:annot:missing-spec] tests/declared/rvalues-with-ghost.i:5: Warning: + Neither code nor specification for function f, generating default assigns from the prototype +[eva] using specification for function f +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + x ∈ {0} + i ∈ [--..--] + __va_arg0 ∈ {5} + __va_arg1 ∈ {20} + __va_arg2 ∈ {{ &x }} + __va_args[0] ∈ {{ (void *)&__va_arg0 }} + [1] ∈ {{ (void *)&__va_arg1 }} + [2] ∈ {{ (void *)&__va_arg2 }} +/* Generated by Frama-C */ +/*@ assigns \result; + assigns \result \from a; */ +int f(int a, void * const *__va_params) /*@ ghost (int x) */; + +int main(void) +{ + int x = 0; + int __va_arg0 = 2 + 3; + int __va_arg1 = 4 * 5; + int *__va_arg2 = & x; + void *__va_args[3] = {& __va_arg0, & __va_arg1, & __va_arg2}; + int i = f(1,(void * const *)(__va_args)) /*@ ghost (x + 3) */; + return i; +} + + diff --git a/src/plugins/variadic/tests/declared/oracle/rvalues.res.oracle b/src/plugins/variadic/tests/declared/oracle/rvalues.res.oracle index 99e27480afacce5296c6d5d0e4b2c5c5f387200f..82863e34c748ad7430e51e9490d9e1cdefa51f28 100644 --- a/src/plugins/variadic/tests/declared/oracle/rvalues.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/rvalues.res.oracle @@ -1,10 +1,10 @@ -[variadic] tests/declared/rvalues.c:1: Declaration of variadic function f. -[variadic] tests/declared/rvalues.c:5: +[variadic] tests/declared/rvalues.i:1: Declaration of variadic function f. +[variadic] tests/declared/rvalues.i:5: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel:annot:missing-spec] tests/declared/rvalues.c:5: Warning: +[kernel:annot:missing-spec] tests/declared/rvalues.i:5: Warning: Neither code nor specification for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/oracle/simple-with-ghost.res.oracle b/src/plugins/variadic/tests/declared/oracle/simple-with-ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fa2e63b8a114173eac0d131f2fe7c203d8ef6592 --- /dev/null +++ b/src/plugins/variadic/tests/declared/oracle/simple-with-ghost.res.oracle @@ -0,0 +1,40 @@ +[variadic] tests/declared/simple-with-ghost.i:1: + Declaration of variadic function f. +[variadic] tests/declared/simple-with-ghost.i:9: + Generic translation of call to variadic function. +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[kernel] tests/declared/simple-with-ghost.i:9: Warning: + No code nor implicit assigns clause for function f, generating default assigns from the prototype +[eva] using specification for function f +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + +/* Generated by Frama-C */ +/*@ assigns \result; + assigns \result \from a, c; + + behavior bhv: + requires c > 0; + requires a ≤ 42; + ensures \result > 0; + */ +int f(int const a, int, int c, void * const *__va_params) + /*@ ghost (int x) */; + +int main(void) +{ + int tmp; + { + int __va_arg0 = 4; + int __va_arg1 = 5; + int __va_arg2 = 6; + void *__va_args[3] = {& __va_arg0, & __va_arg1, & __va_arg2}; + tmp = f(1,2,3,(void * const *)(__va_args)) /*@ ghost (7) */; + } + return tmp; +} + + diff --git a/src/plugins/variadic/tests/declared/oracle/simple.res.oracle b/src/plugins/variadic/tests/declared/oracle/simple.res.oracle index d36878734cf263a85f28807227f051986d50fac3..9112e9470077a769eaa504faed32bb9cf3caf757 100644 --- a/src/plugins/variadic/tests/declared/oracle/simple.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/simple.res.oracle @@ -1,10 +1,10 @@ -[variadic] tests/declared/simple.c:1: Declaration of variadic function f. -[variadic] tests/declared/simple.c:9: +[variadic] tests/declared/simple.i:1: Declaration of variadic function f. +[variadic] tests/declared/simple.i:9: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel] tests/declared/simple.c:9: Warning: +[kernel] tests/declared/simple.i:9: Warning: No code nor implicit assigns clause for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/oracle/struct.res.oracle b/src/plugins/variadic/tests/declared/oracle/struct.res.oracle index 37d0817d12f1fd03bf5342a582c78716c10e7749..851c21816f4c535bc3c0e443d014611b540c9768 100644 --- a/src/plugins/variadic/tests/declared/oracle/struct.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/struct.res.oracle @@ -1,10 +1,10 @@ -[variadic] tests/declared/struct.c:5: Declaration of variadic function f. -[variadic] tests/declared/struct.c:10: +[variadic] tests/declared/struct.i:5: Declaration of variadic function f. +[variadic] tests/declared/struct.i:10: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel:annot:missing-spec] tests/declared/struct.c:10: Warning: +[kernel:annot:missing-spec] tests/declared/struct.i:10: Warning: Neither code nor specification for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/oracle/typedefed_function-with-ghost.res.oracle b/src/plugins/variadic/tests/declared/oracle/typedefed_function-with-ghost.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3038502c8ded9a4b0149591a360b55e8c7118292 --- /dev/null +++ b/src/plugins/variadic/tests/declared/oracle/typedefed_function-with-ghost.res.oracle @@ -0,0 +1,33 @@ +[variadic] tests/declared/typedefed_function-with-ghost.i:2: + Declaration of variadic function f. +[variadic] tests/declared/typedefed_function-with-ghost.i:5: + Generic translation of call to variadic function. +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[kernel:annot:missing-spec] tests/declared/typedefed_function-with-ghost.i:5: Warning: + Neither code nor specification for function f, generating default assigns from the prototype +[eva] using specification for function f +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + __retres ∈ {0} +/* Generated by Frama-C */ +typedef void T(int , void * const *__va_params) /*@ ghost (int ) */; +/*@ assigns \nothing; */ +extern T f; + +int main(void) +{ + int __retres; + { + int __va_arg0 = 2; + int __va_arg1 = 0; + void *__va_args[2] = {& __va_arg0, & __va_arg1}; + f(1,(void * const *)(__va_args)) /*@ ghost (3) */; + } + __retres = 0; + return __retres; +} + + diff --git a/src/plugins/variadic/tests/declared/oracle/typedefed_function.res.oracle b/src/plugins/variadic/tests/declared/oracle/typedefed_function.res.oracle index b497ee3c477f455d1f22aad98c26929e4a251716..fa5cdfe98bbd3fb99d79eaceab46e2b687038d64 100644 --- a/src/plugins/variadic/tests/declared/oracle/typedefed_function.res.oracle +++ b/src/plugins/variadic/tests/declared/oracle/typedefed_function.res.oracle @@ -1,11 +1,11 @@ -[variadic] tests/declared/typedefed_function.c:2: +[variadic] tests/declared/typedefed_function.i:2: Declaration of variadic function f. -[variadic] tests/declared/typedefed_function.c:5: +[variadic] tests/declared/typedefed_function.i:5: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[kernel:annot:missing-spec] tests/declared/typedefed_function.c:5: Warning: +[kernel:annot:missing-spec] tests/declared/typedefed_function.i:5: Warning: Neither code nor specification for function f, generating default assigns from the prototype [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/declared/rvalues-with-ghost.i b/src/plugins/variadic/tests/declared/rvalues-with-ghost.i new file mode 100644 index 0000000000000000000000000000000000000000..6452e6529824d5ff7aade70f2574f6f7c9ac4efe --- /dev/null +++ b/src/plugins/variadic/tests/declared/rvalues-with-ghost.i @@ -0,0 +1,7 @@ +int f(int a,...) /*@ ghost(int x) */; + +int main(){ + int x = 0; + int i = f(1, 2+3, 4*5, &x) /*@ ghost(x+3) */; + return i; +} diff --git a/src/plugins/variadic/tests/declared/rvalues.c b/src/plugins/variadic/tests/declared/rvalues.i similarity index 100% rename from src/plugins/variadic/tests/declared/rvalues.c rename to src/plugins/variadic/tests/declared/rvalues.i diff --git a/src/plugins/variadic/tests/declared/simple-with-ghost.i b/src/plugins/variadic/tests/declared/simple-with-ghost.i new file mode 100644 index 0000000000000000000000000000000000000000..06afdffe232d2490e1e97d85dd70832a95fe9881 --- /dev/null +++ b/src/plugins/variadic/tests/declared/simple-with-ghost.i @@ -0,0 +1,10 @@ +/*@ behavior bhv: + @ requires c>0; + @ requires a<=42; + @ ensures \result > 0; +*/ +int f(const int a, int, int c,...) /*@ ghost (int x) */; + +int main(){ + return f(1, 2, 3, 4, 5, 6) /*@ ghost(7) */; +} diff --git a/src/plugins/variadic/tests/declared/simple.c b/src/plugins/variadic/tests/declared/simple.i similarity index 100% rename from src/plugins/variadic/tests/declared/simple.c rename to src/plugins/variadic/tests/declared/simple.i diff --git a/src/plugins/variadic/tests/declared/struct.c b/src/plugins/variadic/tests/declared/struct.i similarity index 100% rename from src/plugins/variadic/tests/declared/struct.c rename to src/plugins/variadic/tests/declared/struct.i diff --git a/src/plugins/variadic/tests/declared/typedefed_function-with-ghost.i b/src/plugins/variadic/tests/declared/typedefed_function-with-ghost.i new file mode 100644 index 0000000000000000000000000000000000000000..32116ed21ed39bb2b8ba8e1dcfed1ce3236d6770 --- /dev/null +++ b/src/plugins/variadic/tests/declared/typedefed_function-with-ghost.i @@ -0,0 +1,7 @@ +typedef void T(int, ...) /*@ ghost (int) */ ; +extern T f; + +int main () { + f(1, 2, 0) /*@ ghost(3) */; + return 0; +} diff --git a/src/plugins/variadic/tests/declared/typedefed_function.c b/src/plugins/variadic/tests/declared/typedefed_function.i similarity index 100% rename from src/plugins/variadic/tests/declared/typedefed_function.c rename to src/plugins/variadic/tests/declared/typedefed_function.i diff --git a/src/plugins/variadic/tests/defined/oracle/recursive.res.oracle b/src/plugins/variadic/tests/defined/oracle/recursive.res.oracle index 90e4c436eef05876c5fa6f7a399d1ed24a7a8cc9..9fcbfae2ed2afb6f4498cd8fc01efebb747ea53f 100644 --- a/src/plugins/variadic/tests/defined/oracle/recursive.res.oracle +++ b/src/plugins/variadic/tests/defined/oracle/recursive.res.oracle @@ -1,14 +1,14 @@ -[variadic] tests/defined/recursive.c:4: Declaration of variadic function f. -[variadic] tests/defined/recursive.c:8: +[variadic] tests/defined/recursive.i:4: Declaration of variadic function f. +[variadic] tests/defined/recursive.i:8: Generic translation of call to variadic function. -[variadic] tests/defined/recursive.c:12: +[variadic] tests/defined/recursive.i:12: Generic translation of call to variadic function. [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed -[eva] tests/defined/recursive.c:8: Warning: +[eva] tests/defined/recursive.i:8: Warning: recursive call during value analysis - of f (f <- f :: tests/defined/recursive.c:12 <- main). Assuming the call has + of f (f <- f :: tests/defined/recursive.i:12 <- main). Assuming the call has no effect. The analysis will be unsound. [eva] using specification for function f [eva] done for function main diff --git a/src/plugins/variadic/tests/defined/recursive.c b/src/plugins/variadic/tests/defined/recursive.i similarity index 100% rename from src/plugins/variadic/tests/defined/recursive.c rename to src/plugins/variadic/tests/defined/recursive.i diff --git a/src/plugins/variadic/tests/erroneous/invalid_libc.c b/src/plugins/variadic/tests/erroneous/invalid_libc.i similarity index 100% rename from src/plugins/variadic/tests/erroneous/invalid_libc.c rename to src/plugins/variadic/tests/erroneous/invalid_libc.i diff --git a/src/plugins/variadic/tests/erroneous/no-libc.c b/src/plugins/variadic/tests/erroneous/no-libc.i similarity index 100% rename from src/plugins/variadic/tests/erroneous/no-libc.c rename to src/plugins/variadic/tests/erroneous/no-libc.i diff --git a/src/plugins/variadic/tests/erroneous/no-param.c b/src/plugins/variadic/tests/erroneous/no-param.i similarity index 100% rename from src/plugins/variadic/tests/erroneous/no-param.c rename to src/plugins/variadic/tests/erroneous/no-param.i diff --git a/src/plugins/variadic/tests/erroneous/not-enough-par.c b/src/plugins/variadic/tests/erroneous/not-enough-par.i similarity index 100% rename from src/plugins/variadic/tests/erroneous/not-enough-par.c rename to src/plugins/variadic/tests/erroneous/not-enough-par.i diff --git a/src/plugins/variadic/tests/erroneous/oracle/invalid_libc.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/invalid_libc.res.oracle index de3bfcfe76b1ff09db17d7ec9e9bc67d88a32627..321767e52205d5455405b950258b4c4928dab8cd 100644 --- a/src/plugins/variadic/tests/erroneous/oracle/invalid_libc.res.oracle +++ b/src/plugins/variadic/tests/erroneous/oracle/invalid_libc.res.oracle @@ -1,7 +1,7 @@ -[variadic] tests/erroneous/invalid_libc.c:2: +[variadic] tests/erroneous/invalid_libc.i:2: Declaration of variadic function fprintf. -[variadic] tests/erroneous/invalid_libc.c:2: Warning: +[variadic] tests/erroneous/invalid_libc.i:2: Warning: The standard function fprintf was expected to have at least 2 fixed parameters but only has 1. No variadic translation will be performed. -[variadic] tests/erroneous/invalid_libc.c:6: +[variadic] tests/erroneous/invalid_libc.i:6: Generic translation of call to variadic function. diff --git a/src/plugins/variadic/tests/erroneous/oracle/no-libc.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/no-libc.res.oracle index 121d95f029cf9c1cb126173e22f4dee7ec656c8a..64101cd01a75097315b353cb57906d47cfb2b087 100644 --- a/src/plugins/variadic/tests/erroneous/oracle/no-libc.res.oracle +++ b/src/plugins/variadic/tests/erroneous/oracle/no-libc.res.oracle @@ -1,5 +1,5 @@ -[variadic] tests/erroneous/no-libc.c:1: Declaration of variadic function printf. +[variadic] tests/erroneous/no-libc.i:1: Declaration of variadic function printf. [variadic] Warning: Unable to locate ACSL predicate valid_read_string which should be in the Frama-C LibC. Correct specifications can't be generated. [variadic] Warning: Unable to locate global __fc_stdout which should be in the Frama-C LibC. Correct specifications can't be generated. -[variadic] tests/erroneous/no-libc.c:5: +[variadic] tests/erroneous/no-libc.i:5: Translating call to printf to a call to the specialized version printf_va_1. diff --git a/src/plugins/variadic/tests/erroneous/oracle/not-enough-par.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/not-enough-par.res.oracle index 82b7439890793d48dc358156d48bcee6e153366e..c05a4ba9b29af3af3f01dcbf46d240984404e5b4 100644 --- a/src/plugins/variadic/tests/erroneous/oracle/not-enough-par.res.oracle +++ b/src/plugins/variadic/tests/erroneous/oracle/not-enough-par.res.oracle @@ -1,5 +1,4 @@ -[kernel] tests/erroneous/not-enough-par.c:4: User Error: +[kernel] tests/erroneous/not-enough-par.i:4: User Error: Too few arguments in call to f. -[kernel] User Error: stopping on file "tests/erroneous/not-enough-par.c" that has errors. Add - '-kernel-msg-key pp' for preprocessing command. +[kernel] User Error: stopping on file "tests/erroneous/not-enough-par.i" that has errors. [kernel] Frama-C aborted: invalid user input. diff --git a/src/plugins/variadic/tests/erroneous/oracle/variadic-builtin.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/variadic-builtin.res.oracle index 780e418ed94a3b3f92cfd3721e4789ae5b6c793f..30f7e2cf18c5d3543616fe729f4c0856b7693785 100644 --- a/src/plugins/variadic/tests/erroneous/oracle/variadic-builtin.res.oracle +++ b/src/plugins/variadic/tests/erroneous/oracle/variadic-builtin.res.oracle @@ -1,4 +1,4 @@ -[variadic] tests/erroneous/variadic-builtin.c:1: +[variadic] tests/erroneous/variadic-builtin.i:1: Variadic builtin Frama_C_show_each_warning left untransformed. [kernel] Plug-in variadic aborted: unimplemented feature. You may send a feature request at http://bts.frama-c.com with: diff --git a/src/plugins/variadic/tests/erroneous/variadic-builtin.c b/src/plugins/variadic/tests/erroneous/variadic-builtin.i similarity index 100% rename from src/plugins/variadic/tests/erroneous/variadic-builtin.c rename to src/plugins/variadic/tests/erroneous/variadic-builtin.i diff --git a/src/plugins/variadic/tests/known/oracle/printf_redefined.res.oracle b/src/plugins/variadic/tests/known/oracle/printf_redefined.res.oracle index 9b7494fd8342d16b8e56adb562b395d9c87edb25..41b4f0c4fb811f31682c40d4a3d82aba5efd6ef7 100644 --- a/src/plugins/variadic/tests/known/oracle/printf_redefined.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/printf_redefined.res.oracle @@ -1,10 +1,10 @@ -[variadic] tests/known/printf_redefined.c:3: +[variadic] tests/known/printf_redefined.i:3: Declaration of variadic function printf. [variadic] Warning: Unable to locate ACSL predicate valid_read_string which should be in the Frama-C LibC. Correct specifications can't be generated. [variadic] Warning: Unable to locate global __fc_stdout which should be in the Frama-C LibC. Correct specifications can't be generated. -[variadic] tests/known/printf_redefined.c:7: +[variadic] tests/known/printf_redefined.i:7: Translating call to printf to a call to the specialized version printf_va_1. -[variadic] tests/known/printf_redefined.c:7: Warning: +[variadic] tests/known/printf_redefined.i:7: Warning: Incorrect type for argument 2. The argument will be cast from long to size_t. [eva] Analyzing a complete application starting at main [eva] Computing initial state diff --git a/src/plugins/variadic/tests/known/printf_redefined.c b/src/plugins/variadic/tests/known/printf_redefined.i similarity index 100% rename from src/plugins/variadic/tests/known/printf_redefined.c rename to src/plugins/variadic/tests/known/printf_redefined.i diff --git a/src/plugins/variadic/translate.ml b/src/plugins/variadic/translate.ml index 0dbf07862c4da167cad784fc1e547b6b06f098f9..6e7e7c7212514305affbbdb957b0f0facbb6de33 100644 --- a/src/plugins/variadic/translate.ml +++ b/src/plugins/variadic/translate.ml @@ -173,7 +173,8 @@ let translate_variadics (file : file) = | Call(lv, callee, args, loc) -> let is_variadic = try - let last = Extends.List.last (Typ.params (Cil.typeOf callee)) in + let args, _ = Typ.ghost_partitioned_params (Cil.typeOf callee) in + let last = Extends.List.last args in last = Generic.vpar with Extends.List.EmptyList -> false in diff --git a/tests/misc/Change_formals.ml b/tests/cil/Change_formals.ml similarity index 100% rename from tests/misc/Change_formals.ml rename to tests/cil/Change_formals.ml diff --git a/tests/cil/change_formals.c b/tests/cil/change_formals.c new file mode 100644 index 0000000000000000000000000000000000000000..5ac6f89b75edfa8287197e7faefe404870c75820 --- /dev/null +++ b/tests/cil/change_formals.c @@ -0,0 +1,17 @@ +/* run.config +EXECNOW: make -s tests/cil/Change_formals.cmxs +OPT: -load-module tests/cil/Change_formals.cmxs -cpp-extra-args="-DNO_PROTO" -then-on test -print +OPT: -load-module tests/cil/Change_formals.cmxs -cpp-extra-args="-DNO_IMPLEM" -then-on test -print +OPT: -load-module tests/cil/Change_formals.cmxs -then-on test -print +*/ + +#ifndef NO_PROTO +int f(int x); +#endif + +#ifndef NO_IMPLEM +int f(int x) { return x; } +#endif + +// needed to prevent erasure of f in NO_IMPLEM case +int g() { return f(0); } diff --git a/tests/cil/insert_formal.i b/tests/cil/insert_formal.i new file mode 100644 index 0000000000000000000000000000000000000000..d6222ef953c9ff024b70b15790c0599661a69875 --- /dev/null +++ b/tests/cil/insert_formal.i @@ -0,0 +1,104 @@ +/* run.config +MODULE: @PTEST_DIR@/@PTEST_NAME@.cmxs +OPT: -print +*/ + +// v +void void_circumflex( void ) { + +} + +// v +void void_circumflex_g( void ) { + +} + +// v +void void_dollar( void ) { + +} + +// v +void void_dollar_g( void ) { + +} + +// v +void a_circumflex( int a ) { + +} + +// v +void a_dollar( int a ) { + +} + +// v +void a_circumflex_g( int a ) { + +} + +// v +void a_dollar_g( int a ) { + +} + +// v +void a_a( int a ){ + +} + +// v +void ghost_a_circumflex( void ) /*@ ghost ( int a ) */ { + +} + +// v +void ghost_a_dollar( void ) /*@ ghost ( int a ) */ { + +} + +// v +void ghost_a_circumflex_g( void ) /*@ ghost ( int a ) */ { + +} + +// v +void ghost_a_dollar_g( void ) /*@ ghost ( int a ) */ { + +} + +// v +void ghost_a_a( void ) /*@ ghost ( int a ) */ { + +} + +// v +void a_b_c_a (int a, int b, int c) { + +} + +// v +void b_a_c_a (int b, int a, int c) { + +} + +// v +void all_ghost_a_b_c_a ( void )/*@ ghost (int a, int b, int c) */ { + +} + +// v +void all_ghost_b_a_c_a ( void )/*@ ghost (int b, int a, int c) */ { + +} + +// v +void a_ghost_b_c_a ( int a )/*@ ghost (int b, int c) */ { + +} + +// v +void b_ghost_a_c_a ( int b )/*@ ghost (int a, int c) */ { + +} diff --git a/tests/cil/insert_formal.ml b/tests/cil/insert_formal.ml new file mode 100644 index 0000000000000000000000000000000000000000..0a0a7e013955303b51259055161c3e30a9526836 --- /dev/null +++ b/tests/cil/insert_formal.ml @@ -0,0 +1,53 @@ +open Cil_types + +let update_func f = + let insert_circ f = Cil.makeFormalVar f ~where:"^" "x" Cil.intType in + let insert_dollar f = Cil.makeFormalVar f ~where:"$" "x" Cil.intType in + let insert_circ_g f = Cil.makeFormalVar f ~ghost:true ~where:"^" "x" Cil.intType in + let insert_dollar_g f = Cil.makeFormalVar f ~ghost:true ~where:"$" "x" Cil.intType in + let insert_a f = Cil.makeFormalVar f ~where:"a" "x" Cil.intType in + let insert_a_g f = Cil.makeFormalVar f ~ghost:true ~where:"a" "x" Cil.intType in + let circ_list = [ + "void_circumflex" ; + "a_circumflex" ; + "ghost_a_circumflex" + ] in + let dollar_list = [ + "void_dollar" ; + "a_dollar" ; + "ghost_a_dollar" + ] in + let circ_g_list = [ + "void_circumflex_g" ; + "a_circumflex_g" ; + "ghost_a_circumflex_g" + ] in + let dollar_g_list = [ + "void_dollar_g" ; + "a_dollar_g" ; + "ghost_a_dollar_g" + ] in + let a_list = [ + "a_a" ; + "a_b_c_a" ; + "b_a_c_a" ; + "a_ghost_b_c_a" ; + ] in + let a_g_list = [ + "ghost_a_a" ; + "all_ghost_a_b_c_a" ; + "all_ghost_b_a_c_a" ; + "b_ghost_a_c_a" + ] in + if List.mem f.svar.vname circ_list then ignore(insert_circ f) ; + if List.mem f.svar.vname dollar_list then ignore(insert_dollar f) ; + if List.mem f.svar.vname circ_g_list then ignore(insert_circ_g f) ; + if List.mem f.svar.vname dollar_g_list then ignore(insert_dollar_g f) ; + if List.mem f.svar.vname a_list then ignore(insert_a f) ; + if List.mem f.svar.vname a_g_list then ignore(insert_a_g f) ; + () + +let run () = + Globals.Functions.iter_on_fundecs update_func + +let () = Db.Main.extend run diff --git a/tests/misc/oracle/change_formals.0.res.oracle b/tests/cil/oracle/change_formals.0.res.oracle similarity index 75% rename from tests/misc/oracle/change_formals.0.res.oracle rename to tests/cil/oracle/change_formals.0.res.oracle index 22dc10f37e8a0e84a256544ee404ff1e529bcd10..794634cc91e1d6d84d9f983b9b9a68b9e869e1d5 100644 --- a/tests/misc/oracle/change_formals.0.res.oracle +++ b/tests/cil/oracle/change_formals.0.res.oracle @@ -1,4 +1,4 @@ -[kernel] Parsing tests/misc/change_formals.c (with preprocessing) +[kernel] Parsing tests/cil/change_formals.c (with preprocessing) [test] current prj = project "test" [test] current prj = project "test" /* Generated by Frama-C */ diff --git a/tests/misc/oracle/change_formals.1.res.oracle b/tests/cil/oracle/change_formals.1.res.oracle similarity index 69% rename from tests/misc/oracle/change_formals.1.res.oracle rename to tests/cil/oracle/change_formals.1.res.oracle index 1f5fcdcd5e9190f8f8d30d8539dc1445a9034ed0..0269f038c67b179ed56aa983d0535dd43b6a6fc4 100644 --- a/tests/misc/oracle/change_formals.1.res.oracle +++ b/tests/cil/oracle/change_formals.1.res.oracle @@ -1,4 +1,4 @@ -[kernel] Parsing tests/misc/change_formals.c (with preprocessing) +[kernel] Parsing tests/cil/change_formals.c (with preprocessing) [test] current prj = project "test" /* Generated by Frama-C */ int f(int x, int ok); diff --git a/tests/misc/oracle/change_formals.2.res.oracle b/tests/cil/oracle/change_formals.2.res.oracle similarity index 77% rename from tests/misc/oracle/change_formals.2.res.oracle rename to tests/cil/oracle/change_formals.2.res.oracle index 3f746d6b7f699a77b6f8d4fff112a9d72aa9ea18..9e91be519b33bd2915fe44dc2286eb5c28d291bc 100644 --- a/tests/misc/oracle/change_formals.2.res.oracle +++ b/tests/cil/oracle/change_formals.2.res.oracle @@ -1,4 +1,4 @@ -[kernel] Parsing tests/misc/change_formals.c (with preprocessing) +[kernel] Parsing tests/cil/change_formals.c (with preprocessing) [test] current prj = project "test" [test] current prj = project "test" /* Generated by Frama-C */ diff --git a/tests/cil/oracle/insert_formal.res.oracle b/tests/cil/oracle/insert_formal.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..faefb89b04774d031958731f2df0f3da1dc8176c --- /dev/null +++ b/tests/cil/oracle/insert_formal.res.oracle @@ -0,0 +1,103 @@ +[kernel] Parsing tests/cil/insert_formal.i (no preprocessing) +/* Generated by Frama-C */ +void void_circumflex(int x) +{ + return; +} + +void void_circumflex_g(void) /*@ ghost (int x) */ +{ + return; +} + +void void_dollar(int x) +{ + return; +} + +void void_dollar_g(void) /*@ ghost (int x) */ +{ + return; +} + +void a_circumflex(int x, int a) +{ + return; +} + +void a_dollar(int a, int x) +{ + return; +} + +void a_circumflex_g(int a) /*@ ghost (int x) */ +{ + return; +} + +void a_dollar_g(int a) /*@ ghost (int x) */ +{ + return; +} + +void a_a(int a, int x) +{ + return; +} + +void ghost_a_circumflex(int x) /*@ ghost (int a) */ +{ + return; +} + +void ghost_a_dollar(int x) /*@ ghost (int a) */ +{ + return; +} + +void ghost_a_circumflex_g(void) /*@ ghost (int x, int a) */ +{ + return; +} + +void ghost_a_dollar_g(void) /*@ ghost (int a, int x) */ +{ + return; +} + +void ghost_a_a(void) /*@ ghost (int a, int x) */ +{ + return; +} + +void a_b_c_a(int a, int x, int b, int c) +{ + return; +} + +void b_a_c_a(int b, int a, int x, int c) +{ + return; +} + +void all_ghost_a_b_c_a(void) /*@ ghost (int a, int x, int b, int c) */ +{ + return; +} + +void all_ghost_b_a_c_a(void) /*@ ghost (int b, int a, int x, int c) */ +{ + return; +} + +void a_ghost_b_c_a(int a, int x) /*@ ghost (int b, int c) */ +{ + return; +} + +void b_ghost_a_c_a(int b) /*@ ghost (int a, int x, int c) */ +{ + return; +} + + diff --git a/tests/misc/change_formals.c b/tests/misc/change_formals.c deleted file mode 100644 index c84ec7afadef6caf0fe82ca4d74cb4c1521062a2..0000000000000000000000000000000000000000 --- a/tests/misc/change_formals.c +++ /dev/null @@ -1,17 +0,0 @@ -/* run.config -EXECNOW: make -s tests/misc/Change_formals.cmxs -OPT: -load-module tests/misc/Change_formals.cmxs -cpp-extra-args="-DNO_PROTO" -then-on test -print -OPT: -load-module tests/misc/Change_formals.cmxs -cpp-extra-args="-DNO_IMPLEM" -then-on test -print -OPT: -load-module tests/misc/Change_formals.cmxs -then-on test -print -*/ - -#ifndef NO_PROTO -int f(int x); -#endif - -#ifndef NO_IMPLEM -int f(int x) { return x; } -#endif - -// needed to prevent erasure of f in NO_IMPLEM case -int g() { return f(0); } diff --git a/tests/pretty_printing/ghost_parameters.c b/tests/pretty_printing/ghost_parameters.c new file mode 100644 index 0000000000000000000000000000000000000000..b6faaf2100018a347a525b9d92c1f1204765c9b6 --- /dev/null +++ b/tests/pretty_printing/ghost_parameters.c @@ -0,0 +1,47 @@ +void decl_function_void_no_ghost(void); +void def_function_void_no_ghost(void) {} +void decl_function_void_ghost(void) /*@ ghost (int y) */; +void def_function_void_ghost(void) /*@ ghost (int y) */ {} +void decl_function_x_no_ghost(int x); +void def_function_x_no_ghost(int x) {} +void decl_function_x_ghost(int x) /*@ ghost (int y) */; +void def_function_x_ghost(int x) /*@ ghost (int y) */ {} +void decl_with_fptr(void (*ptr)(int x) /*@ ghost (int y) */); +void def_with_fptr(void (*ptr)(int x) /*@ ghost (int y) */) { + void (*local)(int) /*@ ghost (int) */ = ptr; + + (*local)(4) /*@ ghost(2) */; + //@ ghost (*local) (4, 2) ; +} +void decl_variadic(int x, ...) /*@ ghost(int y) */; +void def_variadic(int x, ...) /*@ ghost(int y) */ {} + +int main(void) { + decl_function_void_no_ghost(); + def_function_void_no_ghost(); + decl_function_void_ghost() /*@ ghost (4) */; + def_function_void_ghost() /*@ ghost (4) */; + decl_function_x_no_ghost(2); + def_function_x_no_ghost(2); + decl_function_x_ghost(2) /*@ ghost (4) */; + def_function_x_ghost(2) /*@ ghost (4) */; + decl_with_fptr(&decl_function_x_ghost); + def_with_fptr(&decl_function_x_ghost); + decl_variadic(2, 1, 2, 3, 4) /*@ ghost(4) */; + def_variadic(2, 1, 2, 3, 4) /*@ ghost(4) */; + + /*@ ghost + decl_function_void_no_ghost(); + def_function_void_no_ghost(); + decl_function_void_ghost(4); + def_function_void_ghost(4); + decl_function_x_no_ghost(2); + def_function_x_no_ghost(2); + decl_function_x_ghost(2,4); + def_function_x_ghost(2,4); + decl_with_fptr(&decl_function_x_ghost); + def_with_fptr(&decl_function_x_ghost); + decl_variadic(2, 1, 2, 3, 4, 4); + def_variadic(2, 1, 2, 3, 4, 4); + */ +} \ No newline at end of file diff --git a/tests/pretty_printing/oracle/ghost_parameters.res.oracle b/tests/pretty_printing/oracle/ghost_parameters.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..79cdc64d68cd8d06e45db07a2084eac9205b38b4 --- /dev/null +++ b/tests/pretty_printing/oracle/ghost_parameters.res.oracle @@ -0,0 +1,173 @@ +[kernel] Parsing tests/pretty_printing/ghost_parameters.c (with preprocessing) +/* Generated by Frama-C */ +void decl_function_void_no_ghost(void); + +void def_function_void_no_ghost(void) +{ + return; +} + +void decl_function_void_ghost(void) /*@ ghost (int y) */; + +void def_function_void_ghost(void) /*@ ghost (int y) */ +{ + return; +} + +void decl_function_x_no_ghost(int x); + +void def_function_x_no_ghost(int x) +{ + return; +} + +void decl_function_x_ghost(int x) /*@ ghost (int y) */; + +void def_function_x_ghost(int x) /*@ ghost (int y) */ +{ + return; +} + +void decl_with_fptr(void (*ptr)(int x) /*@ ghost (int y) */); + +void def_with_fptr(void (*ptr)(int x) /*@ ghost (int y) */) +{ + void (*local)(int ) /*@ ghost (int ) */ = ptr; + (*local)(4) /*@ ghost (2) */; + /*@ ghost (*local)(4,2); */ + return; +} + +void decl_variadic(int x , ...) /*@ ghost (int y) */; + +void def_variadic(int x , ...) /*@ ghost (int y) */ +{ + return; +} + +int main(void) +{ + int __retres; + decl_function_void_no_ghost(); + def_function_void_no_ghost(); + decl_function_void_ghost() /*@ ghost (4) */; + def_function_void_ghost() /*@ ghost (4) */; + decl_function_x_no_ghost(2); + def_function_x_no_ghost(2); + decl_function_x_ghost(2) /*@ ghost (4) */; + def_function_x_ghost(2) /*@ ghost (4) */; + decl_with_fptr(& decl_function_x_ghost); + def_with_fptr(& decl_function_x_ghost); + decl_variadic(2,1,2,3,4) /*@ ghost (4) */; + def_variadic(2,1,2,3,4) /*@ ghost (4) */; + /*@ ghost decl_function_void_no_ghost(); */ + /*@ ghost def_function_void_no_ghost(); */ + /*@ ghost decl_function_void_ghost(4); */ + /*@ ghost def_function_void_ghost(4); */ + /*@ ghost decl_function_x_no_ghost(2); */ + /*@ ghost def_function_x_no_ghost(2); */ + /*@ ghost decl_function_x_ghost(2,4); */ + /*@ ghost def_function_x_ghost(2,4); */ + /*@ ghost decl_with_fptr(& decl_function_x_ghost); */ + /*@ ghost def_with_fptr(& decl_function_x_ghost); */ + /*@ ghost decl_variadic(2,1,2,3,4,4); */ + /*@ ghost def_variadic(2,1,2,3,4,4); */ + __retres = 0; + return __retres; +} + + +[kernel] Parsing tests/pretty_printing/result/ghost_parameters.c (with preprocessing) +[kernel] Parsing tests/pretty_printing/ghost_parameters.c (with preprocessing) +[kernel] tests/pretty_printing/ghost_parameters.c:2: Warning: + dropping duplicate def'n of func def_function_void_no_ghost at tests/pretty_printing/ghost_parameters.c:2 in favor of that at tests/pretty_printing/result/ghost_parameters.c:4 +[kernel] tests/pretty_printing/ghost_parameters.c:4: Warning: + dropping duplicate def'n of func def_function_void_ghost at tests/pretty_printing/ghost_parameters.c:4 in favor of that at tests/pretty_printing/result/ghost_parameters.c:11 +[kernel] tests/pretty_printing/ghost_parameters.c:6: Warning: + dropping duplicate def'n of func def_function_x_no_ghost at tests/pretty_printing/ghost_parameters.c:6 in favor of that at tests/pretty_printing/result/ghost_parameters.c:18 +[kernel] tests/pretty_printing/ghost_parameters.c:8: Warning: + dropping duplicate def'n of func def_function_x_ghost at tests/pretty_printing/ghost_parameters.c:8 in favor of that at tests/pretty_printing/result/ghost_parameters.c:25 +[kernel] tests/pretty_printing/ghost_parameters.c:10: Warning: + dropping duplicate def'n of func def_with_fptr at tests/pretty_printing/ghost_parameters.c:10 in favor of that at tests/pretty_printing/result/ghost_parameters.c:32 +[kernel] tests/pretty_printing/ghost_parameters.c:17: Warning: + dropping duplicate def'n of func def_variadic at tests/pretty_printing/ghost_parameters.c:17 in favor of that at tests/pretty_printing/result/ghost_parameters.c:42 +[kernel] tests/pretty_printing/ghost_parameters.c:19: Warning: + def'n of func main at tests/pretty_printing/ghost_parameters.c:19 (sum 21482) conflicts with the one at tests/pretty_printing/result/ghost_parameters.c:47 (sum 23256); keeping the one at tests/pretty_printing/result/ghost_parameters.c:47. +/* Generated by Frama-C */ +void decl_function_void_no_ghost(void); + +void def_function_void_no_ghost(void) +{ + return; +} + +void decl_function_void_ghost(void) /*@ ghost (int y) */; + +void def_function_void_ghost(void) /*@ ghost (int y) */ +{ + return; +} + +void decl_function_x_no_ghost(int x); + +void def_function_x_no_ghost(int x) +{ + return; +} + +void decl_function_x_ghost(int x) /*@ ghost (int y) */; + +void def_function_x_ghost(int x) /*@ ghost (int y) */ +{ + return; +} + +void decl_with_fptr(void (*ptr)(int x) /*@ ghost (int y) */); + +void def_with_fptr(void (*ptr)(int x) /*@ ghost (int y) */) +{ + void (*local)(int ) /*@ ghost (int ) */ = ptr; + (*local)(4) /*@ ghost (2) */; + /*@ ghost (*local)(4,2); */ + return; +} + +void decl_variadic(int x , ...) /*@ ghost (int y) */; + +void def_variadic(int x , ...) /*@ ghost (int y) */ +{ + return; +} + +int main(void) +{ + int __retres; + decl_function_void_no_ghost(); + def_function_void_no_ghost(); + decl_function_void_ghost() /*@ ghost (4) */; + def_function_void_ghost() /*@ ghost (4) */; + decl_function_x_no_ghost(2); + def_function_x_no_ghost(2); + decl_function_x_ghost(2) /*@ ghost (4) */; + def_function_x_ghost(2) /*@ ghost (4) */; + decl_with_fptr(& decl_function_x_ghost); + def_with_fptr(& decl_function_x_ghost); + decl_variadic(2,1,2,3,4) /*@ ghost (4) */; + def_variadic(2,1,2,3,4) /*@ ghost (4) */; + /*@ ghost decl_function_void_no_ghost(); */ + /*@ ghost def_function_void_no_ghost(); */ + /*@ ghost decl_function_void_ghost(4); */ + /*@ ghost def_function_void_ghost(4); */ + /*@ ghost decl_function_x_no_ghost(2); */ + /*@ ghost def_function_x_no_ghost(2); */ + /*@ ghost decl_function_x_ghost(2,4); */ + /*@ ghost def_function_x_ghost(2,4); */ + /*@ ghost decl_with_fptr(& decl_function_x_ghost); */ + /*@ ghost def_with_fptr(& decl_function_x_ghost); */ + /*@ ghost decl_variadic(2,1,2,3,4,4); */ + /*@ ghost def_variadic(2,1,2,3,4,4); */ + __retres = 0; + return __retres; +} + + diff --git a/tests/spec/assigns_from_kf.i b/tests/spec/assigns_from_kf.i new file mode 100644 index 0000000000000000000000000000000000000000..cf8f4228ed4bbb3f61a637e1508e6d97315ecbd9 --- /dev/null +++ b/tests/spec/assigns_from_kf.i @@ -0,0 +1,27 @@ +/* run.config + MODULE: @PTEST_DIR@/@PTEST_NAME@.cmxs + OPT: -print +*/ + +void nothing(void); +int nothing_r(void); + +void something_non_ghost(int *p); +void something_ghost(void) /*@ ghost (int* p) */; + +int something_non_ghost_r(int *p); +int something_ghost_r(void) /*@ ghost (int* p) */; + +void both(int* p, int x) /*@ ghost (int* gp, int gx) */; +int both_r(int* p, int x) /*@ ghost (int* gp, int gx) */; + +void reference(void) { + nothing(); + nothing_r(); + something_non_ghost(0); + something_ghost() /*@ ghost (0) */; + something_non_ghost_r(0); + something_ghost_r() /*@ ghost (0) */; + both(0, 1) /*@ ghost (0, 2) */; + both_r(0, 1) /*@ ghost (0, 2) */; +} \ No newline at end of file diff --git a/tests/spec/assigns_from_kf.ml b/tests/spec/assigns_from_kf.ml new file mode 100644 index 0000000000000000000000000000000000000000..fcab8e135d1e04408c95c695eba44eac20e22173 --- /dev/null +++ b/tests/spec/assigns_from_kf.ml @@ -0,0 +1,4 @@ +let run () = + Globals.Functions.iter (fun kf -> ignore (Annotations.funspec kf)) + +let () = Db.Main.extend run \ No newline at end of file diff --git a/tests/spec/oracle/assigns_from_kf.res.oracle b/tests/spec/oracle/assigns_from_kf.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ac10b7070c2d88b55fd1b456f5a3a9ac30099cdf --- /dev/null +++ b/tests/spec/oracle/assigns_from_kf.res.oracle @@ -0,0 +1,71 @@ +[kernel] Parsing tests/spec/assigns_from_kf.i (no preprocessing) +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function both, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function both_r, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function nothing, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function nothing_r, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function something_ghost, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function something_ghost_r, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function something_non_ghost, generating default assigns from the prototype +[kernel:annot:missing-spec] tests/spec/assigns_from_kf.i:18: Warning: + Neither code nor specification for function something_non_ghost_r, generating default assigns from the prototype +/* Generated by Frama-C */ +/*@ assigns \nothing; */ +void nothing(void); + +/*@ assigns \result; + assigns \result \from \nothing; */ +int nothing_r(void); + +/*@ assigns *p; + assigns *p \from *p; */ +void something_non_ghost(int *p); + +/*@ assigns *p; + assigns *p \from *p; */ +void something_ghost(void) /*@ ghost (int *p) */; + +/*@ assigns \result, *p; + assigns \result \from *p; + assigns *p \from *p; */ +int something_non_ghost_r(int *p); + +/*@ assigns \result, *p; + assigns \result \from \nothing; + assigns *p \from *p; + */ +int something_ghost_r(void) /*@ ghost (int *p) */; + +/*@ assigns *p, *gp; + assigns *p \from *p, x; + assigns *gp \from *p, *gp, x, gx; + */ +void both(int *p, int x) /*@ ghost (int *gp, int gx) */; + +/*@ assigns \result, *p, *gp; + assigns \result \from *p, x; + assigns *p \from *p, x; + assigns *gp \from *p, *gp, x, gx; + */ +int both_r(int *p, int x) /*@ ghost (int *gp, int gx) */; + +void reference(void) +{ + nothing(); + nothing_r(); + something_non_ghost((int *)0); + something_ghost() /*@ ghost ((int *)0) */; + something_non_ghost_r((int *)0); + something_ghost_r() /*@ ghost ((int *)0) */; + both((int *)0,1) /*@ ghost ((int *)0,2) */; + both_r((int *)0,1) /*@ ghost ((int *)0,2) */; + return; +} + + diff --git a/tests/syntax/ghost_func_ptr.i b/tests/syntax/ghost_func_ptr.i new file mode 100644 index 0000000000000000000000000000000000000000..ba5ce7a1911a6eca9b0045ed36ef926977428985 --- /dev/null +++ b/tests/syntax/ghost_func_ptr.i @@ -0,0 +1,5 @@ +//@ ghost void (*g)(int *) = 0 ; + +int main(){ + //@ ghost void (*l)(int *) = 0 ; +} diff --git a/tests/syntax/ghost_parameters.c b/tests/syntax/ghost_parameters.c new file mode 100644 index 0000000000000000000000000000000000000000..5aae254922897843c44c6eca66dda28045391c43 --- /dev/null +++ b/tests/syntax/ghost_parameters.c @@ -0,0 +1,208 @@ +/* run.config + STDOPT: +" -cpp-extra-args=-DARGS_NOT_VOID" + STDOPT: +" -cpp-extra-args=-DARGS_VOID" + STDOPT: +" -cpp-extra-args=-DCOHERENT_DECL" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_LOCAL_DECL_NON_GHOST" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_GLOBAL_DECL_NON_GHOST" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_LOCAL_DECL_GHOST" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_GLOBAL_DECL_GHOST" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_LOCAL_DECL_MORE_GHOSTS" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_GLOBAL_DECL_MORE_GHOSTS" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_LOCAL_DECL_MORE_NON_GHOSTS" + STDOPT: +" -cpp-extra-args=-DINCOHERENT_GLOBAL_DECL_MORE_NON_GHOSTS" + STDOPT: +" -cpp-extra-args=-DVOID_EMPTY_GHOST_PARAMETER_LIST" + STDOPT: +" -cpp-extra-args=-DVOID_GHOST_PARAMETER" +*/ + +#ifdef ARGS_NOT_VOID + +void function(int a, int b) /*@ ghost (int c, int d) */{ + +} + +void caller(void){ + // VALID + function(1, 2) /*@ ghost (3, 4)*/ ; + /*@ ghost function(1, 2, 3, 4) ; */ + + // INVALID + function(1, 2) ; + function(1, 2) /*@ ghost (3) */ ; + function(1) /*@ ghost (2, 3) */ ; + function(1, 2, 3, 4) ; + function() /*@ ghost (1, 2, 3, 4) */ ; + + /*@ ghost function(1, 2) ; */ + /*@ ghost function(1) ; */ + /*@ ghost function(1, 2, 3) ; */ +} + +#endif + +#ifdef ARGS_VOID + +void function(void) /*@ ghost (int c, int d) */{ + +} + +void caller(void){ + // VALID + function() /*@ ghost (3, 4)*/ ; + /*@ ghost function(3, 4) ; */ + + // INVALID + function() ; + function() /*@ ghost (3) */ ; + function(1) /*@ ghost (2, 3) */ ; + function(1, 2) ; + function() /*@ ghost (1, 2, 3) */ ; + + /*@ ghost function() ; */ + /*@ ghost function(1) ; */ + /*@ ghost function(1, 2, 3) ; */ +} + +#endif + +#ifdef COHERENT_DECL + +void caller(void){ + void function(int a, int b) /*@ ghost(int c, int d) */ ; + function(1, 2) /*@ ghost (3, 4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ ; + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_LOCAL_DECL_NON_GHOST + +void caller(void){ + void function(int b) /*@ ghost(int c, int d) */ ; + function(2) /*@ ghost (3, 4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_GLOBAL_DECL_NON_GHOST + +void function(int b) /*@ ghost(int c, int d) */ ; + +void caller(void){ + function(2) /*@ ghost (3, 4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_LOCAL_DECL_GHOST + +void caller(void){ + void function(int a, int b) /*@ ghost(int d) */ ; + function(1, 2) /*@ ghost (4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_GLOBAL_DECL_GHOST + +void function(int a, int b) /*@ ghost(int d) */ ; + +void caller(void){ + function(1, 2) /*@ ghost (3) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_LOCAL_DECL_MORE_GHOSTS + +void caller(void){ + void function(int a, int b, int c) /*@ ghost(int d) */ ; + function(1, 2, 3) /*@ ghost (4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_GLOBAL_DECL_MORE_GHOSTS + +void function(int a, int b, int c) /*@ ghost(int d) */ ; + +void caller(void){ + function(1, 2, 3) /*@ ghost (4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_LOCAL_DECL_MORE_NON_GHOSTS + +void caller(void){ + void function(int a) /*@ ghost(int b, int c, int d) */ ; + function(1) /*@ ghost (2, 3, 4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef INCOHERENT_GLOBAL_DECL_MORE_NON_GHOSTS + +void function(int a) /*@ ghost(int b, int c, int d) */ ; + +void caller(void){ + function(1) /*@ ghost (2, 3, 4) */ ; +} + +void function(int a, int b) /*@ ghost(int c, int d) */ { + +} + +#endif + +#ifdef VOID_EMPTY_GHOST_PARAMETER_LIST + +void function_void(void) /*@ ghost () */ { + +} + +#endif + +#ifdef VOID_GHOST_PARAMETER + +void function_void(void) /*@ ghost (void) */ { + +} + +void function_non_void(int x) /*@ ghost (void) */ { + +} + +#endif \ No newline at end of file diff --git a/tests/syntax/ghost_parameters_formals_status.i b/tests/syntax/ghost_parameters_formals_status.i new file mode 100644 index 0000000000000000000000000000000000000000..4698b9f77e2e313d832db47fc4a41b83371508e5 --- /dev/null +++ b/tests/syntax/ghost_parameters_formals_status.i @@ -0,0 +1,22 @@ +/* run.config + EXECNOW: make -s @PTEST_DIR@/@PTEST_NAME@.cmxs + OPT: -load-module @PTEST_DIR@/@PTEST_NAME@.cmxs +*/ + +void declaration_void(void) /*@ ghost (int x, int y) */ ; +void declaration_not_void(int a, int b) /*@ ghost (int x, int y) */ ; + +void definition_void(void) /*@ ghost(int x, int y) */ { + +} + +void definition_not_void(int a, int b) /*@ ghost(int x, int y) */ { + +} + +void caller(){ + declaration_void() /*@ ghost (1, 2) */ ; + declaration_not_void(1, 2) /*@ ghost (3, 4) */ ; + definition_void() /*@ ghost (1, 2) */ ; + definition_not_void(1, 2) /*@ ghost (3, 4) */ ; +} diff --git a/tests/syntax/ghost_parameters_formals_status.ml b/tests/syntax/ghost_parameters_formals_status.ml new file mode 100644 index 0000000000000000000000000000000000000000..9181658f40760e61e3572a727260aca3c141cc17 --- /dev/null +++ b/tests/syntax/ghost_parameters_formals_status.ml @@ -0,0 +1,28 @@ +open Cil_types + +let run () = + let print_info kf = + let pretty_formal fmt vi = + assert(vi.vformal) ; + Format.fprintf fmt "@\n- %a which is %s" + Cil_datatype.Varinfo.pretty vi + (if vi.vghost then "ghost" else "non-ghost") + in + let pretty_formal_list fmt l = + match l with + | [] -> + Format.fprintf fmt "No Formals" + | _ -> + Format.fprintf fmt "Formals are %a" + (Pretty_utils.pp_flowlist ~left:"" ~sep:"" ~right:"" pretty_formal) l + in + let vi = Kernel_function.get_vi kf in + let formals = Cil.getFormalsDecl vi in + Kernel.feedback "Type of %s is %a.@ %a" + vi.vname + Cil_datatype.Typ.pretty vi.vtype + pretty_formal_list formals + in + Globals.Functions.iter print_info + +let () = Db.Main.extend run diff --git a/tests/syntax/ghost_parameters_side_effect_arg.i b/tests/syntax/ghost_parameters_side_effect_arg.i new file mode 100644 index 0000000000000000000000000000000000000000..00d02e6665a1ff8aa1a5cc14d79c76fbcd1fb191 --- /dev/null +++ b/tests/syntax/ghost_parameters_side_effect_arg.i @@ -0,0 +1,21 @@ +void function(int x) /*@ ghost(int y) */ ; +int other(int x) /*@ ghost(int y) */ ; + +void caller(){ + int x = 0 ; + //@ ghost int g = 0 ; + int t[] = { 0, 0, 0 } ; + + function(x++) /*@ ghost(g++) */ ; + function(x = 2) /*@ ghost(g = 42) */ ; + function(x += 2) /*@ ghost(g += 42) */ ; + function(-x) /*@ ghost(-g) */ ; + function( (x == 0) ? x : 42 ) /*@ ghost( (g == 0) ? g : 42 ) */ ; + function(t[x++]) /*@ ghost(t[g++]) */ ; + function( other(x) /*@ ghost(g) */ ) /*@ ghost( other(x, g) ) */ ; + + /*@ ghost + int i = 1 ; + function(g++, i++) ; + */ +} diff --git a/tests/syntax/oracle/attributes-declarations-definitions.res.oracle b/tests/syntax/oracle/attributes-declarations-definitions.res.oracle index 196ad631a7a9bbc1a7f23829cdf4cc367526f137..5d89e874ee4557ea9e97fcec159d21f36e972995 100644 --- a/tests/syntax/oracle/attributes-declarations-definitions.res.oracle +++ b/tests/syntax/oracle/attributes-declarations-definitions.res.oracle @@ -6,18 +6,18 @@ /* Generated by Frama-C */ typedef int __attribute__((__a1__)) aint; typedef int __attribute__((__p1__)) * __attribute__((__p2__)) iptr; -int __attribute__((__tret5__, __tret4__, __tret3__, __tret2__, __tret1__)) f( -int const __attribute__((__arg3__)) p3) __attribute__((__f5__, __f4__, - __f2__, __f1__)); +int __attribute__((__tret5__, __tret4__, __tret3__, __tret2__, __tret1__)) f +(int const __attribute__((__arg3__)) p3) __attribute__((__f5__, __f4__, + __f2__, __f1__)); /*@ requires p3 ≥ 3; requires p3 ≥ 1; requires p3 ≥ 4; */ -int __attribute__((__tret5__, __tret4__, __tret3__, __tret2__, __tret1__)) f( -int const __attribute__((__arg3__)) p3) __attribute__((__f5__, __f4__, - __f2__, __f1__)); -int __attribute__((__tret5__, __tret4__, __tret3__, __tret2__, __tret1__)) f( -int const __attribute__((__arg3__)) p3) +int __attribute__((__tret5__, __tret4__, __tret3__, __tret2__, __tret1__)) f +(int const __attribute__((__arg3__)) p3) __attribute__((__f5__, __f4__, + __f2__, __f1__)); +int __attribute__((__tret5__, __tret4__, __tret3__, __tret2__, __tret1__)) f +(int const __attribute__((__arg3__)) p3) { int __attribute__((__tret5__, __tret4__, __tret3__, __tret2__, __tret1__)) __retres; __retres = (int __attribute__((__tret3__, __tret2__, __tret1__)))p3; diff --git a/tests/syntax/oracle/ghost_func_ptr.res.oracle b/tests/syntax/oracle/ghost_func_ptr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9c2890ad3dc66b42245237d94ea410ff875b9ca5 --- /dev/null +++ b/tests/syntax/oracle/ghost_func_ptr.res.oracle @@ -0,0 +1,12 @@ +[kernel] Parsing tests/syntax/ghost_func_ptr.i (no preprocessing) +/* Generated by Frama-C */ +/*@ ghost void (*g)(int *) = (void (*)(int *))0; */ +int main(void) +{ + int __retres; + /*@ ghost void (*l)(int *) = (void (*)(int *))0; */ + __retres = 0; + return __retres; +} + + diff --git a/tests/syntax/oracle/ghost_parameters.0.res.oracle b/tests/syntax/oracle/ghost_parameters.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..926c68c1c6b88ab5190ce6d4e0fc0db055e8652e --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.0.res.oracle @@ -0,0 +1,24 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:29: User Error: + Too few ghost arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:30: User Error: + Too few ghost arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:31: User Error: + Too few arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:32: User Error: + Too few ghost arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:32: User Error: + Too many arguments in call to function +[kernel] tests/syntax/ghost_parameters.c:33: User Error: + Too many ghost arguments in call to function +[kernel] tests/syntax/ghost_parameters.c:33: User Error: + Too few arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:35: User Error: + Too few arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:36: User Error: + Too few arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:37: User Error: + Too few arguments in call to function. +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.1.res.oracle b/tests/syntax/oracle/ghost_parameters.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..614c8ad74c075c9e1eb74b8277c9cb1dd90ff432 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.1.res.oracle @@ -0,0 +1,22 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:54: User Error: + Too few ghost arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:55: User Error: + Too few ghost arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:56: User Error: + Too many arguments in call to function +[kernel] tests/syntax/ghost_parameters.c:57: User Error: + Too few ghost arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:57: User Error: + Too many arguments in call to function +[kernel] tests/syntax/ghost_parameters.c:58: User Error: + Too many ghost arguments in call to function +[kernel] tests/syntax/ghost_parameters.c:60: User Error: + Too few arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:61: User Error: + Too few arguments in call to function. +[kernel] tests/syntax/ghost_parameters.c:62: User Error: + Too many arguments in call to function +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.10.res.oracle b/tests/syntax/oracle/ghost_parameters.10.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..477b266404d4270969128b8295e5957a8ffb1083 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.10.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:184: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:178 (different number of arguments). +[kernel] tests/syntax/ghost_parameters.c:184: User Error: + Inconsistent formals + 182 } + 183 + 184 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 185 + 186 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.11.res.oracle b/tests/syntax/oracle/ghost_parameters.11.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1d8c5da2c6f63a8b566ed678f910648131c852eb --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.11.res.oracle @@ -0,0 +1,11 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:192: + syntax error: + Location: line 192, between columns 35 and 36, before or at token: ) + 190 #ifdef VOID_EMPTY_GHOST_PARAMETER_LIST + 191 + 192 void function_void(void) /*@ ghost () */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 193 + 194 } +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.12.res.oracle b/tests/syntax/oracle/ghost_parameters.12.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8bc53156a937624d69449742be9e9d452f89dedf --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.12.res.oracle @@ -0,0 +1,8 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:200: User Error: + ghost parameters list cannot be void +[kernel] tests/syntax/ghost_parameters.c:204: User Error: + ghost parameters list cannot be void +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.2.res.oracle b/tests/syntax/oracle/ghost_parameters.2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..21f52b26feabd38a86fe804f9c8f5ef2033af362 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.2.res.oracle @@ -0,0 +1,16 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +/* Generated by Frama-C */ +void function(int a, int b) /*@ ghost (int c, int d) */; + +void caller(void) +{ + function(1,2) /*@ ghost (3,4) */; + return; +} + +void function(int a, int b) /*@ ghost (int c, int d) */ +{ + return; +} + + diff --git a/tests/syntax/oracle/ghost_parameters.3.res.oracle b/tests/syntax/oracle/ghost_parameters.3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c621d5748d1d6aa8f095a4cb262df1322c86d17d --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.3.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:89: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:85 (different number of arguments). +[kernel] tests/syntax/ghost_parameters.c:89: User Error: + Inconsistent formals + 87 } + 88 + 89 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 90 + 91 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.4.res.oracle b/tests/syntax/oracle/ghost_parameters.4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d6b376ee2b1e3a910608069d60980a8f0f23dde8 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.4.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:103: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:97 (different number of arguments). +[kernel] tests/syntax/ghost_parameters.c:103: User Error: + Inconsistent formals + 101 } + 102 + 103 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 104 + 105 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.5.res.oracle b/tests/syntax/oracle/ghost_parameters.5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..138709d0a9bdc0236cd4021f28304fb0a23c312a --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.5.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:116: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:112 (different number of ghost arguments). +[kernel] tests/syntax/ghost_parameters.c:116: User Error: + Inconsistent formals + 114 } + 115 + 116 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 117 + 118 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.6.res.oracle b/tests/syntax/oracle/ghost_parameters.6.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..5807a9726441f905b6ffed9dd250f8ce4ec425d4 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.6.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:130: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:124 (different number of ghost arguments). +[kernel] tests/syntax/ghost_parameters.c:130: User Error: + Inconsistent formals + 128 } + 129 + 130 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 131 + 132 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.7.res.oracle b/tests/syntax/oracle/ghost_parameters.7.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e5de27561f6b32bb38613b5762dbd2632e2999b4 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.7.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:143: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:139 (different number of arguments). +[kernel] tests/syntax/ghost_parameters.c:143: User Error: + Inconsistent formals + 141 } + 142 + 143 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 144 + 145 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.8.res.oracle b/tests/syntax/oracle/ghost_parameters.8.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bb6ac89e90999848f2a97340e24f02d246491450 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.8.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:157: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:151 (different number of arguments). +[kernel] tests/syntax/ghost_parameters.c:157: User Error: + Inconsistent formals + 155 } + 156 + 157 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 158 + 159 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters.9.res.oracle b/tests/syntax/oracle/ghost_parameters.9.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..53080c4e6f3f5a60ba9ad30cd6a8621da29d5a5d --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters.9.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/syntax/ghost_parameters.c (with preprocessing) +[kernel] tests/syntax/ghost_parameters.c:170: User Error: + Declaration of function does not match previous declaration from tests/syntax/ghost_parameters.c:166 (different number of arguments). +[kernel] tests/syntax/ghost_parameters.c:170: User Error: + Inconsistent formals + 168 } + 169 + 170 void function(int a, int b) /*@ ghost(int c, int d) */ { + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 171 + 172 } +[kernel] User Error: stopping on file "tests/syntax/ghost_parameters.c" that has errors. Add + '-kernel-msg-key pp' for preprocessing command. +[kernel] Frama-C aborted: invalid user input. diff --git a/tests/syntax/oracle/ghost_parameters_formals_status.res.oracle b/tests/syntax/oracle/ghost_parameters_formals_status.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f57bed37aaafe5139024b35445d67e4b7a5e1e5a --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters_formals_status.res.oracle @@ -0,0 +1,25 @@ +[kernel] Parsing tests/syntax/ghost_parameters_formals_status.i (no preprocessing) +[kernel] Type of caller is void (void). + No Formals +[kernel] Type of declaration_not_void is void (int a, int b) + /*@ ghost (int x, int y) */. + Formals are + - a which is non-ghost + - b which is non-ghost + - x which is ghost + - y which is ghost +[kernel] Type of declaration_void is void (void) /*@ ghost (int x, int y) */. + Formals are + - x which is ghost + - y which is ghost +[kernel] Type of definition_not_void is void (int a, int b) + /*@ ghost (int x, int y) */. + Formals are + - a which is non-ghost + - b which is non-ghost + - x which is ghost + - y which is ghost +[kernel] Type of definition_void is void (void) /*@ ghost (int x, int y) */. + Formals are + - x which is ghost + - y which is ghost diff --git a/tests/syntax/oracle/ghost_parameters_side_effect_arg.res.oracle b/tests/syntax/oracle/ghost_parameters_side_effect_arg.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a74ded6cea571f0de9931b075e58544bef5cdef5 --- /dev/null +++ b/tests/syntax/oracle/ghost_parameters_side_effect_arg.res.oracle @@ -0,0 +1,60 @@ +[kernel] Parsing tests/syntax/ghost_parameters_side_effect_arg.i (no preprocessing) +/* Generated by Frama-C */ +void function(int x) /*@ ghost (int y) */; + +int other(int x) /*@ ghost (int y) */; + +void caller(void) +{ + /*@ ghost int g_tmp; */ + int tmp; + /*@ ghost int g_tmp_0; */ + int tmp_0; + /*@ ghost int g_tmp_1; */ + int tmp_1; + /*@ ghost int g_tmp_2; */ + int tmp_2; + /*@ ghost int g_tmp_3; */ + /*@ ghost int g_tmp_4; */ + int x = 0; + /*@ ghost int g = 0; */ + int t[3] = {0, 0, 0}; + /*@ ghost g_tmp = g; */ + /*@ ghost g ++; */ + /*@ ghost ; */ + tmp = x; + x ++; + ; + function(tmp) /*@ ghost (g_tmp) */; + /*@ ghost g = 42; */ + x = 2; + function(x) /*@ ghost (g) */; + /*@ ghost g += 42; */ + x += 2; + function(x) /*@ ghost (g) */; + function(- x) /*@ ghost (- g) */; + /*@ ghost if (g == 0) g_tmp_0 = g; else g_tmp_0 = 42; */ + if (x == 0) tmp_0 = x; else tmp_0 = 42; + function(tmp_0) /*@ ghost (g_tmp_0) */; + /*@ ghost g_tmp_1 = g; */ + /*@ ghost g ++; */ + /*@ ghost ; */ + tmp_1 = x; + x ++; + ; + function(t[tmp_1]) /*@ ghost (t[g_tmp_1]) */; + /*@ ghost g_tmp_2 = other(x,g); */ + tmp_2 = other(x) /*@ ghost (g) */; + function(tmp_2) /*@ ghost (g_tmp_2) */; + /*@ ghost int i = 1; */ + /*@ ghost g_tmp_3 = i; + i ++; + ; + g_tmp_4 = g; + g ++; + ; */ + /*@ ghost function(g_tmp_4,g_tmp_3); */ + return; +} + + diff --git a/tests/syntax/oracle/undeclared_local_bts1126.res.oracle b/tests/syntax/oracle/undeclared_local_bts1126.res.oracle index c1237aab0ad82b4be7420cc870484c8c1a324622..4c135cc183f7d23101b0de47587639afbbcd88f0 100644 --- a/tests/syntax/oracle/undeclared_local_bts1126.res.oracle +++ b/tests/syntax/oracle/undeclared_local_bts1126.res.oracle @@ -32,8 +32,8 @@ extern int ( /* missing proto */ _gnutls_epoch_get)(struct gnutls_session_t x_0, extern int ( /* missing proto */ gnutls_assert_val)(int x_0); -extern int ( /* missing proto */ _gnutls_cipher_suite_get_cipher_algo)( -cipher_suite_st *x_0); +extern int ( /* missing proto */ _gnutls_cipher_suite_get_cipher_algo) +(cipher_suite_st *x_0); extern int ( /* missing proto */ _gnutls_cipher_suite_get_mac_algo)(cipher_suite_st *x_0);