From 51efacc6618db378b56f563882c0a2d090b9a2c4 Mon Sep 17 00:00:00 2001 From: Basile Desloges <basile.desloges@cea.fr> Date: Thu, 25 Nov 2021 16:15:35 +0100 Subject: [PATCH] [eacsl] Split the name from the predicate in `runtime_check_with_msg` --- .../instrumentation_model/e_acsl_assert.c | 18 ++++++++++++--- .../e_acsl_assert_data.h | 2 ++ .../e-acsl/src/code_generator/assert.ml | 23 +++++++++++++++---- .../e-acsl/src/code_generator/assert.mli | 8 ++++--- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert.c b/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert.c index 0d1158d3b7b..e08e827589b 100644 --- a/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert.c +++ b/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert.c @@ -46,6 +46,12 @@ void eacsl_print_values(eacsl_assert_data_t *data) { } #ifndef E_ACSL_EXTERNAL_ASSERT + +/*! \brief Return `str` id `cond` is true, an empty string otherwise. */ +# define STR_IF(cond, str) ((cond) ? (str) : "") +/*! \brief Return `str` if the string is not null, an empty string otherwise. */ +# define STR_IF_NOT_NULL(str) STR_IF(str, str) + /*! \brief Default implementation of E-ACSL runtime assertions */ void eacsl_runtime_assert(int predicate, eacsl_assert_data_t *data) { if (eacsl_runtime_sound_verdict) { @@ -55,9 +61,11 @@ void eacsl_runtime_assert(int predicate, eacsl_assert_data_t *data) { STDERR("%s: In function '%s'\n" "%s:%d: Error: %s failed:\n" "\tThe failing predicate is:\n" - "\t%s.\n", + "\t%s%s%s.\n", data->file, data->fct, data->file, data->line, data->kind, + STR_IF_NOT_NULL(data->name), + STR_IF(data->name, ":\n\t\t"), data->pred_txt); // clang-format on eacsl_print_values(data); @@ -78,9 +86,11 @@ void eacsl_runtime_assert(int predicate, eacsl_assert_data_t *data) { // clang-format off STDERR("%s: In function '%s'\n" "%s:%d: %s valid:\n" - "\t%s.\n", + "\t%s%s%s.\n", data->file, data->fct, data->file, data->line, data->kind, + STR_IF_NOT_NULL(data->name), + STR_IF(data->name, ":\n\t\t"), data->pred_txt); // clang-format on eacsl_print_values(data); @@ -93,9 +103,11 @@ void eacsl_runtime_assert(int predicate, eacsl_assert_data_t *data) { STDERR("%s: In function '%s'\n" "%s:%d: Warning: no sound verdict for %s (guess: %s).\n" "\tthe considered predicate is:\n" - "\t%s\n", + "\t%s%s%s\n", data->file, data->fct, data->file, data->line, data->kind, predicate ? "ok" : "FAIL", + STR_IF_NOT_NULL(data->name), + STR_IF(data->name, ":\n\t\t"), data->pred_txt); // clang-format on eacsl_print_values(data); diff --git a/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert_data.h b/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert_data.h index 7a91b70ac09..aa94970d5ce 100644 --- a/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert_data.h +++ b/src/plugins/e-acsl/share/e-acsl/instrumentation_model/e_acsl_assert_data.h @@ -190,6 +190,8 @@ typedef struct eacsl_assert_data_t { int blocking; /*! C string representing a kind of annotation (e.g., "Assertion") */ const char *kind; + /*! name identifying the predicate */ + const char *name; /*! stringified predicate */ const char *pred_txt; /*! un-instrumented file of predicate placement */ diff --git a/src/plugins/e-acsl/src/code_generator/assert.ml b/src/plugins/e-acsl/src/code_generator/assert.ml index 2321d56a757..f2528e9c6df 100644 --- a/src/plugins/e-acsl/src/code_generator/assert.ml +++ b/src/plugins/e-acsl/src/code_generator/assert.ml @@ -205,7 +205,7 @@ let kind_to_string loc k = | Smart_stmt.Variant -> "Variant" | Smart_stmt.RTE -> "RTE") -let runtime_check_with_msg ~adata ~loc msg ~pred_kind kind kf env predicate_e = +let runtime_check_with_msg ~adata ~loc ?(name="") msg ~pred_kind kind kf env predicate_e = let env = Env.push env in let data_registered, data_ptr, data_vi, env = match adata with @@ -234,14 +234,27 @@ let runtime_check_with_msg ~adata ~loc msg ~pred_kind kind kf env predicate_e = let fct = Cil.mkString ~loc (Functions.RTL.get_original_name kf) in let line = Cil.integer ~loc start_pos.Filepath.pos_lnum in let stmts = - [ Smart_stmt.rtl_call ~loc "assert" [ predicate_e; data_ptr ]; - Smart_stmt.assigns_field ~loc data_vi "line" line; + [ Smart_stmt.assigns_field ~loc data_vi "line" line; Smart_stmt.assigns_field ~loc data_vi "fct" fct; Smart_stmt.assigns_field ~loc data_vi "file" file; Smart_stmt.assigns_field ~loc data_vi "pred_txt" pred_txt; Smart_stmt.assigns_field ~loc data_vi "kind" kind; Smart_stmt.assigns_field ~loc data_vi "blocking" blocking ] in + let stmts = + if Datatype.String.equal name "" then + stmts + else + Smart_stmt.assigns_field + ~loc + data_vi + "name" + (Cil.mkString ~loc name) + :: stmts + in + let stmts = + Smart_stmt.rtl_call ~loc "assert" [ predicate_e; data_ptr ] :: stmts + in let stmts= if data_registered then Smart_stmt.rtl_call ~loc "assert_clean" [ data_ptr ] :: stmts @@ -259,5 +272,7 @@ let runtime_check_with_msg ~adata ~loc msg ~pred_kind kind kf env predicate_e = let runtime_check ~adata ~pred_kind kind kf env e p = let loc = p.pred_loc in + let name = String.concat "/" p.pred_name in + let p = { p with pred_name = [] } in let msg = Format.asprintf "%a@?" Printer.pp_predicate p in - runtime_check_with_msg ~adata ~loc msg ~pred_kind kind kf env e + runtime_check_with_msg ~adata ~loc ~name msg ~pred_kind kind kf env e diff --git a/src/plugins/e-acsl/src/code_generator/assert.mli b/src/plugins/e-acsl/src/code_generator/assert.mli index d81ed28c982..30ae0b268d0 100644 --- a/src/plugins/e-acsl/src/code_generator/assert.mli +++ b/src/plugins/e-acsl/src/code_generator/assert.mli @@ -118,6 +118,7 @@ val runtime_check: val runtime_check_with_msg: adata:t -> loc:location -> + ?name:string -> string -> pred_kind:predicate_kind -> Smart_stmt.annotation_kind -> @@ -125,12 +126,13 @@ val runtime_check_with_msg: Env.t -> exp -> stmt * Env.t -(** [runtime_check_with_msg ~adata ~loc msg ~pred_kind kind kf env e] generates - a runtime check for [e] (or [!e] if [reverse] is [true]) by building a call - to [__e_acsl_assert]. +(** [runtime_check_with_msg ~adata ~loc ?name msg ~pred_kind kind kf env e] + generates a runtime check for [e] (or [!e] if [reverse] is [true]) by + building a call to [__e_acsl_assert]. [adata] is the assertion context holding the data contributing to the assertion. [loc] is the location printed in the message if the runtime check fails. + [name] is the name of the predicate printed if the runtime check fails. [msg] is the message printed if the runtime check fails. [pred_kind] indicates if the assert should be blocking or not. [kind] is the annotation kind of [p]. -- GitLab