From 2ea357b6585263fd29d03c8a1ae6472653a6a657 Mon Sep 17 00:00:00 2001 From: Jan Rochel <jan.rochel@cea.fr> Date: Sun, 1 Sep 2024 13:38:16 +0200 Subject: [PATCH] [e-acsl] pathological example for bad scoping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bin/test.sh -c dev fails for this example. GCC complains that a.out.frama.c:277:13: error: ‘__gen_e_acsl_v_2’ undeclared The translation doesn't take into account the scenario that the same logic function needs to be translated twice. This is due to different call sites requiring different signatures. The authors of the translation must worked with the assumption that uniqueness of logic variables is a strong enough guarantee to be able to reuse the translation of a logic variable can always be re-used. This is wrong, since the translation of a logic variable can be re-used within the context of one function translation, but escapes its scope if it is re-used in another translation of the same function. --- src/plugins/e-acsl/tests/constructs/let.c | 18 ++++ .../e-acsl/tests/constructs/oracle/gen_let.c | 85 +++++++++++++++++++ .../tests/constructs/oracle/let.res.oracle | 4 + 3 files changed, 107 insertions(+) create mode 100644 src/plugins/e-acsl/tests/constructs/let.c create mode 100644 src/plugins/e-acsl/tests/constructs/oracle/gen_let.c create mode 100644 src/plugins/e-acsl/tests/constructs/oracle/let.res.oracle diff --git a/src/plugins/e-acsl/tests/constructs/let.c b/src/plugins/e-acsl/tests/constructs/let.c new file mode 100644 index 00000000000..eef3a376cf1 --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/let.c @@ -0,0 +1,18 @@ +/* run.config + COMMENT: The same function is translated twice with different signatures. + COMMENT: This regression test ensures that translations of sub-terms do not + COMMENT: spill over from one translation to the other, falling out of scope. +*/ + +/*@ + +logic ℤ f(ℤ x) = + x ≡ 0 ? 0 : + \let v = f(0); + 0 ≡ v ? x - 1 : 0; + +*/ + +int main() { + /*@ assert f(1) == 0; */ +} diff --git a/src/plugins/e-acsl/tests/constructs/oracle/gen_let.c b/src/plugins/e-acsl/tests/constructs/oracle/gen_let.c new file mode 100644 index 00000000000..60957b9d31a --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle/gen_let.c @@ -0,0 +1,85 @@ +/* Generated by Frama-C */ +#include "pthread.h" +#include "sched.h" +#include "signal.h" +#include "stddef.h" +#include "stdint.h" +#include "stdio.h" +#include "time.h" +extern __attribute__((__FC_BUILTIN__)) int __e_acsl_sound_verdict; + +/*@ +logic integer f(integer x) = x == 0? 0: (\let v = f(0); 0 == v? x - 1: 0); + +*/ +long __gen_e_acsl_f_2(int x); + +int __gen_e_acsl_f(int x); + +int main(void) +{ + int __retres; + __e_acsl_memory_init((int *)0,(char ***)0,8UL); + { + int __gen_e_acsl_f_6; + __e_acsl_assert_data_t __gen_e_acsl_assert_data = {.values = (void *)0}; + __gen_e_acsl_f_6 = __gen_e_acsl_f(1); + __e_acsl_assert_register_int(& __gen_e_acsl_assert_data,"f(1)",0, + __gen_e_acsl_f_6); + __gen_e_acsl_assert_data.blocking = 1; + __gen_e_acsl_assert_data.kind = "Assertion"; + __gen_e_acsl_assert_data.pred_txt = "f(1) == 0"; + __gen_e_acsl_assert_data.file = "let.c"; + __gen_e_acsl_assert_data.fct = "main"; + __gen_e_acsl_assert_data.line = 17; + __e_acsl_assert(__gen_e_acsl_f_6 == 0,& __gen_e_acsl_assert_data); + __e_acsl_assert_clean(& __gen_e_acsl_assert_data); + } + /*@ assert f(1) == 0; */ ; + __retres = 0; + __e_acsl_memory_clean(); + return __retres; +} + +/*@ assigns \result; + assigns \result \from x; */ +int __gen_e_acsl_f(int x) +{ + long __gen_e_acsl_if_4; + if (x == 0) __gen_e_acsl_if_4 = 0L; + else { + long __gen_e_acsl_v; + long __gen_e_acsl_f_5; + long __gen_e_acsl_if_3; + __gen_e_acsl_f_5 = __gen_e_acsl_f_2(0); + __gen_e_acsl_v = __gen_e_acsl_f_5; + /*@ assert Eva: initialization: \initialized(&__gen_e_acsl_v_2); */ + if (0L == __gen_e_acsl_v_2) __gen_e_acsl_if_3 = x - 1L; + else __gen_e_acsl_if_3 = 0L; + __gen_e_acsl_if_4 = __gen_e_acsl_if_3; + } + int __retres = (int)__gen_e_acsl_if_4; + return __retres; +} + +/*@ assigns \result; + assigns \result \from x; */ +long __gen_e_acsl_f_2(int x) +{ + long __gen_e_acsl_if_2; + if (x == 0) __gen_e_acsl_if_2 = 0L; + else { + long __gen_e_acsl_v_2; + long __gen_e_acsl_f_4; + long __gen_e_acsl_if; + __gen_e_acsl_f_4 = __gen_e_acsl_f_2(0); + __gen_e_acsl_v_2 = __gen_e_acsl_f_4; + if (0L == __gen_e_acsl_v_2) __gen_e_acsl_if = x - 1L; + else __gen_e_acsl_if = 0L; + __gen_e_acsl_if_2 = __gen_e_acsl_if; + } + long __retres = (int)__gen_e_acsl_if_2; + return __retres; +} + + diff --git a/src/plugins/e-acsl/tests/constructs/oracle/let.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle/let.res.oracle new file mode 100644 index 00000000000..d3f26b8698b --- /dev/null +++ b/src/plugins/e-acsl/tests/constructs/oracle/let.res.oracle @@ -0,0 +1,4 @@ +[e-acsl] beginning translation. +[e-acsl] translation done in project "e-acsl". +[eva:alarm] let.c:12: Warning: + accessing uninitialized left-value. assert \initialized(&__gen_e_acsl_v_2); -- GitLab