diff --git a/src/kernel_internals/typing/populate_spec.ml b/src/kernel_internals/typing/populate_spec.ml index 24d88efe2edc27fe3fb0cbb3fef8f2f178fbd45f..bbbbd7b7fc2f0d5e6df9c55181c2114865da1167 100644 --- a/src/kernel_internals/typing/populate_spec.ml +++ b/src/kernel_internals/typing/populate_spec.ml @@ -549,11 +549,11 @@ let build_config mode = terminates = mode; } -let get_config_default () = +let get_config_mode () = build_config @@ get_mode @@ Kernel.GeneratedSpecMode.get () let get_config () = - let default = get_config_default () in + let default = get_config_mode () in let collect (k,v) conf = let mode = get_mode (Option.get v) in match k with @@ -572,7 +572,6 @@ let get_config () = let do_populate kf original_spec = let config = get_config () in - let exits = Exits.get_default config.exits kf original_spec in let assigns = Assigns.get_default config.assigns kf original_spec in let requires = Requires.get_default config.requires kf original_spec in @@ -613,12 +612,22 @@ module Is_populated = let () = Ast.add_linked_state Is_populated.self -let populate_funspec kf spec = - if not @@ Kernel.GenerateDefaultSpec.get() || Is_populated.mem kf then false +let populate_funspec ~force kf spec = + let is_proto = not @@ Kernel_function.has_definition kf in + let skip_generation = not @@ Kernel.GenerateDefaultSpec.get () in + let is_empty_spec = Cil.is_empty_funspec spec in + let skip_proto = is_proto && not force && is_empty_spec in + if (not force && skip_generation) || Is_populated.mem kf || skip_proto + then false else begin + if is_proto && is_empty_spec then + Kernel.warning ~once:true ~current:true ~wkey:Kernel.wkey_missing_spec + "Neither code nor specification for function %a, \ + generating default specs from the prototype" + Kernel_function.pretty kf; do_populate kf spec; Is_populated.add kf (); true end -let () = Annotations.populate_spec_ref := populate_funspec +let () = Annotations.populate_spec_ref := populate_funspec ~force:true diff --git a/src/kernel_internals/typing/populate_spec.mli b/src/kernel_internals/typing/populate_spec.mli index 940da158cfb4ac7278bf6643c4cab05684390afd..27ae84f04b666934a5b768c68b53b05fda3b1ea2 100644 --- a/src/kernel_internals/typing/populate_spec.mli +++ b/src/kernel_internals/typing/populate_spec.mli @@ -60,4 +60,4 @@ val register : ?status_terminates:status -> string -> unit -val populate_funspec : kernel_function -> spec -> bool +val populate_funspec : force:bool -> kernel_function -> spec -> bool diff --git a/src/kernel_services/ast_queries/file.ml b/src/kernel_services/ast_queries/file.ml index 3b93f038bb97a2d4f44e1f0da1d34c918a509ef7..36bb0e417a434e938b8c589cf42f5ddbe3d2241d 100644 --- a/src/kernel_services/ast_queries/file.ml +++ b/src/kernel_services/ast_queries/file.ml @@ -1189,7 +1189,8 @@ let () = let populate_spec () = let add_spec kf = - ignore @@ Populate_spec.populate_funspec kf (Annotations.funspec kf) + ignore @@ Populate_spec.populate_funspec ~force:false kf + (Annotations.funspec ~populate:false kf) in Globals.Functions.iter add_spec diff --git a/tests/spec/default_spec_combine.ml b/tests/spec/default_spec_combine.ml index dd81d458061a8bb554e1786101617512e4768d12..6261077f996b4fcc155bba54723938dfea1bbf3d 100644 --- a/tests/spec/default_spec_combine.ml +++ b/tests/spec/default_spec_combine.ml @@ -14,6 +14,12 @@ let status_allocates = Property_status.Dont_know let gen_terminates _ _ = None let status_terminates = Property_status.Dont_know +let run () = + let get_spec kf = + ignore(Annotations.funspec kf) + in + Globals.Functions.iter get_spec + let populate () = Format.printf "Registering an mode that does nothing@."; Populate_spec.register @@ -25,4 +31,4 @@ let populate () = "donothing" - let () = Cmdline.run_after_configuring_stage populate +let () = Cmdline.run_after_configuring_stage populate diff --git a/tests/spec/default_spec_custom.ml b/tests/spec/default_spec_custom.ml index 5220b81414525f0cb8b1d67061ff3e0a51c585c6..826cd252d4412701ec30b57f22b403ff2e334582 100644 --- a/tests/spec/default_spec_custom.ml +++ b/tests/spec/default_spec_custom.ml @@ -26,6 +26,12 @@ let status_assigns = Property_status.True let status_allocates = Property_status.Dont_know let status_terminates = Property_status.Dont_know +let run () = + let get_spec kf = + ignore(Annotations.funspec kf) + in + Globals.Functions.iter get_spec + let populate () = Format.printf "Registering an empty spec generation mode@."; Populate_spec.register "emptymode"; @@ -39,4 +45,6 @@ let populate () = "mymode" - let () = Cmdline.run_after_configuring_stage populate +let () = Cmdline.run_after_configuring_stage populate + +let () = Db.Main.extend run diff --git a/tests/spec/default_spec_mode.i b/tests/spec/default_spec_mode.i index 8c987bb116f20c5e32154d4cdadff3aa31b1e2d3..de2d911f8eff7565ffae7f058c8865dfc174dfa8 100644 --- a/tests/spec/default_spec_mode.i +++ b/tests/spec/default_spec_mode.i @@ -21,6 +21,7 @@ void f2(){ } // Test for automatic assigns +//@ requires \true; int f3(int* a); // Has behavior by default diff --git a/tests/spec/oracle/default_spec_custom.0.res.oracle b/tests/spec/oracle/default_spec_custom.0.res.oracle index 72faead364b09e6ffb977a3f17cc0d821bcce069..fda41e6d63057da79517b773ecfedf608db05d4b 100644 --- a/tests/spec/oracle/default_spec_custom.0.res.oracle +++ b/tests/spec/oracle/default_spec_custom.0.res.oracle @@ -6,10 +6,14 @@ Registering a new spec generation mode [kernel] Warning: Custom generation from mode emptymode not defined for requires, using frama-c mode instead [kernel] Warning: Custom generation from mode emptymode not defined for allocates, using frama-c mode instead [kernel] Warning: Custom generation from mode emptymode not defined for terminates, using frama-c mode instead +[kernel:annot:missing-spec] default_spec_custom.i:18: Warning: + Neither code nor specification for function f1, generating default specs from the prototype [kernel] Warning: Custom status from mode emptymode not defined for exits [kernel] Warning: Custom status from mode emptymode not defined for assigns [kernel] Warning: Custom status from mode emptymode not defined for allocates [kernel] Warning: Custom status from mode emptymode not defined for terminates +[kernel:annot:missing-spec] default_spec_custom.i:18: Warning: + Neither code nor specification for function f3, generating default specs from the prototype /* Generated by Frama-C */ /*@ terminates \true; exits \false; diff --git a/tests/spec/oracle/default_spec_custom.1.res.oracle b/tests/spec/oracle/default_spec_custom.1.res.oracle index 7c6188e9550932bf83949bb00aed55eb51aafbd8..3151473f64cd26f33ade3c2431e795f2627acd78 100644 --- a/tests/spec/oracle/default_spec_custom.1.res.oracle +++ b/tests/spec/oracle/default_spec_custom.1.res.oracle @@ -1,6 +1,10 @@ Registering an empty spec generation mode Registering a new spec generation mode [kernel] Parsing default_spec_custom.i (no preprocessing) +[kernel:annot:missing-spec] default_spec_custom.i:18: Warning: + Neither code nor specification for function f1, generating default specs from the prototype +[kernel:annot:missing-spec] default_spec_custom.i:18: Warning: + Neither code nor specification for function f3, generating default specs from the prototype /* Generated by Frama-C */ /*@ requires \false; terminates \false; diff --git a/tests/spec/oracle/default_spec_mode.0.res.oracle b/tests/spec/oracle/default_spec_mode.0.res.oracle index 9624686acc4dc681db6c3c4cdb8154d4c0d74e2e..e36e713765661974785859139e5a07493fce89a5 100644 --- a/tests/spec/oracle/default_spec_mode.0.res.oracle +++ b/tests/spec/oracle/default_spec_mode.0.res.oracle @@ -8,6 +8,7 @@ void f2(void) return; } +/*@ requires \true; */ int f3(int *a); /*@ requires \true; diff --git a/tests/spec/oracle/default_spec_mode.1.res.oracle b/tests/spec/oracle/default_spec_mode.1.res.oracle index 9624686acc4dc681db6c3c4cdb8154d4c0d74e2e..e36e713765661974785859139e5a07493fce89a5 100644 --- a/tests/spec/oracle/default_spec_mode.1.res.oracle +++ b/tests/spec/oracle/default_spec_mode.1.res.oracle @@ -8,6 +8,7 @@ void f2(void) return; } +/*@ requires \true; */ int f3(int *a); /*@ requires \true; diff --git a/tests/spec/oracle/default_spec_mode.2.res.oracle b/tests/spec/oracle/default_spec_mode.2.res.oracle index ecda6945556f64107334dff2970a6f836316414a..e3d1b2a70b4ab679c2049d735103be40dc5b7c66 100644 --- a/tests/spec/oracle/default_spec_mode.2.res.oracle +++ b/tests/spec/oracle/default_spec_mode.2.res.oracle @@ -1,7 +1,5 @@ [kernel] Parsing default_spec_mode.i (no preprocessing) /* Generated by Frama-C */ -/*@ terminates \true; - allocates \nothing; */ void f1(void); /*@ terminates \true; @@ -12,7 +10,8 @@ void f2(void) return; } -/*@ terminates \true; +/*@ requires \true; + terminates \true; allocates \nothing; */ int f3(int *a); diff --git a/tests/spec/oracle/default_spec_mode.3.res.oracle b/tests/spec/oracle/default_spec_mode.3.res.oracle index 9ae4d897289ffbd8f74e0cf478d39b5d3a0f23c8..a9f745a014834522381957113332b8a16232fdb6 100644 --- a/tests/spec/oracle/default_spec_mode.3.res.oracle +++ b/tests/spec/oracle/default_spec_mode.3.res.oracle @@ -1,7 +1,5 @@ [kernel] Parsing default_spec_mode.i (no preprocessing) /* Generated by Frama-C */ -/*@ requires \false; - terminates \false; */ void f1(void); /*@ terminates \true; @@ -14,7 +12,7 @@ void f2(void) return; } -/*@ requires \false; +/*@ requires \true; terminates \false; */ int f3(int *a); diff --git a/tests/spec/oracle/default_spec_mode.4.res.oracle b/tests/spec/oracle/default_spec_mode.4.res.oracle index 272ef95df50d5a12434417a83eba8f2a9de6d888..90038462eb51543ab393e7acacb7d4349423df21 100644 --- a/tests/spec/oracle/default_spec_mode.4.res.oracle +++ b/tests/spec/oracle/default_spec_mode.4.res.oracle @@ -1,9 +1,5 @@ [kernel] Parsing default_spec_mode.i (no preprocessing) /* Generated by Frama-C */ -/*@ terminates \true; - exits \false; - assigns \nothing; - allocates \nothing; */ void f1(void); /*@ terminates \true; @@ -15,7 +11,8 @@ void f2(void) return; } -/*@ terminates \true; +/*@ requires \true; + terminates \true; exits \false; assigns \result, *a; assigns \result \from *a; diff --git a/tests/spec/oracle/default_spec_mode.5.res.oracle b/tests/spec/oracle/default_spec_mode.5.res.oracle index 1fa027e6bafbd8c8b87585758b685659038e1249..69c1b68dab380444d5914c928ff3a3f6a6f7417c 100644 --- a/tests/spec/oracle/default_spec_mode.5.res.oracle +++ b/tests/spec/oracle/default_spec_mode.5.res.oracle @@ -1,8 +1,5 @@ [kernel] Parsing default_spec_mode.i (no preprocessing) /* Generated by Frama-C */ -/*@ requires \false; - terminates \true; - assigns \nothing; */ void f1(void); /*@ terminates \true; @@ -13,7 +10,7 @@ void f2(void) return; } -/*@ requires \false; +/*@ requires \true; terminates \true; assigns \result, *a; assigns \result \from *a;