diff --git a/.Makefile.lint b/.Makefile.lint index b1cacfe729919dae0c13e0d0f2b82bad3938a0b4..69b506b6c4e6dcb894a746aed704839d6e5b8ee3 100644 --- a/.Makefile.lint +++ b/.Makefile.lint @@ -181,7 +181,6 @@ ML_LINT_KO+=src/libraries/utils/hptset.ml ML_LINT_KO+=src/libraries/utils/hptset.mli ML_LINT_KO+=src/libraries/utils/indexer.ml ML_LINT_KO+=src/libraries/utils/indexer.mli -ML_LINT_KO+=src/libraries/utils/leftistheap.mli ML_LINT_KO+=src/libraries/utils/pretty_utils.ml ML_LINT_KO+=src/libraries/utils/pretty_utils.mli ML_LINT_KO+=src/libraries/utils/qstack.ml diff --git a/Changelog b/Changelog index cbaba73e633d47793905f529b68d0f82beceb28e..c4be996965f6c843d60644c383d06de96e3536c3 100644 --- a/Changelog +++ b/Changelog @@ -17,9 +17,25 @@ Open Source Release <next-release> ################################## +- Eva [2019/10/23] New option -eva-auto-loop-unroll N to unroll all + loops whose number of iterations can be easily bounded by <N>. +- Eva [2019/10/21] New octagon domain inferring relations of the form + l ≤ ±X±Y ≤ e between pairs of integer variables X and Y. Enabled + with option -eva-octagon-domain. Only infers relations between + pairs of scalar variables occuring in a same instruction. + Intra-procedural by default; octagons can be propagated through + function calls with option -eva-octagon-through-calls. +- Eva [2019/10/04] Evaluates ACSL predicates \is_plus_infinity and + \is_minus_infinity. +- Kernel [2019/10/04] Supports macro INFINITY and NAN. o Config [2019/09/27] ocp-indent 1.7.0 is now used for indentation +o Eva [2019/09/16] Dynamic registration of abstract values and domains: + developers of new domains no longer need to modify Eva's engine. +-* Kernel [2019/09/13] Fixes Hptmap on keys with id greater than 2^28. -* Makefile [2019/09/12] Fixes #2378 - bytecode only compilation (patch contributed by madroach) and use -thread where needed. +-* Eva [2019/08/21] Fixes the reduction by the negation of \initialized + and \dangling predicates on imprecise lvalues. -* Kernel [2019/08/20] Fixes a rare but critical bug which occured when Frama-C internally switched the current project in presence of >2 projects and destroyed the old current project at about the same @@ -40,6 +56,8 @@ o! Sparecode [2019/07/26] Removed from Db. Use proper Sparecode API instead. -! Kernel [2019/07/24] OCaml version greater than or equal to 4.05.0 required. - Kernel [2019/07/24] Improve placeholders handling in -cpp-command o! Kernel [2019/07/23] Types in Properties are now records and not tuples +- Eva [2019/07/09] Supports ACSL floating-point comparison operators + eq_float, le_float, eq_double, le_double, etc. o! Kernel [2019/06/28] removes AST constructors TCoerce, TCoerceE, PLCoercion, PLCoercionE, Psubtype and PLsubtype -* Kernel [2019/06/20] fixes dangling ref when removing unused static local diff --git a/Makefile b/Makefile index 476d1807b2c22731957fd4d801361f45cbd6671b..6662ccfbd0253bbaa9cb0a55ffe13667951e5926 100644 --- a/Makefile +++ b/Makefile @@ -461,7 +461,6 @@ LIB_CMO =\ src/libraries/utils/rgmap \ src/libraries/utils/bitvector \ src/libraries/utils/qstack \ - src/libraries/utils/leftistheap \ src/libraries/stdlib/integer \ src/libraries/utils/json \ src/libraries/utils/markdown \ @@ -823,7 +822,7 @@ PLUGIN_ENABLE:=$(ENABLE_EVA) PLUGIN_NAME:=Eva PLUGIN_DIR:=src/plugins/value PLUGIN_EXTRA_DIRS:=engine values domains domains/cvalue domains/apron \ - domains/gauges domains/equality legacy slevel utils gui_files \ + domains/gauges domains/equality legacy partitioning utils gui_files \ values/numerors domains/numerors PLUGIN_TESTS_DIRS+=value/traces @@ -856,12 +855,12 @@ endif # General rules for ordering files within PLUGIN_CMO: # - try to keep the legacy Value before Eva -PLUGIN_CMO:= slevel/split_strategy value_parameters \ +PLUGIN_CMO:= partitioning/split_strategy value_parameters \ utils/value_perf utils/value_util utils/red_statuses \ utils/mark_noresults \ utils/widen_hints_ext utils/widen utils/partitioning_annots \ - engine/split_return \ - slevel/per_stmt_slevel \ + partitioning/split_return \ + partitioning/per_stmt_slevel \ utils/library_functions \ utils/eval_typ utils/backward_formals \ alarmset eval utils/structure utils/abstract \ @@ -875,6 +874,7 @@ PLUGIN_CMO:= slevel/split_strategy value_parameters \ domains/printer_domain \ domains/traces_domain \ domains/simple_memory \ + domains/octagons \ domains/gauges/gauges_domain \ domains/hcexprs \ domains/equality/equality domains/equality/equality_domain \ @@ -898,10 +898,10 @@ PLUGIN_CMO:= slevel/split_strategy value_parameters \ domains/cvalue/cvalue_domain \ engine/subdivided_evaluation engine/evaluation engine/abstractions \ engine/recursion engine/transfer_stmt engine/transfer_specification \ - engine/partitioning_index engine/mem_exec \ - engine/partition engine/partitioning_parameters engine/trace_partitioning \ - engine/iterator \ - engine/initialization \ + partitioning/auto_loop_unroll \ + partitioning/partition partitioning/partitioning_parameters \ + partitioning/partitioning_index partitioning/trace_partitioning \ + engine/mem_exec engine/iterator engine/initialization \ engine/compute_functions engine/analysis register \ $(APRON_CMO) $(NUMERORS_CMO) PLUGIN_CMI:= values/abstract_value values/abstract_location \ diff --git a/doc/value/div.c b/doc/value/examples/alarms/div.c similarity index 100% rename from doc/value/div.c rename to doc/value/examples/alarms/div.c diff --git a/doc/value/double_op_arg.c b/doc/value/examples/alarms/double_op_arg.c similarity index 100% rename from doc/value/double_op_arg.c rename to doc/value/examples/alarms/double_op_arg.c diff --git a/doc/value/double_op_res.c b/doc/value/examples/alarms/double_op_res.c similarity index 100% rename from doc/value/double_op_res.c rename to doc/value/examples/alarms/double_op_res.c diff --git a/doc/value/invalid.c b/doc/value/examples/alarms/invalid.c similarity index 100% rename from doc/value/invalid.c rename to doc/value/examples/alarms/invalid.c diff --git a/doc/value/invalid_bool.c b/doc/value/examples/alarms/invalid_bool.c similarity index 100% rename from doc/value/invalid_bool.c rename to doc/value/examples/alarms/invalid_bool.c diff --git a/doc/value/lshift.c b/doc/value/examples/alarms/lshift.c similarity index 100% rename from doc/value/lshift.c rename to doc/value/examples/alarms/lshift.c diff --git a/doc/value/ov_float_int.c b/doc/value/examples/alarms/ov_float_int.c similarity index 100% rename from doc/value/ov_float_int.c rename to doc/value/examples/alarms/ov_float_int.c diff --git a/doc/value/overlap.c b/doc/value/examples/alarms/overlap.c similarity index 100% rename from doc/value/overlap.c rename to doc/value/examples/alarms/overlap.c diff --git a/doc/value/pointer_comparison.c b/doc/value/examples/alarms/pointer_comparison.c similarity index 100% rename from doc/value/pointer_comparison.c rename to doc/value/examples/alarms/pointer_comparison.c diff --git a/doc/value/se.c b/doc/value/examples/alarms/se.c similarity index 100% rename from doc/value/se.c rename to doc/value/examples/alarms/se.c diff --git a/doc/value/shift.c b/doc/value/examples/alarms/shift.c similarity index 100% rename from doc/value/shift.c rename to doc/value/examples/alarms/shift.c diff --git a/doc/value/uninitialized.c b/doc/value/examples/alarms/uninitialized.c similarity index 100% rename from doc/value/uninitialized.c rename to doc/value/examples/alarms/uninitialized.c diff --git a/doc/value/valid_function.c b/doc/value/examples/alarms/valid_function.c similarity index 100% rename from doc/value/valid_function.c rename to doc/value/examples/alarms/valid_function.c diff --git a/doc/value/annotations_2.c b/doc/value/examples/annotations_2.c similarity index 100% rename from doc/value/annotations_2.c rename to doc/value/examples/annotations_2.c diff --git a/doc/value/ari.c b/doc/value/examples/ari.c similarity index 100% rename from doc/value/ari.c rename to doc/value/examples/ari.c diff --git a/doc/value/array.c b/doc/value/examples/array.c similarity index 100% rename from doc/value/array.c rename to doc/value/examples/array.c diff --git a/doc/value/array_array_2.c b/doc/value/examples/array_array_2.c similarity index 100% rename from doc/value/array_array_2.c rename to doc/value/examples/array_array_2.c diff --git a/doc/value/bases.c b/doc/value/examples/bases.c similarity index 100% rename from doc/value/bases.c rename to doc/value/examples/bases.c diff --git a/doc/value/boucles.c b/doc/value/examples/boucles.c similarity index 100% rename from doc/value/boucles.c rename to doc/value/examples/boucles.c diff --git a/doc/value/boucles1.c b/doc/value/examples/boucles1.c similarity index 100% rename from doc/value/boucles1.c rename to doc/value/examples/boucles1.c diff --git a/doc/value/boucles_run.c b/doc/value/examples/boucles_run.c similarity index 100% rename from doc/value/boucles_run.c rename to doc/value/examples/boucles_run.c diff --git a/doc/value/case.c b/doc/value/examples/case.c similarity index 100% rename from doc/value/case.c rename to doc/value/examples/case.c diff --git a/doc/value/default.c b/doc/value/examples/default.c similarity index 100% rename from doc/value/default.c rename to doc/value/examples/default.c diff --git a/doc/value/deps.c b/doc/value/examples/deps.c similarity index 100% rename from doc/value/deps.c rename to doc/value/examples/deps.c diff --git a/doc/value/depth.c b/doc/value/examples/depth.c similarity index 100% rename from doc/value/depth.c rename to doc/value/examples/depth.c diff --git a/doc/value/double_assign.c b/doc/value/examples/double_assign.c similarity index 100% rename from doc/value/double_assign.c rename to doc/value/examples/double_assign.c diff --git a/doc/value/exemple_origin_arithmetic.c b/doc/value/examples/exemple_origin_arithmetic.c similarity index 100% rename from doc/value/exemple_origin_arithmetic.c rename to doc/value/examples/exemple_origin_arithmetic.c diff --git a/doc/value/false_al.c b/doc/value/examples/false_al.c similarity index 100% rename from doc/value/false_al.c rename to doc/value/examples/false_al.c diff --git a/doc/value/fonctions.c b/doc/value/examples/fonctions.c similarity index 100% rename from doc/value/fonctions.c rename to doc/value/examples/fonctions.c diff --git a/doc/value/introduction.c b/doc/value/examples/introduction.c similarity index 100% rename from doc/value/introduction.c rename to doc/value/examples/introduction.c diff --git a/doc/value/leaf.c b/doc/value/examples/leaf.c similarity index 100% rename from doc/value/leaf.c rename to doc/value/examples/leaf.c diff --git a/doc/value/main.c b/doc/value/examples/main.c similarity index 100% rename from doc/value/main.c rename to doc/value/examples/main.c diff --git a/doc/value/merge.c b/doc/value/examples/merge.c similarity index 100% rename from doc/value/merge.c rename to doc/value/examples/merge.c diff --git a/doc/value/misa.c b/doc/value/examples/misa.c similarity index 100% rename from doc/value/misa.c rename to doc/value/examples/misa.c diff --git a/doc/value/no_propagation.c b/doc/value/examples/no_propagation.c similarity index 100% rename from doc/value/no_propagation.c rename to doc/value/examples/no_propagation.c diff --git a/doc/value/nondet.c b/doc/value/examples/nondet.c similarity index 100% rename from doc/value/nondet.c rename to doc/value/examples/nondet.c diff --git a/doc/value/op_inputs.c b/doc/value/examples/op_inputs.c similarity index 100% rename from doc/value/op_inputs.c rename to doc/value/examples/op_inputs.c diff --git a/doc/value/pad.c b/doc/value/examples/pad.c similarity index 100% rename from doc/value/pad.c rename to doc/value/examples/pad.c diff --git a/doc/value/perf.c b/doc/value/examples/perf.c similarity index 100% rename from doc/value/perf.c rename to doc/value/examples/perf.c diff --git a/doc/value/posix.c b/doc/value/examples/posix.c similarity index 100% rename from doc/value/posix.c rename to doc/value/examples/posix.c diff --git a/doc/value/reduction.c b/doc/value/examples/reduction.c similarity index 100% rename from doc/value/reduction.c rename to doc/value/examples/reduction.c diff --git a/doc/value/rte.c b/doc/value/examples/rte.c similarity index 100% rename from doc/value/rte.c rename to doc/value/examples/rte.c diff --git a/doc/value/s_t.c b/doc/value/examples/s_t.c similarity index 100% rename from doc/value/s_t.c rename to doc/value/examples/s_t.c diff --git a/doc/value/sq.c b/doc/value/examples/sq.c similarity index 100% rename from doc/value/sq.c rename to doc/value/examples/sq.c diff --git a/doc/value/termination.c b/doc/value/examples/termination.c similarity index 100% rename from doc/value/termination.c rename to doc/value/examples/termination.c diff --git a/doc/value/vraie_al.c b/doc/value/examples/vraie_al.c similarity index 100% rename from doc/value/vraie_al.c rename to doc/value/examples/vraie_al.c diff --git a/doc/value/gui-images-raw/RMB_click.svg b/doc/value/gui-images/RMB_click.svg similarity index 100% rename from doc/value/gui-images-raw/RMB_click.svg rename to doc/value/gui-images/RMB_click.svg diff --git a/doc/value/eval-acsl.png b/doc/value/gui-images/eval-acsl.png similarity index 100% rename from doc/value/eval-acsl.png rename to doc/value/gui-images/eval-acsl.png diff --git a/doc/value/gui-callstacks-annotated.png b/doc/value/gui-images/gui-callstacks-annotated.png similarity index 100% rename from doc/value/gui-callstacks-annotated.png rename to doc/value/gui-images/gui-callstacks-annotated.png diff --git a/doc/value/gui-images-raw/gui-callstacks.png b/doc/value/gui-images/gui-callstacks.png similarity index 100% rename from doc/value/gui-images-raw/gui-callstacks.png rename to doc/value/gui-images/gui-callstacks.png diff --git a/doc/value/gui-images-raw/gui-callstacks.svg b/doc/value/gui-images/gui-callstacks.svg similarity index 100% rename from doc/value/gui-images-raw/gui-callstacks.svg rename to doc/value/gui-images/gui-callstacks.svg diff --git a/doc/value/gui-loop-to-unroll.png b/doc/value/gui-images/gui-loop-to-unroll.png similarity index 100% rename from doc/value/gui-loop-to-unroll.png rename to doc/value/gui-images/gui-loop-to-unroll.png diff --git a/doc/value/gui-red-alarms-panel.png b/doc/value/gui-images/gui-red-alarms-panel.png similarity index 100% rename from doc/value/gui-red-alarms-panel.png rename to doc/value/gui-images/gui-red-alarms-panel.png diff --git a/doc/value/gui-red-values.png b/doc/value/gui-images/gui-red-values.png similarity index 100% rename from doc/value/gui-red-values.png rename to doc/value/gui-images/gui-red-values.png diff --git a/doc/value/gui-side-panel.png b/doc/value/gui-images/gui-side-panel.png similarity index 100% rename from doc/value/gui-side-panel.png rename to doc/value/gui-images/gui-side-panel.png diff --git a/doc/value/gui-values-annotated.png b/doc/value/gui-images/gui-values-annotated.png similarity index 100% rename from doc/value/gui-values-annotated.png rename to doc/value/gui-images/gui-values-annotated.png diff --git a/doc/value/gui-images-raw/gui-values.png b/doc/value/gui-images/gui-values.png similarity index 100% rename from doc/value/gui-images-raw/gui-values.png rename to doc/value/gui-images/gui-values.png diff --git a/doc/value/gui-images-raw/gui-values.svg b/doc/value/gui-images/gui-values.svg similarity index 100% rename from doc/value/gui-images-raw/gui-values.svg rename to doc/value/gui-images/gui-values.svg diff --git a/doc/value/gui1-annotated.pdf b/doc/value/gui-images/gui1-annotated.pdf similarity index 100% rename from doc/value/gui1-annotated.pdf rename to doc/value/gui-images/gui1-annotated.pdf diff --git a/doc/value/gui-images-raw/gui1-annotated.svg b/doc/value/gui-images/gui1-annotated.svg similarity index 100% rename from doc/value/gui-images-raw/gui1-annotated.svg rename to doc/value/gui-images/gui1-annotated.svg diff --git a/doc/value/gui-images-raw/gui1.png b/doc/value/gui-images/gui1.png similarity index 100% rename from doc/value/gui-images-raw/gui1.png rename to doc/value/gui-images/gui1.png diff --git a/doc/value/gui2.png b/doc/value/gui-images/gui2.png similarity index 100% rename from doc/value/gui2.png rename to doc/value/gui-images/gui2.png diff --git a/doc/value/gui3.png b/doc/value/gui-images/gui3.png similarity index 100% rename from doc/value/gui3.png rename to doc/value/gui-images/gui3.png diff --git a/doc/value/gui4.png b/doc/value/gui-images/gui4.png similarity index 100% rename from doc/value/gui4.png rename to doc/value/gui-images/gui4.png diff --git a/doc/value/gui5.png b/doc/value/gui-images/gui5.png similarity index 100% rename from doc/value/gui5.png rename to doc/value/gui-images/gui5.png diff --git a/doc/value/studia.png b/doc/value/gui-images/studia.png similarity index 100% rename from doc/value/studia.png rename to doc/value/gui-images/studia.png diff --git a/doc/value/gui.tex b/doc/value/gui.tex index 62e1b8e87129388ad83eb8baecb4e56d81355141..4a767a5126cf2aa4a28b7c02dec4c8388bd982d7 100644 --- a/doc/value/gui.tex +++ b/doc/value/gui.tex @@ -39,7 +39,7 @@ indicate some parts that are never (or rarely) used with \Eva{}. \begin{figure}[hbt] \centering -\includegraphics[width=\textwidth]{gui1-annotated.pdf} +\includegraphics[width=\textwidth]{gui-images/gui1-annotated.pdf} \caption{Frama-C GUI for \Eva{}} \label{fig:gui-eva} \end{figure} @@ -64,7 +64,7 @@ The checkbox {\em Show list of red alarms} shows or hides the \begin{figure} \centering -\includegraphics[scale=0.7]{gui-side-panel.png} +\includegraphics[scale=0.7]{gui-images/gui-side-panel.png} \caption{GUI side panel for \Eva{}} \label{fig:gui-side-panel} \end{figure} @@ -85,7 +85,7 @@ non-terminating statement, which in our example is a call to \begin{figure}[hbt] \centering -\includegraphics[width=\textwidth]{gui2.png} +\includegraphics[width=\textwidth]{gui-images/gui2.png} \caption{Unreachable code in the Frama-C GUI} \label{fig:gui-unreachable} \end{figure} @@ -120,7 +120,7 @@ the most powerful inspection tool for the \Eva{} plug-in in the Frama-C GUI. \begin{figure}[hbtp] \centering -\includegraphics[width=\textwidth]{gui-values-annotated.png} +\includegraphics[width=\textwidth]{gui-images/gui-values-annotated.png} \caption{Values panel} \label{fig:values-panel} \end{figure} @@ -141,7 +141,7 @@ displayed in the \emph{Values} panel. \begin{figure}[!hbtp] \centering -\includegraphics[scale=0.7]{eval-acsl.png} +\includegraphics[scale=0.7]{gui-images/eval-acsl.png} \caption{Evaluate ACSL term dialog, accessible via a context menu or by pressing Ctrl+E.} \label{fig:eval-acsl} @@ -168,7 +168,7 @@ via right-clicks (Figure~\ref{fig:callstacks}). \begin{figure}[hbtp] \centering -\includegraphics[width=\textwidth]{gui-callstacks-annotated.png} +\includegraphics[width=\textwidth]{gui-images/gui-callstacks-annotated.png} \caption{Callstacks display} \label{fig:callstacks} \end{figure} @@ -202,7 +202,7 @@ the result displayed in Figure~\ref{fig:non-term-callstack}. \begin{figure}[hbt] \centering -\includegraphics[width=\textwidth]{gui5.png} +\includegraphics[width=\textwidth]{gui-images/gui5.png} \caption{Focused on a non-terminating callstack} \label{fig:non-term-callstack} \end{figure} @@ -245,7 +245,7 @@ indirect accesses. \begin{figure}[h!] \caption{\label{fig:studia}Studia elements in the GUI} \centering - \includegraphics[width=\textwidth]{studia} + \includegraphics[width=\textwidth]{gui-images/studia} \end{figure} Typical usage of Studia consists in: starting the GUI, selecting an alarm @@ -321,7 +321,7 @@ status was emitted during the analysis. \begin{figure}[htbp] \centering -\includegraphics[width=\textwidth]{gui-red-alarms-panel.png} +\includegraphics[width=\textwidth]{gui-images/gui-red-alarms-panel.png} \caption{Red alarms panel} \label{fig:red-alarms-panel} \end{figure} @@ -335,7 +335,7 @@ the property evaluated to false at least once''. \begin{figure}[htbp] \centering -\includegraphics[width=\textwidth]{gui-red-values.png} +\includegraphics[width=\textwidth]{gui-images/gui-red-values.png} \caption{Indicators of red alarms in the Values panel} \label{fig:red-values} \end{figure} diff --git a/doc/value/main.idx b/doc/value/main.idx deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/doc/value/main.tex b/doc/value/main.tex index 8a8ef8917377f732c9ad306cc8a44e66b110f564..abb6737522fbfad435bb1ad7827f77e80a0dbe01 100644 --- a/doc/value/main.tex +++ b/doc/value/main.tex @@ -119,7 +119,7 @@ code and observe an over-approximation of the set of values this expression can take at run-time. Here is a simple C example: -\listinginputcaption{1}{\texttt{introduction.c}}{introduction.c} +\listinginputcaption{1}{\texttt{introduction.c}}{examples/introduction.c} If either interface of Frama-C is launched with options \lstinline|-eva introduction.c|, @@ -151,7 +151,7 @@ during the last forty years. An analyzed application may contain run-time errors: divisions by zero, invalid pointer accesses,\ldots -\listinginputcaption{1}{\texttt{rte.c}}{rte.c} +\listinginputcaption{1}{\texttt{rte.c}}{examples/rte.c} When launched with \lstinline|frama-c -eva rte.c|, \Eva{} emits a warning about an out-of-bound access at line 5: @@ -645,20 +645,32 @@ Before we spend any of our time looking at each of these alarms, trying to determine whether they are true or false, it is a good idea to make the analyzer spend more of {\em its} time trying to determine the same thing. -There are different settings that influence the compromise -between precision and resource consumption. When dealing with bounded loops, -the best approach consists in using an ACSL annotation, \verb+//@ loop unroll N+, -to direct \Eva{} to analyze precisely the N first iterations of the loop -before approximating the results. +There are different settings that influence the trade-off +between precision and resource consumption. -Currently, annotating loops is done manually; in future releases of Frama-C, -this will be partly automated. In simple loops, you can obtain its -bounds via the GUI, by inspecting the values taken by the loop counter, -as in the example below: +When dealing with bounded loops, option \verb+-eva-auto-loop-unroll N+ +automatically unrolls simple loops that have less than \verb+N+ iterations. +This option is based on syntactic heuristics to improve the precision +at a low cost, and will not handle complex loops. +It should be enabled in most analyses. + +If automatic loop unrolling is insufficient, the next best approach consists in +using an ACSL annotation, \verb+//@ loop unroll N+, to direct \Eva{} to analyze +precisely the \verb+N+ first iterations of the loop before approximating the +results. + +Note: both approaches can be combined to enable automatic loop unrolling +{\em except} in a few chosen loops: since the \verb+@loop unroll+ annotation +takes precedence over other options, adding \verb+@loop unroll 0;+ to a loop +will prevent it from being unrolled, even when \verb+-eva-auto-loop-unroll+ +is active. + +Frama-C's graphical interface can help estimating loop bounds by inspecting the +values taken by the loop counter, as in the example below: \begin{figure}[hbt] \centering -\includegraphics[width=0.75\textwidth]{gui-loop-to-unroll.png} +\includegraphics[width=0.75\textwidth]{gui-images/gui-loop-to-unroll.png} \caption{Estimating loop unroll bounds in the GUI} \label{fig:gui-loop-to-unroll} \end{figure} @@ -682,7 +694,7 @@ then add the loop unroll annotation, as follows: The value 4 is sufficient to completely unroll the loop, even though \verb|i| ranges from 0 to 4 (5 values in total). One way to confirm the unrolling is -complete is to check that the ``starting to merge loop iterations'' is no +complete is to check that ``starting to merge loop iterations'' is no longer emitted when entering the loop. Also, when a loop unroll annotation is present but insufficient to unroll the loop, a message is emitted: @@ -1346,7 +1358,7 @@ previously written as a single write that modified the whole set of bits exactly. An example of a program leading to a misaligned read is the following: -\listinginput{1}{misa.c} +\listinginput{1}{examples/misa.c} The value returned by the function \lstinline|main| is\\ \lstinline|{{ garbled mix of &{ x; y } (origin: Misaligned { misa.c:6 }) }}|.\\ The analyzer is by default configured for a 32-bit architecture, @@ -1371,7 +1383,7 @@ alignments are fused together. In the example below, the memory states from the then branch and from the else branch contain in the array \lstinline|t| some 32-bit addresses with incompatible alignments. -\listinginput{1}{merge.c} +\listinginput{1}{examples/merge.c} The value returned by function \lstinline|main| is\\ \lstinline|{{ garbled mix of &{ x; y } (origin: Merge { merge.c:10 }) }}|. @@ -1393,7 +1405,7 @@ The origin \lstinline$Arithmetic L$ indicates that arithmetic operations take place without the analyzer being able to represent the result precisely. -\listinginput{1}{ari.c} +\listinginput{1}{examples/ari.c} In this example, the return value for \lstinline|f| is\\ \lstinline|{{ garbled mix of &{ x; y } (origin: Arithmetic { ari.c:4 }) }}|. @@ -1425,7 +1437,7 @@ a dereferenced pointer is valid, it emits an alarm that expresses that the pointer needs to be valid at that point. Likewise, direct array accesses that may be invalid are flagged. -\listinginput{1}{invalid.c} +\listinginput{1}{examples/alarms/invalid.c} In the above example, the analysis is not able to guarantee that the memory accesses \lstinline|t[i]| and \lstinline|*p| are valid, so it emits a proof obligation for each: @@ -1465,7 +1477,7 @@ property that the divisor is different from zero when it continues the analysis after this point. The property expressed by an alarm may also not be taken into account when it is not easy to do so. -\listinginput{1}{div.c} +\listinginput{1}{examples/alarms/div.c} \begin{logs} div.c:4: ... division by zero. assert (int)(x*y) != 0; div.c:5: ... division by zero. assert x != 0; @@ -1487,7 +1499,7 @@ indeed, processors are often built in a way that such an operation does not produce the \lstinline|0| or \lstinline|-1| result that could have been expected. Here is an example of program with such an issue, and the resulting alarm: -\listinginput{1}{shift.c} +\listinginput{1}{examples/alarms/shift.c} \begin{logs} shift.c:4: ... invalid RHS operand for shift. assert 0 <= c < 32; \end{logs} @@ -1502,7 +1514,7 @@ and does not lead to an alarm by default. However, the option \lstinline|-warn-right-shift-negative| can be used to enable such alarms. -\listinginput{1}{lshift.c} +\listinginput{1}{examples/alarms/lshift.c} \begin{logs} [eva:alarm] lshift.c:4: Warning: invalid LHS operand for left shift. assert 0 <= x; \end{logs} @@ -1541,7 +1553,7 @@ or unsigned downcasts that may exceed the destination range. An alarm is emitted when a floating-point value appears to exceed the range of the integer type it is converted to. -\listinginput{1}{ov_float_int.c} +\listinginput{1}{examples/alarms/ov_float_int.c} \begin{logs} ... [eva:alarm] ov_float_int.c:6: Warning: overflow in conversion from floating-point @@ -1560,7 +1572,7 @@ with a finite interval representing the result obtained if excluding these possibilities. This interval, like any other result, may be over-approximated. An example of this first kind of alarm can be seen in the following example. -\listinginput{1}{double_op_res.c} +\listinginput{1}{examples/alarms/double_op_res.c} \begin{shell} frama-c -eva -main sum double_op_res.c \end{shell} @@ -1578,7 +1590,7 @@ from \lstinline|int*| to \lstinline|float*|. The emitted alarm excludes the possibility of the bit sequence used as a the argument representing \lstinline|NaN|, an infinite, or an address. See the example below. -\listinginput{1}{double_op_arg.c} +\listinginput{1}{examples/alarms/double_op_arg.c} \begin{shell} frama-c -eva double_op_arg.c \end{shell} @@ -1606,7 +1618,7 @@ value of a local variable that has not been initialized, or if it appears to manipulate the address of a local variable outside of the scope of said variable. Both issues occur in the following example: -\listinginput{1}{uninitialized.c} +\listinginput{1}{examples/alarms/uninitialized.c} \Eva{} emits alarms for lines 5 (variable \lstinline|r| may be uninitialized) and 13 (a dangling pointer to local variable \lstinline|t| is used). @@ -1650,7 +1662,7 @@ the values 0 and 1, but any other value might be a trap representation, that is, an object representation that does not represent a valid value of the type. Trap representations can be created through unions or pointer casts. -\listinginput{1}{invalid_bool.c} +\listinginput{1}{examples/alarms/invalid_bool.c} \begin{shell} frama-c -eva invalid_bool.c \end{shell} @@ -1680,7 +1692,7 @@ accordingly to the emitted alarm. For instance, for the quantity \lstinline|&x+2| must be reliably comparable to 0, the analysis assumes that the result of the comparison is 1. The consequences are visible when analyzing the following example: -\listinginput{1}{pointer_comparison.c} +\listinginput{1}{examples/alarms/pointer_comparison.c} \Eva{} finds that this program does not terminate. This seems incorrect because an actual execution will terminate on most architectures. @@ -1727,7 +1739,7 @@ the example \lstinline|y = *p + x++;|, the post-increment is defined as long as \lstinline|*p| does not have any bits in common with \lstinline|x|. -\listinginput{1}{se.c} +\listinginput{1}{examples/alarms/se.c} \begin{shell} frama-c -eva se.c -unspecified-access \end{shell} @@ -1781,7 +1793,7 @@ These limitations will be addressed in a future version. Vaguely related to, but different from, undefined side-effects in expressions, \Eva{} warns about the following program: -\listinginput{1}{overlap.c} +\listinginput{1}{examples/alarms/overlap.c} The programmer thought implementation-defined behavior was invoked in the above program, using an union to type-pun between structs S and T. @@ -1829,7 +1841,7 @@ if it can give some meaning to the call. This is meant to account for frequent misconceptions on type compatibility (e.g. \lstinline|void *| and \lstinline|int *| are \emph{not} compatible). -\listinginput{1}{valid_function.c} +\listinginput{1}{examples/alarms/valid_function.c} \begin{logs} [eva:alarm] valid_function.c:9: Warning: @@ -2165,7 +2177,7 @@ introduce approximations when analyzing a loop. Let us assume, in the following lines, that the function \lstinline|c| is unknown: -\listinginput{1}{boucles.c} +\listinginput{1}{examples/boucles.c} The \Eva{} plug-in could provide the best possible sets of values if the user explicitly instructed it to study step by step each @@ -2188,7 +2200,7 @@ call site. In the following example, the body of \lstinline|f| is analyzed again at each analysis of the body of the loop. The result of the analysis is as precise as the result obtained for the example in section \ref{boucles}. -\listinginput{1}{fonctions.c} +\listinginput{1}{examples/fonctions.c} Calls to variadic functions are handled by the \textsf{Variadic} plug-in, which translates calls to variadic functions into semantically-equivalent calls, @@ -2225,7 +2237,7 @@ assume that the actual entry point for the example of section \ref{fonctions} is not the function \lstinline|main_1| but the following \lstinline|main_main| function: -\listinginput{17}{main.c} +\listinginput{17}{examples/main.c} If the user specifies the wrong entry point \lstinline|main_1|, the plug-in will provide the @@ -2269,6 +2281,14 @@ a library function is to write C code that models its behavior, so that its code is no longer missing from the point of view of the analyzer. +Frama-C provides a set of specifications for the most common functions in the C +standard library and for some POSIX functions, plus a few extensions +(BSD, GNU, etc.). These specifications allow the analysis of applications which +use these libraries, but they become part of the {\em trusted computing base}: +it is the responsibility of the user to verify that these specifications are +correct with respect to the actual standard library implementation from the +actual execution environment. + \subsection{Choosing between complete and partial application mode} This section uses a small example to illustrate the pitfalls that should @@ -2479,7 +2499,7 @@ that the analyzed code fits in this hypothesis. On the following example, it generates a proof obligation meaning that ``the comparison on line 8 is safe only if \lstinline|p| is a valid address or if the base address of \lstinline|p| is the same as that of \lstinline|&x|''. -\listinginput{1}{bases.c} +\listinginput{1}{examples/bases.c} It is mandatory to check this proof obligation. When analyzing this example, the analysis infers that the loop never terminates (because @@ -2568,7 +2588,7 @@ real execution. Currently, \Eva{} is not designed to prove the termination of loops or similar liveness properties. For instance, the following program does not terminate: -\listinginput{1}{termination.c} +\listinginput{1}{examples/termination.c} If this program is analyzed with the default options of \Eva{}, the analysis finds that every time execution reaches the end of \lstinline|main|, the value @@ -3273,16 +3293,16 @@ on its own in a generic context. \section{Improving precision in loops} \label{boucles-traitement} -The default treatment of loops by the analyzer may produce -results that are too approximate. Tuning -the treatment of loops can improve precision. +The default treatment of loops by the analyzer often produces +results that are too approximate. +Fine-tuning loops is one of the main ways to improve precision in the analysis. When encountering a loop, the analyzer tries to compute a state -that contains all the concrete states possible at -run-time, including the initial concrete state just before -entering the loop. This englobing state may be too imprecise -by construction: typically, if the analyzed loop is initializing -an array, the user does not expect to see the initial values of +that contains all the possible concrete states at run-time, +including the initial concrete state just before entering the loop. +This enclosing state, by construction, is often imprecise: +typically, if the analyzed loop is initializing an array, +the user does not expect to see the initial values of the array appear in the state computed by the analyzer. The solution in this case is to either unroll loops, using one of several available methods, or to add annotations (widening hints or loop invariants) @@ -3292,23 +3312,57 @@ time remains bounded. \subsection{Loop unrolling} \label{loop-unroll} -Loop unrolling is often easier to apply, since it does not require much -knowledge about the loop, other than an estimate of the number of iterations. -This estimate may not improve precision if too low -or lead to unnecessary work if too high, -but will never affect its correctness. - -\subsubsection{Loop unroll annotations} - Whenever a loop has a fixed number of iterations (or a known upper bound), -an easy and precise way to handle it is to include a -\lstinline|loop unroll <n>| annotation, where -\lstinline|<n>| is the number of iterations of the loop. -It will indicate \Eva{} to analyze the loop by semantically unrolling each -iteration, avoiding merging states from different iterations. +Eva can precisely analyze it by semantically unrolling each iteration, +avoiding merging states from different iterations. This leads to increased cost in terms of analysis, but usually the cost increase is worth the improvement in precision. +Loop unrolling is often easy to apply, since it does not require much +knowledge about the loop, other than an estimate of the number of iterations. +If the estimate is too low, precision won't improve; if it is too high, +it may lead to unnecessary work; but under no circumstances will it affect the +correctness of the analysis. + +\subsubsection{Automatic loop unrolling} + +\Eva{} includes a syntactic heuristic to automatically unroll simple loops +whose number of iterations can be easily bounded. +It is enabled via option \lstinline|-eva-auto-loop-unroll <n>|, where +\lstinline|<n>| is the maximum number of iterations to unroll: loops with +less than \lstinline|<n>| iterations will be completely unrolled. +If the analysis cannot infer that a loop terminates within less than +\lstinline|<n>| iterations, then no unrolling is performed. + +\lstinline|-eva-auto-loop-unroll| is recommended as the first approach towards +loop unrolling, due to its low cost and ease of setup. An unrolling limit +up to a few hundred seems suitable in most cases. + +If \emph{all} loops in a program need to be unrolled, one way to do it quickly +consists in using option \lstinline|-eva-min-loop-unroll <n>|, +where \lstinline|<n>| is the number of iterations to unroll in each loop. +This option is very expensive, and its use should be limited. + +For a more fine-grained analysis and for non-trivial loops, +annotations are available to configure the loop unrolling on a case by case +basis. +These annotations take precedence over the automatic loop unrolling mechanism +and can be combined with them, e.g. to automatically unroll {\em all but} a few +loops. + +With options \lstinline|-eva-auto-loop-unroll AUTO -eva-min-loop-unroll MIN|: +\begin{itemize} +\item if a loop has a loop unroll annotation, it is unrolled accordingly; +\item otherwise, if a loop has evidently less than \lstinline|AUTO| iterations, + it is completely unrolled; +\item otherwise, the \lstinline|MIN| first iterations of the loop are unrolled. +\end{itemize} + +\subsubsection{Loop unroll annotations} + +Individual loops can be unrolled by preceding them with a +\lstinline|loop unroll <n>| annotation, where \lstinline|<n>| is the number +of iterations to unroll. Such annotations must be placed just before the loop (i.e. before the \lstinline|while|, \lstinline|for| or \lstinline|do| introducing the loop), and one annotation is required per loop, including nested ones. For instance: @@ -3360,14 +3414,9 @@ Note that using an unrolling parameter which is higher than the actual number of iterations of a loop doesn't generally have an effect on the analysis. The analyzer will usually detect that further iterations are not useful. -If all loops in a program need to be unrolled, one way to do it quickly -consists in using option \lstinline|-eva-min-loop-unroll <n>|, -where \lstinline|<n>| is the number of iterations to unroll in each loop. -This option has lower precedence than \lstinline|loop unroll| annotations: -\Eva{} will always consider the latter if it is present in a loop. -This allows, for instance, to prevent unrolling of an infinite loop by -adding \lstinline|loop unroll 0| before it, while unrolling the remaining -loops by the specified amount in \lstinline|-eva-min-loop-unroll|. +Loop annotations can also be used to prevent the automatic loop unrolling +for some specific loops: adding \lstinline|loop unroll 0| before a loop +ensures that no iteration of the loop will be unrolled. \subsubsection{Unrolling via option {\em -eva-slevel}} \label{slevel} @@ -3956,6 +4005,55 @@ while (--x > 0) { cannot be analyzed precisely, because the relation between \texttt{x} and \texttt{y} is not affine. + +\subsection{Octagons} +\label{sec:octagons} + +Activating option \texttt{-eva-octagon-domain} instructs Eva to infer relations +between variables as numerical constraints of the form $l \leq \pm X \pm Y \leq +u$, where $X$ and $Y$ are program variables, and $l$ and $u$ are constants. + +These relations are then used to evaluate more precisely the possible values +of an expression involving $X$ and $Y$, or to deduce a reduction of +the possible values of $X$ from a reduction of the possible values of $Y$. + +The following code is a minimal working example that illustrates +the precision improvement provided by the octagon domain. +\begin{lstlisting} +void main (int y) { + int k = Frama_C_interval(0, 10); + int x = y + k; // x - y $\in$ [0..10] + int r = x + 3 - y; // r $\in$ [-7..3] + int t; + if (y > 15) + t = x; // t $\in$ [6..$\infty$] +} +\end{lstlisting} + + +Currently, the octagon domain is fast but has two strong limitations: +\begin{itemize} +\item + The domain only infers relations between scalar variables of integer types. + It ignores pointers, arrays and structure fields. +\item + The domain only infers relations between pairs of variables occurring in the + same instruction, as \lstinline|x = y + k;| or \lstinline|if (x < y + k)|. + If an instruction involves 3 variables or more, relations are inferred for + each pair of variables. +\end{itemize} + +The domain is intraprocedural by default: the inferred relations are local to +the current function and are lost when entering a function call or returning +to its caller. + +The option \verb+-eva-octagon-through-calls+ makes the octagon domain +interprocedural, which is a more precise but slower mode where +the inferred relations are propagated through function calls. +The analysis of a function can then use the relations inferred in the callers, +and at the end, the inferred relations are propagated back to the caller. + + \subsection{Bitwise values} \label{sec:bitwise} @@ -4184,7 +4282,7 @@ of this function. In the example below, the dependency of \lstinline|double_assign| is \lstinline|a FROM c|. The variable \lstinline|b| is not a functional input because the final value of \lstinline|a| depends only on \lstinline|c|. -\listinginput{1}{double_assign.c} +\listinginput{1}{examples/double_assign.c} The dependencies of a function may also be listed as \lstinline|NO EFFECTS|. This means that the function has no effects when it terminates. There @@ -4269,7 +4367,7 @@ are guaranteed to have been over-written when the function terminates; the latter is a by-product of the computation of operational inputs that someone may find useful someday. -\listinginput{1}{op_inputs.c} +\listinginput{1}{examples/op_inputs.c} This example, when analyzed with the options \lstinline|-inout -lib-entry -main op|, is found to have on termination the operational @@ -4357,7 +4455,7 @@ ensure that the property $P$ holds. Let us consider for instance the following function. -\listinginput{1}{reduction.c} +\listinginput{1}{examples/reduction.c} \begin{shell} frama-c -eva -eva-slevel 12 -lib-entry -main f reduction.c @@ -4393,7 +4491,7 @@ in that point of the program. This treatment often improves the precision of the analysis. It can be used with tautological assertions to provide hints to the analyzer, as shown in the following example. -\listinginput{1}{sq.c} +\listinginput{1}{examples/sq.c} \begin{shell} frama-c -eva -eva-slevel 2 sq.c @@ -4432,7 +4530,7 @@ not taken into account at all. \smallskip The two functions below illustrate both of these limitations: -\listinginput{1}{annotations_2.c} +\listinginput{1}{examples/annotations_2.c} If the analyzer is launched with options \lstinline|-lib-entry -main generalization|, @@ -4954,7 +5052,7 @@ The implementation of these functions might change in future versions of Frama-C, but their types and their behavior will stay the same. Example of use of the functions introducing non-determinism: -\listinginput{1}{nondet.c} +\listinginput{1}{examples/nondet.c} With the command below, the obtained result for variable \lstinline|X| is \lstinline|[-45..150],0%3|. @@ -5044,6 +5142,9 @@ of the domain, shown in Figure~\ref{fig:log-category}. Gauges & \lstinline|d-gauges| & \ref{sec:gauges} \tabularnewline \midrule + Octagons & \lstinline|d-octagon| & \ref{sec:octagons} + \tabularnewline + \midrule Bitwise & \lstinline|d-bitwise| & \ref{sec:bitwise} \tabularnewline \midrule @@ -5324,29 +5425,30 @@ return \lstinline|6| and \lstinline|36| respectively. \question{Which option should I use to improve the handling of loops in my program?} -The recommended way is to use \lstinline|loop unroll| annotations on a case by -case basis, which is the most precise and stable mechanism currently in \Eva{}. -Alternatively, using \lstinline|-eva-slevel| is the next best approach. -This option is more costly, often hard to predict, and can only be specified -globally or at the function level (via \lstinline|-eva-slevel-function|). -However, it works for loops that are built using \lstinline|goto|s instead of -\lstinline|for| or \lstinline|while|, and it also improves precision when -evaluating \lstinline|if| or \lstinline|switch| conditionals (but it is consumed -by them, which can be confusing for the user). - -Both approaches do have a minor drawback, in that they do not allow to observe -a specific iteration step of the loop. The main advantage of these options is -that they leave the source code unchanged. - -The Frama-C kernel has an option \lstinline|-ulevel|, which performs a -syntactic modification of the analyzed source code. Its advantage is that, -by explicitly separating iteration steps, it allows to use -the graphical user interface to observe values or express properties for a -specific iteration step of the loop. However, the duplication of loop -statements and variables can lead to cluttered code. Also, the transformation -increases the size of the code in the Frama-C AST and, for large functions, -this has a significant impact in the analysis -time. For these reasons, \lstinline|-ulevel| is seldom used nowadays. +Start with \lstinline|-eva-auto-loop-unroll|. If automatic unrolling is not +sufficient, the recommended way is to use \lstinline|loop unroll| annotations +on a case by case basis. This is the most precise and stable mechanism +currently in \Eva{}. It does have the drawback of requiring changes to the +source code, however. + +If none of the above techniques is suitable, using \lstinline|-eva-slevel| +is the next best approach. Compared to the previous ones, this option is more +costly, often hard to predict, and can only be specified globally or at the +function level (via \lstinline|-eva-slevel-function|), however it works with +loops that are built using \lstinline|goto|s instead of \lstinline|for| or +\lstinline|while|. It also improves precision when evaluating \lstinline|if| or +\lstinline|switch| conditionals (but it is consumed by them, which can be +confusing for the user). + +Finally, there is an option from the Frama-C kernel, \lstinline|-ulevel|, +which performs a syntactic modification of the analyzed source code. +Its advantage is that, by explicitly separating iteration steps, +it allows using the graphical user interface to observe values or express +properties for a specific iteration step of the loop. +However, the duplication of loop statements and variables can clutter the code. +Also, the transformation increases the size of the code in the Frama-C AST and, +for large functions, this has a significant impact in the analysis time. +For these reasons, \lstinline|-ulevel| is seldom used nowadays. \question{Alarms that occur after a true alarm in the analyzed code @@ -5357,7 +5459,7 @@ time. For these reasons, \lstinline|-ulevel| is seldom used nowadays. The answers to these questions are ``yes'' and ``yes''. Consider the following example: -\listinginput{1}{vraie_al.c} +\listinginput{1}{examples/vraie_al.c} When analyzing this example, \Eva{} does not emit an alarm on line 6. This is perfectly correct, since no error occurs at @@ -5388,7 +5490,7 @@ the case of a false alarm. Deciding whether the first alarm is a true or a false one is the responsibility of the user. This situation happens in the following example: -\listinginput{1}{false_al.c} +\listinginput{1}{examples/false_al.c} Analyzing this example with the default options produces: \begin{logs} diff --git a/doc/value/makefile b/doc/value/makefile index 674a0cc5d30670a872aa9e1219635262c8e78fe3..e7799466cb4418291ff270fac8d4dffb0086d3d9 100644 --- a/doc/value/makefile +++ b/doc/value/makefile @@ -1,5 +1,3 @@ -GENERATED=main.aux main.cb main.cb2 main.log main.out main.toc main.pdf - all: main .PHONY: main @@ -10,7 +8,7 @@ include ../MakeLaTeXModern OPENSOURCE?=yes export OPENSOURCE -main: ../../VERSION *.c +main: ../../VERSION examples/**.c $(MAKE) -C examples/parametrizing $(MAKE) $(FRAMAC_MODERN) latexmk -pdf main.tex @@ -21,7 +19,7 @@ else endif clean: - rm -f $(GENERATED) + latexmk -C -bibtex install: rm -f ../manuals/eva-manual.pdf diff --git a/doc/value/revert_preview.scpt b/doc/value/revert_preview.scpt deleted file mode 100644 index 4e7ef74055d16df432d23af15ccac2adbf239999..0000000000000000000000000000000000000000 --- a/doc/value/revert_preview.scpt +++ /dev/null @@ -1,26 +0,0 @@ - --- activate Preview - tell application "Preview" - activate - end tell - - --- Interface with the document - tell application "System Events" - tell process "Preview" - --- Select Revert from the File menu - tell menu bar 1 - tell menu bar item "File" - tell menu 1 - click menu item "Revert" - end tell - end tell - end tell - - --- Restore the original page (assumes standard toolbar layout) - --- Is there an easier way? ---- tell window 1 ---- keystroke tab & tab & tab & return ---- keystroke tab & tab & tab & tab using {shift down} ---- end tell - end tell - end tell - diff --git a/headers/close-source/JCF_LGPL b/headers/close-source/JCF_LGPL deleted file mode 100644 index 040d941d8e378f0ad4cbfa0150f65e61eefe5435..0000000000000000000000000000000000000000 --- a/headers/close-source/JCF_LGPL +++ /dev/null @@ -1,12 +0,0 @@ - -Copyright (C) Jean-Christophe Filliatre - -This software is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License version 2.1, with the special exception on linking -described in file LICENSE. - -This software is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - diff --git a/headers/header_spec.txt b/headers/header_spec.txt index 338db1fb14a0050bfabd25fd5ae64b9801c34c6c..3a00fb89591cebef116a40d4612856c551d31075 100644 --- a/headers/header_spec.txt +++ b/headers/header_spec.txt @@ -102,10 +102,8 @@ headers/open-source/UNMODIFIED_WHY3: .ignore headers/updates-headers.sh: CEA_PROPRIETARY lib/plugins/PLUGINS.README: .ignore licenses/CDDL-1.0: .ignore -licenses/GPLv3: .ignore licenses/LGPLv2: .ignore licenses/LGPLv2.1: .ignore -licenses/LGPLv3: .ignore licenses/Q_MODIFIED_LICENSE: .ignore man/frama-c.1: CEA_LGPL opam/descr: .ignore @@ -151,7 +149,6 @@ share/Makefile.dynamic_config.internal: CEA_LGPL share/Makefile.generic: CEA_LGPL share/Makefile.plugin.template: CEA_LGPL share/META.frama-c: .ignore -share/builtin.h: CEA_LGPL share/configure.ac: CEA_LGPL share/emacs/acsl.el: ACSL_EL share/emacs/frama-c-dev.el: CEA_LGPL @@ -671,8 +668,6 @@ src/libraries/utils/hptset.ml: CEA_LGPL src/libraries/utils/hptset.mli: CEA_LGPL src/libraries/utils/indexer.ml: CEA_LGPL src/libraries/utils/indexer.mli: CEA_LGPL -src/libraries/utils/leftistheap.ml: JCF_LGPL -src/libraries/utils/leftistheap.mli: JCF_LGPL src/libraries/utils/markdown.ml: CEA_LGPL src/libraries/utils/markdown.mli: CEA_LGPL src/libraries/utils/pretty_utils.ml: CEA_LGPL @@ -1136,10 +1131,8 @@ src/plugins/value/domains/abstract_domain.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/printer_domain.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/printer_domain.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/simpler_domains.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/domains/apron/apron_domain.ko.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/apron/apron_domain.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/apron/apron_domain.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/domains/apron/apron_domain.ok.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/cvalue/builtins.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/cvalue/builtins.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/cvalue/builtins_float.ml: CEA_LGPL_OR_PROPRIETARY @@ -1192,6 +1185,8 @@ src/plugins/value/domains/hcexprs.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/hcexprs.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/inout_domain.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/inout_domain.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/domains/octagons.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/domains/octagons.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/offsm_domain.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/offsm_domain.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/powerset.ml: CEA_LGPL_OR_PROPRIETARY @@ -1199,8 +1194,6 @@ src/plugins/value/domains/powerset.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/sign_domain.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/sign_domain.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/numerors/numerors_domain.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/domains/numerors/numerors_domain.ok.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/domains/numerors/numerors_domain.ko.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/numerors/numerors_domain.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/simple_memory.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/domains/simple_memory.mli: CEA_LGPL_OR_PROPRIETARY @@ -1222,21 +1215,10 @@ src/plugins/value/engine/iterator.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/iterator.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/mem_exec.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/mem_exec.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/partition.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/partition.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/partitioning_index.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/partitioning_index.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/partitioning_parameters.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/partitioning_parameters.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/recursion.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/recursion.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/split_return.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/split_return.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/state_partitioning.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/subdivided_evaluation.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/subdivided_evaluation.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/trace_partitioning.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/engine/trace_partitioning.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/transfer_logic.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/transfer_logic.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/engine/transfer_specification.ml: CEA_LGPL_OR_PROPRIETARY @@ -1267,10 +1249,22 @@ src/plugins/value/legacy/function_args.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/legacy/function_args.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/register.ml: CEA_LGPL_OR_PROPRIETARY src/plugins/value/register.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/slevel/per_stmt_slevel.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/slevel/per_stmt_slevel.mli: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/slevel/split_strategy.ml: CEA_LGPL_OR_PROPRIETARY -src/plugins/value/slevel/split_strategy.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/auto_loop_unroll.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/auto_loop_unroll.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/partition.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/partition.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/partitioning_index.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/partitioning_index.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/partitioning_parameters.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/partitioning_parameters.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/per_stmt_slevel.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/per_stmt_slevel.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/split_return.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/split_return.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/split_strategy.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/split_strategy.mli: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/trace_partitioning.ml: CEA_LGPL_OR_PROPRIETARY +src/plugins/value/partitioning/trace_partitioning.mli: CEA_LGPL_OR_PROPRIETARY src/plugins/value/test.assert.sh: .ignore src/plugins/value/test.sh: .ignore src/plugins/value/utils/abstract.ml: CEA_LGPL_OR_PROPRIETARY diff --git a/headers/open-source/JCF_LGPL b/headers/open-source/JCF_LGPL deleted file mode 100644 index 169d635765b4441a4a98ee28a3c4c7b8e9e39c7e..0000000000000000000000000000000000000000 --- a/headers/open-source/JCF_LGPL +++ /dev/null @@ -1,15 +0,0 @@ - -Copyright (C) Jean-Christophe Filliatre - -This software is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License version 2.1, with the special exception on linking -described in file LICENSE. - -This software is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -File modified by CEA (Commissariat à l'énergie atomique et aux - énergies alternatives). - diff --git a/licenses/GPLv3 b/licenses/GPLv3 deleted file mode 100644 index 94a9ed024d3859793618152ea559a168bbcbb5e2..0000000000000000000000000000000000000000 --- a/licenses/GPLv3 +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - <program> Copyright (C) <year> <name of author> - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -<http://www.gnu.org/licenses/>. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/licenses/LGPLv3 b/licenses/LGPLv3 deleted file mode 100644 index fc8a5de7edf437cdc98a216370faf7c757279bcb..0000000000000000000000000000000000000000 --- a/licenses/LGPLv3 +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/share/analysis-scripts/make_template.py b/share/analysis-scripts/make_template.py index ca241cc8f0ebf660365c6369a52385506d19bd24..94a6a8fe3ca393515bdaf624ea4ee6f4a10a9905 100755 --- a/share/analysis-scripts/make_template.py +++ b/share/analysis-scripts/make_template.py @@ -73,7 +73,7 @@ def get_known_machdeps(): match = re.match("\[kernel\] supported machines are (.*) \(default is (.*)\).", output, re.DOTALL) if not match: print("error getting known machdeps: " + output) - sys.exit() + sys.exit(1) machdeps = match.group(1).split() default_machdep = match.group(2) return (default_machdep, machdeps) diff --git a/share/configure.ac b/share/configure.ac index 1ea8d54d0ee906608bb404a4eaa5e4d11a9210e9..85a700fb52d3420893e0313b35574bd5ca3a9c2e 100644 --- a/share/configure.ac +++ b/share/configure.ac @@ -212,6 +212,74 @@ m4_define([configure_library], ]) ]) +# 1st param: actual name of the ocamlfind package (often lowercase) +# 2nd param: warning to display if problem +m4_define([configure_pkg], +[ +define([PKG_UP],[tovarname($1)]) +m4_ifdef([HAS_OCAML_]PKG_UP,, + [ + define([VAR],[[OCAML_]PKG_UP]) + define([require],[$[REQUIRE_OCAML_]PKG_UP]) + define([use],[$[USE_OCAML_]PKG_UP]) + define([msg],[$2]) + define([has],[[HAS_OCAML_]PKG_UP]) + + has= + AC_MSG_CHECKING(for OCaml package $1) + VAR=$(ocamlfind query $1 -format %v 2>/dev/null) + if test -z "$VAR" ; then + AC_MSG_RESULT(not found via ocamlfind.) + has=no + else + AC_MSG_RESULT(found.) + has=yes + fi + m4_divert_push(frama_c_configure_tool) + if test -n "require" -o -n "use" -o "$force_check" = "yes"; then + if test "$has" = "no"; then + AC_MSG_WARN([msg]) + reason="$1 missing" + for p in require; do + up=`upper "$p"` + ep=ENABLE_$up + eval enable_p=\$$ep + if test "$enable_p" != "no"; then + fp=FORCE_`upper "$p"` + if eval test "\$$fp" = "yes"; then + AC_MSG_ERROR([$p requested but $reason.]) + fi + eval $ep="no\ \(see\ warning\ about\ $1\)" + AC_MSG_WARN([$p disabled because $reason.]) + eval INFO_$up=\", $reason\" + fi + done + for p in use; do + up=`upper "$p"` + ep=ENABLE_$up + eval eep="\$$ep" + if test "`echo $eep | sed -e 's/ .*//' `" != "no"; then + eval $ep="partial\ \(see\ warning\ about\ $1\)" + AC_MSG_WARN([$p partially enabled because $reason.]) + eval INFO_$up=\", $reason\" + fi + done + else + VAR=PKG_UP + fi + fi + m4_divert_pop(frama_c_configure_tool) + AC_SUBST(VAR) + AC_SUBST(has) + undefine([PKG_UP]) + undefine([VAR]) + undefine([require]) + undefine([use]) + undefine([msg]) + undefine([has]) +]) +]) + # 1st param: uppercase name of the program # 2nd param: program which must exist. See comment on configure_library() # on how to deal with multiple choices for a given program. @@ -280,6 +348,7 @@ AC_CHECK_PROG(has,$file,yes,no) ]) ]) + EXTERNAL_PLUGINS= define([plugin_require_external], @@ -296,6 +365,20 @@ define([plugin_use_external], m4_undefine([USE]) m4_undefine([UPORIG])]) +define([plugin_require_pkg], + [m4_define([UPORIG],[OCAML_]tovarname($2)) + m4_define([REQUIRE],[REQUIRE_]UPORIG) + REQUIRE=$REQUIRE" "$1 + m4_undefine([REQUIRE]) + m4_undefine([UPORIG])]) + +define([plugin_use_pkg], + [m4_define([UPORIG],[OCAML_]tovarname($2)) + m4_define([USE],[USE_]UPORIG) + USE=$USE" "$1 + m4_undefine([USE]) + m4_undefine([UPORIG])]) + define([plugin_require], [m4_define([UPTARGET],tovarname($1)) m4_define([UPORIG],tovarname($2)) diff --git a/share/libc/__fc_machdep.h b/share/libc/__fc_machdep.h index f6f2d7e9a6d71c73f7cc7a786e0f77a6190bce45..55db3e0093ebd50630f313f57cb9a533a9646d1b 100644 --- a/share/libc/__fc_machdep.h +++ b/share/libc/__fc_machdep.h @@ -99,6 +99,10 @@ /* POSIX */ #define __SSIZE_T int #define __SSIZE_MAX __FC_INT_MAX +/* stdio.h */ +#ifndef __FC_L_tmpnam +#define __FC_L_tmpnam 1024 +#endif /* stdint.h */ #define __FC_PTRDIFF_MIN __FC_INT_MIN #define __FC_PTRDIFF_MAX __FC_INT_MAX @@ -195,6 +199,10 @@ /* POSIX */ #define __SSIZE_T signed long #define __SSIZE_MAX __FC_LONG_MAX +/* stdio.h */ +#ifndef __FC_L_tmpnam +#define __FC_L_tmpnam 1024 +#endif /* stdint.h */ #define __FC_PTRDIFF_MIN __FC_LONG_MIN #define __FC_PTRDIFF_MAX __FC_LONG_MAX @@ -293,6 +301,10 @@ /* POSIX */ #define __SSIZE_T signed long #define __SSIZE_MAX __FC_LONG_MAX +/* stdio.h */ +#ifndef __FC_L_tmpnam +#define __FC_L_tmpnam 1024 +#endif /* stdint.h */ #define __FC_PTRDIFF_MIN __FC_LONG_MIN #define __FC_PTRDIFF_MAX __FC_LONG_MAX @@ -388,6 +400,10 @@ /* POSIX */ #define __SSIZE_T int #define __SSIZE_MAX __FC_INT_MAX +/* stdio.h */ +#ifndef __FC_L_tmpnam +#define __FC_L_tmpnam 1024 +#endif /* stdint.h */ #define __FC_PTRDIFF_MIN __FC_INT_MIN #define __FC_PTRDIFF_MAX __FC_INT_MAX @@ -558,6 +574,10 @@ /* POSIX */ #define __SSIZE_T signed long long +/* stdio.h */ +#ifndef __FC_L_tmpnam +#define __FC_L_tmpnam 20 +#endif /* stdint.h */ #define __FC_WCHAR_MIN 0 #define __FC_WCHAR_MAX __FC_USHRT_MAX diff --git a/share/libc/__fc_string_axiomatic.h b/share/libc/__fc_string_axiomatic.h index a89a527466eacc4412932d441b23dbfbb3817c69..efd4b09bc698630ed51de4c0ae6bdece653e5e11 100644 --- a/share/libc/__fc_string_axiomatic.h +++ b/share/libc/__fc_string_axiomatic.h @@ -171,6 +171,21 @@ __BEGIN_DECLS @ } @*/ +/*@ axiomatic WMemChr { + @ logic 𔹠wmemchr{L}(wchar_t *s, wchar_t c, ℤ n) + @ reads s[0..n - 1]; + @ // Returns [true] iff wide char array [s] contains wide character [c] + @ + @ logic ℤ wmemchr_off{L}(wchar_t *s, wchar_t c, ℤ n) + @ reads s[0..n - 1]; + @ // Returns the offset at which [c] appears in [s]. + @ + @ axiom wmemchr_def{L}: + @ \forall wchar_t *s; \forall wchar_t c; \forall ℤ n; + @ wmemchr(s,c,n) <==> \exists int i; 0 <= i < n && s[i] == c; + @ } + @*/ + /*@ axiomatic WcsLen { @ logic ℤ wcslen{L}(wchar_t *s) @ reads s[0..]; diff --git a/share/libc/math.h b/share/libc/math.h index ff121459534bd3d364ed3040fdf1fd591e60cf11..e8b81c90b83c350b1c1b52aa643198aab7e41c8f 100644 --- a/share/libc/math.h +++ b/share/libc/math.h @@ -37,10 +37,6 @@ typedef double double_t; #define MATH_ERRNO 1 #define MATH_ERREXCEPT 2 -#define HUGE_VAL 0x1.0p2047 -#define HUGE_VALF 0x1.0p255f -#define HUGE_VALL 0x1.0p32767L - /* The constants below are not part of C99/C11 but they are defined in POSIX */ #define M_E 0x1.5bf0a8b145769p1 /* e */ #define M_LOG2E 0x1.71547652b82fep0 /* log_2 e */ @@ -755,6 +751,37 @@ extern int __finite(double d); # define isfinite(x) \ (sizeof (x) == sizeof (float) ? __finitef (x) : __finite (x)) +//The (integer x) argument is just here because a function without argument is +//applied differently in ACSL and C + +/*@ + + logic float __fc_infinity(integer x) = \plus_infinity; + logic float __fc_nan(integer x) = \NaN; + + @*/ + +/*@ + ensures result_is_infinity: \is_plus_infinity(\result); + assigns \result \from \nothing; + @*/ +extern const float __fc_infinity(int x); + +/*@ + ensures result_is_nan: \is_NaN(\result); + assigns \result \from \nothing; + @*/ +extern const float __fc_nan(int x); + + +#define INFINITY __fc_infinity(0) +#define NAN __fc_nan(0) + +#define HUGE_VALF INFINITY +#define HUGE_VAL ((double)INFINITY) +#define HUGE_VALL ((long double)INFINITY) + + __END_DECLS __POP_FC_STDLIB diff --git a/share/libc/stdio.h b/share/libc/stdio.h index 9c27119c016ce7fced52dde77b279b8f1db2630b..b571cce1e3e1386dc938692203cfff6d8edc9787 100644 --- a/share/libc/stdio.h +++ b/share/libc/stdio.h @@ -44,6 +44,9 @@ __PUSH_FC_STDLIB #define BUFSIZ __FC_BUFSIZ #define FOPEN_MAX __FC_FOPEN_MAX #define FILENAME_MAX __FC_FILENAME_MAX +#ifndef __FC_L_tmpnam +#error machdep should have defined __FC_L_tmpnam! +#endif #define L_tmpnam __FC_L_tmpnam #include "__fc_define_seek_macros.h" @@ -67,10 +70,22 @@ extern FILE * __fc_stdout; non-interferent between them. */ -/*@ assigns \nothing; */ +/*@ // missing: assigns 'filesystem' \from filename[0..]; + // missing: assigns errno one of several possible values + requires valid_filename: valid_read_string(filename); + assigns \result \from indirect:filename[0..strlen(filename)]; + ensures result_ok_or_error: \result == 0 || \result == -1; +*/ extern int remove(const char *filename); -/*@ assigns \nothing; */ +/*@ // missing: assigns 'filesystem' \from old_name[0..], new_name[0..]; + // missing: assigns errno one of 21 different possible values + requires valid_old_name: valid_read_string(old_name); + requires valid_new_name: valid_read_string(new_name); + assigns \result \from indirect:old_name[0..strlen(old_name)], + indirect:new_name[0..strlen(new_name)]; + ensures result_ok_or_error: \result == 0 || \result == -1; +*/ extern int rename(const char *old_name, const char *new_name); FILE __fc_fopen[__FC_FOPEN_MAX]; @@ -83,33 +98,59 @@ FILE* const __fc_p_fopen = __fc_fopen; */ extern FILE *tmpfile(void); +char __fc_tmpnam[L_tmpnam]; +char * const __fc_p_tmpnam = __fc_tmpnam; + /*@ - assigns \result \from s[..]; - assigns s[..] \from \nothing; - // TODO: more precise behaviors from ISO C 7.19.4.4 + // Note: the tmpnam example in POSIX uses an array of size L_tmpnam+1 + // missing: assigns __fc_p_tmpnam[0..L_tmpnam] \from 'PRNG and internal state' + // missing: if called more than TMP_MAX, behavior is implementation-defined + requires valid_s_or_null: s == \null || \valid(s+(0 .. L_tmpnam)); + assigns __fc_p_tmpnam[0 .. L_tmpnam] \from __fc_p_tmpnam[0 .. L_tmpnam], + indirect:s; + assigns s[0 .. L_tmpnam] \from indirect:s, __fc_p_tmpnam[0 .. L_tmpnam]; + assigns \result \from s, __fc_p_tmpnam; + ensures result_string_or_null: \result == \null || \result == s || + \result == __fc_p_tmpnam; */ extern char *tmpnam(char *s); /*@ + // missing: assigns errno requires valid_stream: \valid(stream); - assigns \result \from stream, stream->__fc_FILE_id; + assigns \result \from indirect:stream, indirect:*stream; ensures result_zero_or_EOF: \result == 0 || \result == EOF; - // TODO: more precise behaviors from ISO C 7.19.4.1 */ extern int fclose(FILE *stream); /*@ + // missing: assigns errno requires null_or_valid_stream: stream == \null || \valid_read(stream); - assigns \result \from stream, stream->__fc_FILE_id; ensures result_zero_or_EOF: \result == 0 || \result == EOF; - // TODO: more precise behaviors from ISO C 7.19.5.2 + assigns \result + \from indirect:*stream, indirect:__fc_fopen[0 .. __FC_FOPEN_MAX-1]; + assigns *stream, __fc_fopen[0 .. __FC_FOPEN_MAX-1] + \from indirect:stream, *stream, + __fc_fopen[0 .. __FC_FOPEN_MAX-1]; // may flush ALL open streams + behavior flush_all: + assumes all_streams: stream == \null; + assigns __fc_fopen[0 .. __FC_FOPEN_MAX-1] + \from __fc_fopen[0 .. __FC_FOPEN_MAX-1]; // flush ALL open streams + assigns \result \from indirect:__fc_fopen[0 .. __FC_FOPEN_MAX-1]; + behavior flush_stream: + assumes single_stream: stream != \null; + assigns *stream \from *stream; + assigns \result \from indirect:*stream; + complete behaviors; + disjoint behaviors; */ extern int fflush(FILE *stream); /*@ requires valid_filename: valid_read_string(filename); requires valid_mode: valid_read_string(mode); - assigns \result \from indirect:filename[..], indirect:mode[..], __fc_p_fopen; + assigns \result \from indirect:filename[0..strlen(filename)], + indirect:mode[0..strlen(mode)], __fc_p_fopen; ensures result_null_or_valid_fd: \result==\null || (\subset(\result,&__fc_fopen[0 .. __FC_FOPEN_MAX-1])) ; */ @@ -118,8 +159,9 @@ extern FILE *fopen(const char * restrict filename, /*@ requires valid_mode: valid_read_string(mode); - assigns \result, __fc_fopen[fd] \from indirect:fd, indirect:mode[0..], - indirect:__fc_fopen[fd], __fc_p_fopen; + assigns \result, __fc_fopen[fd] \from indirect:fd, + indirect:mode[0..strlen(mode)], + indirect:__fc_fopen[fd], __fc_p_fopen; ensures result_null_or_valid_fd: \result == \null || (\subset(\result,&__fc_fopen[0 .. __FC_FOPEN_MAX-1])) ; */ @@ -222,55 +264,97 @@ extern int fgetc(FILE *stream); /*@ requires valid_stream: \valid(stream); - assigns s[0..size] \from indirect:size, indirect:*stream; + requires room_s: \valid(s+(0..size-1)); + assigns s[0..size-1] \from indirect:size, indirect:*stream; assigns \result \from s, indirect:size, indirect:*stream; ensures result_null_or_same: \result == \null || \result == s; + ensures initialization:at_least_one:\result != \null ==> \initialized(&s[0]); + // the return value does not tell how many characters were written, + // so we can only ensure the first one was initialized ensures terminated_string_on_success: \result != \null ==> valid_string(s); */ extern char *fgets(char * restrict s, int size, FILE * restrict stream); -/*@ assigns *stream ; */ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from c, *stream; + assigns \result \from indirect:*stream; +*/ extern int fputc(int c, FILE *stream); -/*@ assigns *stream \from s[..]; */ +/*@ + requires valid_string_s: valid_read_string(s); + assigns *stream \from s[0..strlen(s)], *stream; + assigns \result \from indirect:s[0..strlen(s)], indirect:*stream; +*/ extern int fputs(const char * restrict s, FILE * restrict stream); -/*@ assigns \result,*stream \from *stream; */ +/*@ + requires valid_stream: \valid(stream); + assigns \result, *stream \from *stream; +*/ extern int getc(FILE *stream); -/*@ assigns \result \from *__fc_stdin ; */ +/*@ + assigns \result, *__fc_stdin \from *__fc_stdin; +*/ extern int getchar(void); +// Number of characters that will read by gets() +/*@ + axiomatic GetsLength { + logic size_t gets_length{L} reads *__fc_stdin; + } +*/ + /*@ - assigns s[..] \from *__fc_stdin ; - assigns \result \from s, __fc_stdin; + requires room_s: \valid(s+(0..gets_length)); + assigns s[0..gets_length] \from *__fc_stdin ; + assigns \result \from s, *__fc_stdin; + assigns *__fc_stdin \from *__fc_stdin; ensures result_null_or_same: \result == s || \result == \null; */ extern char *gets(char *s); -/*@ assigns *stream \from c; */ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from c, *stream; + assigns \result \from indirect:*stream; +*/ extern int putc(int c, FILE *stream); -/*@ assigns *__fc_stdout \from c; */ +/*@ + assigns *__fc_stdout \from c, *__fc_stdout; + assigns \result \from indirect:*__fc_stdout; +*/ extern int putchar(int c); -/*@ assigns *__fc_stdout \from s[..]; */ +/*@ + requires valid_string_s: valid_read_string(s); + assigns *__fc_stdout \from s[0..strlen(s)], *__fc_stdout; + assigns \result \from indirect:s[0..strlen(s)], indirect:*__fc_stdout; +*/ extern int puts(const char *s); -/*@ assigns *stream \from c; */ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from indirect:c; + assigns \result \from indirect:c, indirect:*stream; + ensures result_ok_or_error: \result == c || \result == EOF; +*/ extern int ungetc(int c, FILE *stream); /*@ requires valid_ptr_block: \valid(((char*)ptr)+(0..(nmemb*size)-1)); requires valid_stream: \valid(stream); - assigns *(((char*)ptr)+(0..(nmemb*size)-1)) \from size, nmemb, *stream; - assigns \result \from size, *stream; + assigns *(((char*)ptr)+(0..(nmemb*size)-1)), *stream + \from indirect:size, indirect:nmemb, indirect:*stream; + assigns \result \from size, indirect:*stream; ensures size_read: \result <= nmemb; ensures initialization: \initialized(((char*)ptr)+(0..(\result*size)-1)); - //TODO: specify precise fields from struct FILE */ extern size_t fread(void * restrict ptr, size_t size, size_t nmemb, @@ -279,15 +363,20 @@ extern size_t fread(void * restrict ptr, /*@ requires valid_ptr_block: \valid_read(((char*)ptr)+(0..(nmemb*size)-1)); requires valid_stream: \valid(stream); - assigns *stream, \result \from *(((char*)ptr)+(0..(nmemb*size)-1)); + assigns *stream, \result \from indirect:*(((char*)ptr)+(0..(nmemb*size)-1)); ensures size_written: \result <= nmemb; - //TODO: specify precise fields from struct FILE */ extern size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb, FILE * restrict stream); -/*@ assigns *pos \from *stream ; */ +/*@ + requires valid_stream: \valid(stream); + requires valid_pos: \valid(pos); + requires initialization:pos: \initialized(pos); + assigns *pos \from indirect:*stream; + assigns \result \from indirect:*stream; + */ extern int fgetpos(FILE * restrict stream, fpos_t * restrict pos); @@ -300,7 +389,12 @@ extern int fgetpos(FILE * restrict stream, */ extern int fseek(FILE *stream, long int offset, int whence); -/*@ assigns *stream \from *pos; */ +/*@ + requires valid_stream: \valid(stream); + requires valid_pos: \valid_read(pos); + requires initialization:pos: \initialized(pos); + assigns *stream \from *pos; +*/ extern int fsetpos(FILE *stream, const fpos_t *pos); /*@ @@ -311,50 +405,108 @@ extern int fsetpos(FILE *stream, const fpos_t *pos); */ extern long int ftell(FILE *stream); -/*@ assigns *stream \from \nothing; */ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from \nothing; + */ extern void rewind(FILE *stream); -/*@ assigns *stream \from \nothing; */ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from \nothing; + */ extern void clearerr(FILE *stream); -/*@ assigns \result \from *stream ;*/ +/*@ + requires valid_stream: \valid(stream); + assigns \result \from indirect:*stream; +*/ extern int feof(FILE *stream); -/*@ assigns \result \from *stream ;*/ +/*@ + requires valid_stream: \valid(stream); + assigns \result \from indirect:*stream; +*/ extern int fileno(FILE *stream); -/*@ assigns *stream \from \nothing ;*/ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from \nothing; +*/ extern void flockfile(FILE *stream); -/*@ assigns *stream \from \nothing ;*/ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from \nothing; +*/ extern void funlockfile(FILE *stream); -/*@ assigns \result,*stream \from \nothing ;*/ +/*@ + requires valid_stream: \valid(stream); + assigns \result,*stream \from \nothing; +*/ extern int ftrylockfile(FILE *stream); -/*@ assigns \result \from *stream ;*/ +/*@ + requires valid_stream: \valid(stream); + assigns \result \from indirect:*stream; +*/ extern int ferror(FILE *stream); -/*@ assigns __fc_stdout \from __fc_errno, s[..]; */ +/*@ + requires valid_string_s: valid_read_string(s); + assigns __fc_stdout \from __fc_errno, s[0..strlen(s)]; + */ extern void perror(const char *s); -/*@ assigns \result,*stream \from *stream; */ +/*@ + requires valid_stream: \valid(stream); + assigns \result,*stream \from *stream; +*/ extern int getc_unlocked(FILE *stream); -/*@ assigns \result \from *__fc_stdin ; */ + +/*@ + assigns \result \from *__fc_stdin; + */ extern int getchar_unlocked(void); -/*@ assigns *stream \from c; */ + +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from c; + assigns \result \from indirect:*stream; +*/ extern int putc_unlocked(int c, FILE *stream); -/*@ assigns *__fc_stdout \from c; */ + +/*@ + assigns *__fc_stdout \from c; + assigns \result \from indirect:*__fc_stdout; + */ extern int putchar_unlocked(int c); -/*@ assigns *stream \from \nothing; */ +/*@ + requires valid_stream: \valid(stream); + assigns *stream \from \nothing; +*/ extern void clearerr_unlocked(FILE *stream); -/*@ assigns \result \from *stream ;*/ + +/*@ + requires valid_stream: \valid(stream); + assigns \result \from indirect:*stream; +*/ extern int feof_unlocked(FILE *stream); -/*@ assigns \result \from *stream ;*/ + +/*@ + requires valid_stream: \valid(stream); + assigns \result \from indirect:*stream; +*/ extern int ferror_unlocked(FILE *stream); -/*@ assigns \result \from *stream ;*/ + +/*@ + requires valid_stream: \valid(stream); + assigns \result \from indirect:*stream; +*/ extern int fileno_unlocked(FILE *stream); + extern int fflush_unlocked(FILE *stream); extern int fgetc_unlocked(FILE *stream); extern int fputc_unlocked(int c, FILE *stream); diff --git a/share/libc/sys/resource.h b/share/libc/sys/resource.h index 566a0fa31e89d69517d1abc749a81056d01f6c07..bcb311cb3768d2207524d2a27044ed02e2196fd7 100644 --- a/share/libc/sys/resource.h +++ b/share/libc/sys/resource.h @@ -65,21 +65,27 @@ extern int getpriority(int which, id_t who); /*@ assigns \result \from which,who,prio; */ extern int setpriority(int which, id_t who, int prio); -/*@ assigns \result \from r; - @ assigns rl->rlim_cur \from r; - @ assigns rl->rlim_max \from r; +/*@ + requires valid_rlp: \valid(rlp); + assigns \result, *rlp \from resource; */ -extern int getrlimit(int r, struct rlimit *rl); +extern int getrlimit(int resource, struct rlimit *rlp); -/*@ assigns \result \from r; - @ assigns ru->ru_utime \from r; - @ assigns ru->ru_stime \from r; +/*@ + requires valid_r_usage: \valid(r_usage); + assigns *r_usage \from who; + assigns \result \from indirect:who; + ensures result_ok_or_error: \result == 0 || \result == -1; */ -extern int getrusage(int r, struct rusage *ru); +extern int getrusage(int who, struct rusage *r_usage); -/*@ assigns \result \from r,rl->rlim_cur,rl->rlim_max; +/*@ + requires valid_rlp: \valid_read(rlp); + assigns *rlp \from resource; + assigns \result \from indirect:resource, indirect:*rlp; + ensures result_ok_or_error: \result == 0 || \result == -1; */ -extern int setrlimit(int r, const struct rlimit * rl); +extern int setrlimit(int resource, const struct rlimit *rlp); __END_DECLS __POP_FC_STDLIB diff --git a/share/libc/sys/time.h b/share/libc/sys/time.h index 426f637688704543ab931b8ea5d48424d621bdaf..afeb1fb4af0c87f6b6dd097c375672b22c38bb90 100644 --- a/share/libc/sys/time.h +++ b/share/libc/sys/time.h @@ -30,6 +30,7 @@ __BEGIN_DECLS #include "../__fc_define_suseconds_t.h" #include "../__fc_define_fd_set_t.h" #include "../__fc_define_timespec.h" +#include "../__fc_string_axiomatic.h" struct timeval { time_t tv_sec; suseconds_t tv_usec; @@ -44,7 +45,12 @@ struct timezone { //@ ghost volatile unsigned int __fc_time __attribute__((FRAMA_C_MODEL)); //@ ghost extern int __fc_tz __attribute__((FRAMA_C_MODEL)); -/*@ assigns \result \from path[0..],times[0..1]; */ +/*@ + requires valid_path: valid_read_string(path); + requires valid_times_or_null: \valid_read(times+(0..1)) || times == \null; + assigns \result \from indirect:path[0..strlen(path)], + indirect:times, indirect:times[0..1]; +*/ extern int utimes(const char *path, const struct timeval times[2]); /*@ assigns tv->tv_sec, tv->tv_usec \from __fc_time; @@ -83,10 +89,14 @@ extern int utimes(const char *path, const struct timeval times[2]); @*/ extern int gettimeofday(struct timeval * restrict tv, void * restrict tz); -/*@ assigns \result,__fc_time,__fc_tz - @ \from tv->tv_sec, tv->tv_usec, - @ tz->tz_dsttime, tz->tz_minuteswest; - @*/ +/*@ + requires valid_tv_or_null: \valid_read(tv) || tv == \null; + requires valid_tz_or_null: \valid_read(tz) || tz == \null; + assigns __fc_time, __fc_tz \from tv->tv_sec, tv->tv_usec, + tz->tz_dsttime, tz->tz_minuteswest; + assigns \result \from indirect:*tv, indirect:*tz; + ensures result_ok_or_error: \result == 0 || \result == -1; +*/ extern int settimeofday(const struct timeval *tv, const struct timezone *tz); #if (defined _POSIX_C_SOURCE && (_POSIX_C_SOURCE) >= 200112L) || \ diff --git a/share/libc/time.h b/share/libc/time.h index 52c66700cc80c3df73b708b8f6a302a30b2d6877..f0de06cabd85307aa0dad4d05dd7122bae3dc630 100644 --- a/share/libc/time.h +++ b/share/libc/time.h @@ -86,7 +86,11 @@ extern clock_t clock(void); /*@ assigns \result \from time1, time0; */ extern double difftime(time_t time1, time_t time0); -/*@ assigns *timeptr, \result \from *timeptr; */ +/*@ + requires valid_timeptr: \valid(timeptr); + assigns *timeptr \from *timeptr; + assigns \result \from indirect:*timeptr; + */ extern time_t mktime(struct tm *timeptr); /*@ @@ -122,14 +126,18 @@ extern char *ctime(const time_t *timer); struct tm __fc_time_tm; struct tm * const __fc_p_time_tm = &__fc_time_tm; -/*@ assigns \result \from __fc_p_time_tm; +/*@ + requires valid_timer: \valid_read(timer); + assigns \result \from __fc_p_time_tm; assigns __fc_time_tm \from *timer; ensures result_null_or_internal_tm: \result == &__fc_time_tm || \result == \null ; */ extern struct tm *gmtime(const time_t *timer); -/*@ assigns \result \from __fc_p_time_tm; +/*@ + requires valid_timer: \valid_read(timer); + assigns \result \from __fc_p_time_tm; assigns __fc_time_tm \from *timer; ensures result_null_or_internal_tm: \result == &__fc_time_tm || \result == \null; @@ -290,7 +298,6 @@ extern int timer_getoverrun(timer_t); extern int timer_gettime(timer_t, struct itimerspec *); extern int timer_settime(timer_t, int, const struct itimerspec *restrict, struct itimerspec *restrict); -extern void tzset(void); extern int daylight; extern long timezone; diff --git a/share/libc/unistd.h b/share/libc/unistd.h index 4a8a0455ceb36a581255d0a30a29e4f94a198aba..799cb03c7bdddae9766726300f8c301453cbd31c 100644 --- a/share/libc/unistd.h +++ b/share/libc/unistd.h @@ -985,6 +985,7 @@ extern long pathconf(char const *path, int name); extern int pause(void); /*@ + requires valid_pipefd: \valid(pipefd+(0..1)); assigns pipefd[0..1] \from indirect:__fc_fds[0..]; assigns \result \from indirect:__fc_fds[0..]; ensures initialization:pipefd: \initialized(&pipefd[0..1]); @@ -1100,6 +1101,7 @@ volatile char *__fc_p_ttyname = __fc_ttyname; /*@ // missing: may assign to errno: EBADF, ENOTTY + requires valid_fildes: 0 <= fildes < __FC_MAX_OPEN_FILES; assigns \result \from __fc_p_ttyname, indirect:fildes; ensures result_name_or_null: \result == __fc_p_ttyname || \result == \null; */ diff --git a/share/libc/wchar.h b/share/libc/wchar.h index ff7e863ad8de1e7b5cf5c657bfe7f17d873ceadd..fb07265633362a1736cde59aac0f3f83d1bf365d 100644 --- a/share/libc/wchar.h +++ b/share/libc/wchar.h @@ -41,6 +41,8 @@ __PUSH_FC_STDLIB // ISO C requires the tag 'struct tm' (as declared in <time.h>) to be declared. #include "time.h" +#include "string.h" + __BEGIN_DECLS #ifndef WEOF @@ -48,16 +50,35 @@ __BEGIN_DECLS #endif /*@ + requires valid: + valid_read_or_empty((char*)s, (size_t)(sizeof(wchar_t)*n)) + || \valid_read(((unsigned char*)s)+(0..wmemchr_off(s,c,n))); + @ requires initialization: + \initialized(s+(0..n - 1)) + || \initialized(s+(0..wmemchr_off(s,c,n))); + @ requires danglingness: + non_escaping(s, (size_t)(sizeof(wchar_t)*n)) + || non_escaping(s, (size_t)(sizeof(wchar_t)*(wmemchr_off(s,c,n)+1))); assigns \result \from s, indirect:s[0 .. n-1], indirect:c, indirect:n; ensures result_null_or_inside_s: \result == \null || \subset (\result, s+(0 .. n-1)); */ extern wchar_t * wmemchr(const wchar_t *s, wchar_t c, size_t n); -/*@ assigns \result \from indirect:s1[0 .. n-1], indirect:s2[0 .. n-1], indirect:n; */ +/*@ + requires valid_s1: valid_read_or_empty(s1, (size_t)(sizeof(wchar_t)*n)); + requires valid_s2: valid_read_or_empty(s2, (size_t)(sizeof(wchar_t)*n)); + requires initialization:s1: \initialized(s1+(0..n-1)); + requires initialization:s2: \initialized(s2+(0..n-1)); + requires danglingness:s1: non_escaping(s1, (size_t)(sizeof(wchar_t)*n)); + requires danglingness:s2: non_escaping(s2, (size_t)(sizeof(wchar_t)*n)); + assigns \result \from indirect:s1[0 .. n-1], indirect:s2[0 .. n-1], indirect:n; +*/ extern int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n); /*@ + requires valid_dest: valid_or_empty(dest, (size_t)(sizeof(wchar_t)*n)); + requires valid_src: valid_read_or_empty(src, (size_t)(sizeof(wchar_t)*n)); requires separation:dest:src: \separated(dest+(0 .. n-1), src+(0 .. n-1)); assigns dest[0 .. n-1] \from src[0 .. n-1], indirect:src, indirect:n; assigns \result \from dest; @@ -66,6 +87,8 @@ extern int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n); extern wchar_t * wmemcpy(wchar_t *restrict dest, const wchar_t *restrict src, size_t n); /*@ + requires valid_src: \valid_read(src+(0..n-1)); + requires valid_dest: \valid(dest+(0..n-1)); assigns dest[0 .. n-1] \from src[0 .. n-1], indirect:src, indirect:n; assigns \result \from dest; ensures result_ptr: \result == dest; @@ -73,6 +96,7 @@ extern wchar_t * wmemcpy(wchar_t *restrict dest, const wchar_t *restrict src, si extern wchar_t * wmemmove(wchar_t *dest, const wchar_t *src, size_t n); /*@ + requires valid_wcs: \valid(wcs+(0..n-1)); assigns wcs[0 .. n-1] \from wc, indirect:n; assigns \result \from wcs; ensures result_ptr: \result == wcs; @@ -82,6 +106,10 @@ extern wchar_t * wmemmove(wchar_t *dest, const wchar_t *src, size_t n); extern wchar_t * wmemset(wchar_t *wcs, wchar_t wc, size_t n); /*@ + requires valid_wstring_src: valid_read_wstring(src); + requires valid_wstring_dest: valid_wstring(dest); + requires room_for_concatenation: \valid(dest+(wcslen(dest)..wcslen(dest)+wcslen(src))); + requires separation:\separated(dest+(0..wcslen(dest)+wcslen(src)),src+(0..wcslen(src))); assigns dest[0 .. ] \from dest[0 .. ], indirect:dest, src[0 .. ], indirect:src; assigns \result \from dest; ensures result_ptr: \result == dest; @@ -96,21 +124,36 @@ extern wchar_t * wcscat(wchar_t *restrict dest, const wchar_t *restrict src); */ extern wchar_t * wcschr(const wchar_t *wcs, wchar_t wc); -/*@ assigns \result \from indirect:s1[0 .. ], indirect:s2[0 .. ]; */ +/*@ + requires valid_wstring_s1: valid_read_wstring(s1); // over-strong + requires valid_wstring_s2: valid_read_wstring(s2); // over-strong + assigns \result \from indirect:s1[0 .. ], indirect:s2[0 .. ]; +*/ extern int wcscmp(const wchar_t *s1, const wchar_t *s2); /*@ - assigns dest[0 .. ] \from src[0 .. ], indirect:src, dest[0 .. ], indirect:dest; + requires valid_wstring_src: valid_read_wstring(src); + requires room_wstring: \valid(dest+(0 .. wcslen(src))); + requires separation:\separated(dest+(0..wcslen(src)),src+(0..wcslen(src))); + assigns dest[0 .. wcslen(src)] \from src[0 .. wcslen(src)], indirect:src; assigns \result \from dest; ensures result_ptr: \result == dest; */ extern wchar_t * wcscpy(wchar_t *restrict dest, const wchar_t *restrict src); -/*@ assigns \result \from indirect:wcs[0 .. ], indirect:accept[0 .. ]; */ +/*@ + requires valid_wstring_wcs: valid_read_wstring(wcs); + requires valid_wstring_accept: valid_read_wstring(accept); + assigns \result \from indirect:wcs[0 .. ], indirect:accept[0 .. ]; + */ extern size_t wcscspn(const wchar_t *wcs, const wchar_t *accept); // wcslcat is a BSD extension (non-C99, non-POSIX) /*@ + requires valid_nwstring_src: valid_read_nwstring(src, n); + requires valid_wstring_dest: valid_wstring(dest); + requires room_for_concatenation: \valid(dest+(wcslen(dest)..wcslen(dest)+\min(wcslen(src), n))); + requires separation:\separated(dest+(0..wcslen(dest)+wcslen(src)),src+(0..wcslen(src))); assigns dest[0 .. ] \from dest[0 .. ], indirect:dest, src[0 .. n-1], indirect:src, indirect:n; assigns \result \from indirect:dest[0 .. ], indirect:src[0 .. n-1], indirect:n; */ @@ -118,6 +161,8 @@ extern size_t wcslcat(wchar_t *restrict dest, const wchar_t *restrict src, size_ // wcslcpy is a BSD extension (non-C99, non-POSIX) /*@ + requires valid_wstring_src: valid_read_wstring(src); + requires room_nwstring: \valid(dest+(0 .. n)); requires separation:dest:src: \separated(dest+(0 .. n-1), src+(0 .. n-1)); assigns dest[0 .. n-1] \from src[0 .. n-1], indirect:src, indirect:n; assigns \result \from indirect:dest[0 .. n-1], indirect:dest, @@ -125,29 +170,45 @@ extern size_t wcslcat(wchar_t *restrict dest, const wchar_t *restrict src, size_ */ extern size_t wcslcpy(wchar_t *dest, const wchar_t *src, size_t n); -/*@ requires valid_string_s: valid_read_wstring(s); - assigns \result \from indirect:s[0 .. ]; */ +/*@ + requires valid_string_s: valid_read_wstring(s); + assigns \result \from indirect:s[0 .. wcslen(s)]; + ensures result_is_length: \result == wcslen(s); + */ extern size_t wcslen(const wchar_t *s); /*@ + requires valid_nwstring_src: valid_read_nwstring(src, n); + requires valid_wstring_dest: valid_wstring(dest); + requires room_for_concatenation: \valid(dest+(wcslen(dest)..wcslen(dest)+\min(wcslen(src), n))); + requires separation:\separated(dest+(0..wcslen(dest)+wcslen(src)),src+(0..wcslen(src))); assigns dest[0 .. ] \from dest[0 .. ], indirect:dest, src[0 .. n-1], indirect:src, indirect:n; assigns \result \from dest; ensures result_ptr: \result == dest; */ extern wchar_t * wcsncat(wchar_t *restrict dest, const wchar_t *restrict src, size_t n); -/*@ assigns \result \from indirect:s1[0 .. n-1], indirect:s2[0 .. n-1], indirect:n; */ +/*@ + requires valid_wstring_s1: valid_read_wstring(s1); // over-strong + requires valid_wstring_s2: valid_read_wstring(s2); // over-strong + assigns \result \from indirect:s1[0 .. n-1], indirect:s2[0 .. n-1], indirect:n; +*/ extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); /*@ + requires valid_wstring_src: valid_read_wstring(src); + requires room_nwstring: \valid(dest+(0 .. n-1)); requires separation:dest:src: \separated(dest+(0 .. n-1), src+(0 .. n-1)); assigns dest[0 .. n-1] \from src[0 .. n-1], indirect:src, indirect:n; assigns \result \from dest; ensures result_ptr: \result == dest; + ensures initialization: \initialized(dest+(0 .. n-1)); */ extern wchar_t * wcsncpy(wchar_t *restrict dest, const wchar_t *restrict src, size_t n); /*@ + requires valid_wstring_wcs: valid_read_wstring(wcs); + requires valid_wstring_accept: valid_read_wstring(accept); assigns \result \from wcs, indirect:wcs[0 .. ], indirect:accept[0 .. ]; ensures result_null_or_inside_wcs: \result == \null || \subset (\result, wcs+(0 .. )); @@ -155,16 +216,24 @@ extern wchar_t * wcsncpy(wchar_t *restrict dest, const wchar_t *restrict src, si extern wchar_t * wcspbrk(const wchar_t *wcs, const wchar_t *accept); /*@ - assigns \result \from wcs, indirect:wcs[0 .. ], indirect:wc; + requires valid_wstring_wcs: valid_read_wstring(wcs); + assigns \result \from wcs, indirect:wcs[0 .. wcslen(wcs)], indirect:wc; ensures result_null_or_inside_wcs: \result == \null || \subset (\result, wcs+(0 .. )); */ extern wchar_t * wcsrchr(const wchar_t *wcs, wchar_t wc); -/*@ assigns \result \from indirect:wcs[0 .. ], indirect:accept[0 .. ]; */ +/*@ + requires valid_wstring_wcs: valid_read_wstring(wcs); + requires valid_wstring_accept: valid_read_wstring(accept); + assigns \result \from indirect:wcs[0 .. wcslen(wcs)], + indirect:accept[0 .. wcslen(accept)]; +*/ extern size_t wcsspn(const wchar_t *wcs, const wchar_t *accept); /*@ + requires valid_wstring_haystack: valid_read_wstring(haystack); + requires valid_wstring_needle: valid_read_wstring(needle); assigns \result \from haystack, indirect:haystack[0 .. ], indirect:needle[0 .. ]; ensures result_null_or_inside_haystack: \result == \null || \subset (\result, haystack+(0 .. )); @@ -172,8 +241,9 @@ extern size_t wcsspn(const wchar_t *wcs, const wchar_t *accept); extern wchar_t * wcsstr(const wchar_t *haystack, const wchar_t *needle); /*@ + requires room_nwstring: \valid(ws+(0..n-1)); requires valid_stream: \valid(stream); - assigns ws[0..n] \from indirect:n, indirect:*stream; + assigns ws[0..n-1] \from indirect:n, indirect:*stream; assigns \result \from ws, indirect:n, indirect:*stream; ensures result_null_or_same: \result == \null || \result == ws; ensures terminated_string_on_success: 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/parsing/logic_parser.mly b/src/kernel_internals/parsing/logic_parser.mly index e5efe57447e06eca9c6d6a6bb409346c9dcb7372..7d800ea9fe6be22f57a17c8ecab9b301efba66b1 100644 --- a/src/kernel_internals/parsing/logic_parser.mly +++ b/src/kernel_internals/parsing/logic_parser.mly @@ -721,8 +721,8 @@ cv: type_spec_cv: type_spec { $1 } -| cv type_spec { LTattribute ($2, $1) } -| type_spec cv { LTattribute ($1, $2) } +| cv type_spec_cv { LTattribute ($2, $1) } +| type_spec_cv cv { LTattribute ($1, $2) } cast_logic_type: | type_spec_cv abs_spec_cv_option { $2 $1 } diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index 7ba8fa5f2a6c9d5a93c9bfb429456bfaac0b816b..4cfcf1a6dbc2fb12b9cd97f28067f0579f2c34a1 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 loc 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 ~loc false false name t' in vi.vdescr <- Some descr; vi.vdescrpure <- descrpure; alphaConvertVarAndAddToEnv false vi @@ -1565,7 +1566,8 @@ struct match Cil_datatype.Varinfo.Hashtbl.find_opt replacements vi with | None -> let vi' = - newTempVar (vi.vname ^ " initialization") true vi.vtype + newTempVar + ~ghost vi.vdecl (vi.vname ^ " initialization") true vi.vtype in Cil_datatype.Varinfo.Hashtbl.add replacements vi vi'; vars := vi' :: !vars; @@ -2619,11 +2621,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 +3040,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 +3970,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 } @@ -4343,7 +4354,11 @@ let rec doSpecList ghost (suggestedAnonName: string) * collected and processed separately. *) let attrs : A.attribute list ref = ref [] in (* __attribute__, etc. *) let cvattrs : A.cvspec list ref = ref [] in (* const/volatile *) - + let suggestedAnonName = + if suggestedAnonName <> "" then suggestedAnonName + else if get_current_stdheader () = "" then "" + else "fc_stdlib" + in let doSpecElem (se: A.spec_elem) (acc: A.typeSpecifier list) : A.typeSpecifier list = @@ -4709,12 +4724,10 @@ 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 ~loc:ldecl 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 +4796,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 +5039,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 +5066,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 +5086,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 +5165,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 +5219,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 +6073,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 +6180,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 loc descr true t in ([var tmp], local_var_chunk se' tmp +++ (mkStmtOneInstr ~ghost:local_env.is_ghost ~valid_sid @@ -6223,7 +6262,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 loc descr true lvt in let chunk = i2c (mkStmtOneInstr ~ghost:local_env.is_ghost ~valid_sid @@ -6345,7 +6384,7 @@ and doExp local_env finishExp [] se e' intType | _ -> let tmp = - newTempVar "<boolean expression>" true intType + newTempVar ~ghost loc "<boolean expression>" true intType in let condChunk = compileCondExp ~ghost ce @@ -6362,7 +6401,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 +6529,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 +6549,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 +6628,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 +6678,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 +6719,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 +6742,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 loc "vararg" true resTyp in locals := v::!locals; false, var v, [], resTyp in @@ -6717,7 +6771,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 +6807,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 +6846,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 @@ -6899,6 +6953,19 @@ and doExp local_env "Invalid call to builtin_expect" end + | "__fc_infinity" -> begin + piscall := false; + let cst = CReal (infinity, FFloat, Some "INFINITY") in + pres := Cil.new_exp ~loc (Const cst); + prestype := Cil.floatType; + end + | "__fc_nan" -> begin + piscall := false; + let cst = CReal (nan, FFloat, Some "NAN") in + pres := Cil.new_exp ~loc (Const cst); + prestype := Cil.floatType; + end + (* TODO: Only keep the side effects of the 1st or 2nd argument | "__builtin_choose_expr" -> begin match !pargs with @@ -6991,8 +7058,7 @@ and doExp local_env Cil_descriptive_printer.pp_exp) !pargs in - let tmp = newTempVar descr false restype'' in - tmp.vdecl <- loc; + let tmp = newTempVar ~ghost loc descr false restype'' in locals:=tmp::!locals; (* Remember that this variable has been created for this * specific call. We will use this in collapseCallCast. *) @@ -7131,7 +7197,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 loc 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, _, _) = @@ -7200,7 +7266,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 loc 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, _, _) = @@ -7229,7 +7295,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 loc descr true tresult in false, var tmp, [], tresult, local_var_chunk empty tmp in @@ -7302,7 +7368,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 loc "GNU.body" true t in b.bstmts <- b.bstmts @ [Cil.mkStmtOneInstr ~ghost:local_env.is_ghost ~valid_sid @@ -8501,7 +8567,11 @@ 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 loc = v.vdecl in + let v' = + newTempVar ~ghost loc (vi.vname ^ " initialization") true vi.vtype + in temp := Some v'; ChangeTo v' end else SkipChildren @@ -8530,8 +8600,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 @@ -8701,7 +8771,7 @@ and createLocal ghost ((_, sto, _, _) as specs) (* do it in two *) let rt, _, _, _ = splitFunctionType alloca.vtype in let tmp = - newTempVar + newTempVar ~ghost loc (Format.asprintf "alloca(%a)" Cil_printer.pp_exp alloca_size) false rt in @@ -8763,7 +8833,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 @@ -8970,10 +9040,10 @@ 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 - (f.vdecl <- loc; - f.vattr <- fa; + let doFormal (loc : location) ((fn, ft, fa) as fd) = + let ghost = ghost || isGhostFormalVarDecl fd in + let f = makeVarinfo ~ghost ~temp:false ~loc false true fn ft in + (f.vattr <- fa; alphaConvertVarAndAddToEnv true f) in let rec doFormals fl' ll' = @@ -8992,7 +9062,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_internals/typing/logic_builtin.ml b/src/kernel_internals/typing/logic_builtin.ml index ae1a73a97132d659383b01a7ec8643a7f72c002d..7bf6f33d929adccfc01553e0efea752412d41cd2 100644 --- a/src/kernel_internals/typing/logic_builtin.ml +++ b/src/kernel_internals/typing/logic_builtin.ml @@ -285,6 +285,9 @@ let init = ["m", rounding_mode; "x", Lreal], float_type; "\\round_double", [], ["m", rounding_mode ; "x", Lreal], double_type; + "\\plus_infinity", [], [], float_type; + "\\minus_infinity", [], [], float_type; + "\\NaN", [], [], float_type; (*"\\round_quad", [], ["m", rounding_mode; "x", Lreal], long_double_type;*) diff --git a/src/kernel_internals/typing/oneret.ml b/src/kernel_internals/typing/oneret.ml index 93f6d99db42097ddebfd0dff184a4a9ba841e699..e789fd76600c5ba79e5dede7e3253e075e634c82 100644 --- a/src/kernel_internals/typing/oneret.ml +++ b/src/kernel_internals/typing/oneret.ml @@ -197,21 +197,23 @@ let oneret ?(callback: callback option) (f: fundec) : unit = let lastloc = ref Cil_datatype.Location.unknown in let getRetVar = let retVar : varinfo option ref = ref None in - fun () -> + fun loc -> match !retVar with - Some rv -> rv - | None -> begin - let rv = makeLocalVar f "__retres" retTyp in (* don't collide *) - retVar := Some rv; - rv - end + | None -> + let rv = makeLocalVar ~loc f "__retres" retTyp in (* don't collide *) + retVar := Some rv; + rv + | Some rv -> + if rv.vdecl = Cil_datatype.Location.unknown then + rv.vdecl <- loc; + rv in let convert_result p = let vis = object inherit Cil.nopCilVisitor method! vterm_lhost = function | TResult _ -> - let v = getRetVar () in + let v = getRetVar Cil_datatype.Location.unknown in ChangeTo (TVar (cvar_to_lvar v)) | TMem _ | TVar _ -> DoChildren end @@ -267,7 +269,7 @@ let oneret ?(callback: callback option) (f: fundec) : unit = (* Must create a statement *) let rv = if hasRet then - Some (new_exp ~loc (Lval(Var (getRetVar ()), NoOffset))) + Some (new_exp ~loc (Lval(Var (getRetVar loc), NoOffset))) else None in mkStmt (Return (rv, loc)) @@ -338,7 +340,7 @@ let oneret ?(callback: callback option) (f: fundec) : unit = * an instruction that sets the return value (if any). *) s.skind <- begin match retval with - Some rval -> Instr (Set((Var (getRetVar ()), NoOffset), rval, loc)) + Some rval -> Instr (Set((Var (getRetVar loc), NoOffset), rval, loc)) | None -> Instr (Skip loc) end; let returns_assert = ref ptrue in @@ -347,7 +349,7 @@ let oneret ?(callback: callback option) (f: fundec) : unit = returns_stack; (match retval with | Some _ -> - let lvar = Cil.cvar_to_lvar (getRetVar()) in + let lvar = Cil.cvar_to_lvar (getRetVar loc) in Stack.iter (fun (_,_,ca) -> adjust_assigns_clause loc lvar ca.annot_content) returns_stack diff --git a/src/kernel_services/abstract_interp/float_interval.ml b/src/kernel_services/abstract_interp/float_interval.ml index 13650e1b3183bdf9b665803d79f5d9eb61f90e05..a881b71694746b3f6618aa9965359110d8a2ec4a 100644 --- a/src/kernel_services/abstract_interp/float_interval.ml +++ b/src/kernel_services/abstract_interp/float_interval.ml @@ -223,7 +223,7 @@ module Make (F: Float_sig.S) = struct let pos_zero prec = singleton (Cst.pos_zero prec) let one prec = singleton (F.of_float Near prec 1.) let pos_infinity prec = singleton (Cst.pos_infinity prec) - let _neg_infinity prec = singleton (Cst.neg_infinity prec) + let neg_infinity prec = singleton (Cst.neg_infinity prec) let minus_one_one prec ~nan = FRange.inject ~nan (F.of_float Near prec (-1.)) (F.of_float Near prec 1.) @@ -437,17 +437,27 @@ module Make (F: Float_sig.S) = struct | FRange.Itv (_, _, true) | FRange.NaN -> Comp.Unknown - let backward_is_not_nan = function - | FRange.NaN -> `Bottom - | FRange.Itv (b, e, _) -> `Value (FRange.inject ~nan:false b e) - - let backward_is_finite prec = function - | FRange.NaN -> `Bottom - | FRange.Itv (b, e, _) as f -> - if Cmp.equal b e && F.is_infinite b - then `Bottom (* [f] is exactly an infinite, we can return `Bottom even - in the [Real] case *) - else narrow (top_finite prec) f + let backward_is_nan ~positive = function + | FRange.NaN as v -> if positive then `Value v else `Bottom + | FRange.Itv (_, _, false) as v -> if positive then `Bottom else `Value v + | FRange.Itv (b, e, true) -> + if positive then `Value nan else `Value (FRange.inject ~nan:false b e) + + let backward_is_finite ~positive prec = function + | FRange.NaN as v -> if positive then `Bottom else `Value v + | FRange.Itv (b, e, nan) as f -> + if positive + then + if Cmp.equal b e && F.is_infinite b + then `Bottom (* [f] is exactly an infinite, we can return `Bottom + even in the [Real] case. *) + else narrow (top_finite prec) f + else + match F.is_infinite b, F.is_infinite e with + | true, true -> `Value f (* No possible reduction. *) + | true, false -> `Value (FRange.inject ~nan b b) + | false, true -> `Value (FRange.inject ~nan e e) + | false, false -> if nan then `Value FRange.nan else `Bottom let has_greater_min_bound t1 t2 = match t1, t2 with diff --git a/src/kernel_services/abstract_interp/float_interval_sig.mli b/src/kernel_services/abstract_interp/float_interval_sig.mli index aee6a1d773ce8bba231de5e1445ec9b92131bcba..53b9ae7ec2ed45f0d647612c340d210cb3648ba7 100644 --- a/src/kernel_services/abstract_interp/float_interval_sig.mli +++ b/src/kernel_services/abstract_interp/float_interval_sig.mli @@ -47,6 +47,10 @@ module type S = sig (** The NaN singleton *) val nan: t + (** The infinities singleton *) + val pos_infinity: prec -> t + val neg_infinity: prec -> t + (** [inject ~nan b e] creates the floating-point interval [b..e], plus NaN if [nan] is true. [b] and [e] must be ordered, and not NaN. They can be infinite. *) @@ -87,8 +91,8 @@ module type S = sig val is_finite: t -> Abstract_interp.Comp.result val is_not_nan: t -> Abstract_interp.Comp.result - val backward_is_finite: prec -> t -> t or_bottom - val backward_is_not_nan: t -> t or_bottom + val backward_is_finite: positive:bool -> prec -> t -> t or_bottom + val backward_is_nan: positive:bool -> t -> t or_bottom (** [has_greater_min_bound f1 f2] returns 1 if the interval [f1] has a better minimum bound (i.e. greater) than the interval [f2]. *) diff --git a/src/kernel_services/abstract_interp/ival.ml b/src/kernel_services/abstract_interp/ival.ml index 3d7cdeb70656b929e2f259a7dcb20977f6eea92b..b9f8d8529c95358a14b00b53f6ee29139f433a23 100644 --- a/src/kernel_services/abstract_interp/ival.ml +++ b/src/kernel_services/abstract_interp/ival.ml @@ -1161,6 +1161,42 @@ let join v1 v2 = pretty v1 pretty v2 pretty result; *) result +let complement_int_under ~size ~signed i = + let e = Int.two_power_of_int (if signed then size - 1 else size) in + let b = if signed then Int.neg e else Int.zero in + let e = Int.pred e in + let inject_range min max = `Value (inject_range (Some min) (Some max)) in + match i with + | Float _ -> `Bottom + | Set [||] -> inject_range b e + | Set set -> + let l = Array.length set in + let array = Array.make (l + 2) Int.zero in + array.(0) <- b; + Array.blit set 0 array 1 l; + array.(l+1) <- e; + let index = ref (-1) in + let max_delta = ref Int.zero in + for i = 0 to l do + let delta = Int.sub array.(i+1) array.(i) in + if Int.gt delta !max_delta then begin + index := i; + max_delta := delta + end + done; + inject_range array.(!index) array.(!index + 1) + | Top (min, max, _rem, _modu) -> + match min, max with + | None, None -> `Bottom + | Some min, None -> inject_range b (Int.pred min) + | None, Some max -> inject_range (Int.succ max) e + | Some min, Some max -> + let delta_min = Int.sub min b in + let delta_max = Int.sub e max in + if Int.le delta_min delta_max + then inject_range (Int.succ max) e + else inject_range b (Int.pred min) + let fold_int f v acc = match v with Top(None,_,_,_) | Top(_,None,_,_) | Float _ -> diff --git a/src/kernel_services/abstract_interp/ival.mli b/src/kernel_services/abstract_interp/ival.mli index cc7f8630939e8ca2024d3abea7fadb2075d7f635..a94f2aa8f8c32356edcef3dd7c3c67add75b029c 100644 --- a/src/kernel_services/abstract_interp/ival.mli +++ b/src/kernel_services/abstract_interp/ival.mli @@ -319,6 +319,9 @@ val reinterpret_as_int: size:Integer.t -> signed:bool -> t -> t (** Bitwise reinterpretation of the given value, of size [size], as an integer of the given signedness (and size). *) +val complement_int_under: size:int -> signed:bool -> t -> t Bottom.or_bottom +(** Returns an under-approximation of the integers of the given size and + signedness that are *not* represented by the given ival. *) val pretty_debug : Format.formatter -> t -> unit diff --git a/src/kernel_services/analysis/interpreted_automata.ml b/src/kernel_services/analysis/interpreted_automata.ml index fd73d9c1eb22c83d8d33bb3711085d7f4f39b6c6..a1159e205a64295d77a3320e3dc1c8106b4348ea 100644 --- a/src/kernel_services/analysis/interpreted_automata.ml +++ b/src/kernel_services/analysis/interpreted_automata.ml @@ -941,6 +941,9 @@ let is_wto_head kf = Compute.is_wto_head (get_wto_index_table kf) let is_back_edge kf = Compute.is_back_edge (get_wto_index_table kf) +(* ---------------------------------------------------------------------- *) +(* --- Graph with only one entry per component --- *) +(* ---------------------------------------------------------------------- *) module UnrollUnnatural = struct @@ -1090,3 +1093,88 @@ module UnrollUnnatural = struct g' end + + +(* ---------------------------------------------------------------------- *) +(* --- Dataflow computation --- *) +(* ---------------------------------------------------------------------- *) + +module type Domain = +sig + type t + + val join : t -> t -> t + val widen : t -> t -> t option (* returns None when inclusion *) + val transfer : vertex transition -> t -> t option +end + + +module Dataflow (D : Domain) = +struct + module Results = Vertex.Hashtbl + + let fixpoint kf initial_value = + let automaton = get_automaton kf in + let graph = automaton.graph in + let wto = get_wto kf in + let results = Results.create (G.nb_vertex graph) in + + (* Compute the transfer function for the given edge and add the result to + acc *) + let process_edge (v1,e,_v2) acc = + (* Retrieve origin value *) + match Results.find_opt results v1 with + | None -> acc (* No previous value *) + | Some value -> + match D.transfer e.edge_transition value with + | None -> acc + | Some new_value -> new_value :: acc + in + + (* Compute the abstract value for the given control point ; compute all + incoming transfer functions *) + let process_vertex v = + let incomming = G.fold_pred_e process_edge graph v [] + and initial = if v == automaton.entry_point then [initial_value] else [] + in + match initial @ incomming with + | [] -> (* Zero incomming values -> Bottom *) + Results.remove results v + | v1 :: vl -> + (* Join incomming values *) + let result = List.fold_left D.join v1 vl in + Results.add results v result + in + + (* widen returns whether it is necessary to continue to iterate or not *) + let widen v previous = + let current = Results.find_opt results v in + match previous, current with + | _, None -> false (* Current is bottom, let's quit *) + | None, _ -> true (* Previous was bottom *) + | Some v1, Some v2 -> + match D.widen v1 v2 with + | None -> false (* End of iteration *) + | Some value -> (* new value *) + Results.add results v value; + true + in + + let rec iterate_list l = + List.iter iterate_element l + and iterate_element = function + | Wto.Node v -> + ignore (process_vertex v) + | Wto.Component (v, w) -> + while + let previous = Results.find_opt results v in + process_vertex v; + widen v previous + do + iterate_list w; + done; + in + iterate_list wto; + results +end + diff --git a/src/kernel_services/analysis/interpreted_automata.mli b/src/kernel_services/analysis/interpreted_automata.mli index c7c1b86d8732efb66b29bd2448ba60f0b8fa557c..e939c4cf6c4c86478c96343bfc7d689fa19d4713 100644 --- a/src/kernel_services/analysis/interpreted_automata.mli +++ b/src/kernel_services/analysis/interpreted_automata.mli @@ -244,3 +244,37 @@ module UnrollUnnatural : sig automaton -> wto -> Compute.wto_index_table -> G.t end + + +(** Dataflow computation: simple data-flow analysis using interpreted automata. + This is mostly intended as an example for using interpreted automata; + see also tests/misc/interpreted_automata_dataflow.ml for a complete example + using this dataflow. *) + +(** Input domain for a simple dataflow analysis. *) +module type Domain = +sig + type t (** States propagated by the dataflow analysis. *) + + (** Merges two states coming from different paths. *) + val join : t -> t -> t + + (** [widen v1 v2] must returns None if [v2] is included in [v1]. + Otherwise, over-approximates the join between [v1] and [v2] such that + any sequence of successive widenings is ultimately stationary, + i.e. […widen (widen (widen x0 x1) x2) x3…] eventually returns None. + Called on loop heads to ensure the analysis termination. *) + val widen : t -> t -> t option + + (** Transfer function for transitions: computes the state after the transition + from the state before. Returns None if the end of the transition is not + reachable from the given state. *) + val transfer : vertex transition -> t -> t option +end + +(** Builds a simple dataflow analysis over an input domain. *) +module Dataflow (D : Domain) : +sig + val fixpoint : Cil_types.kernel_function -> D.t -> D.t Vertex.Hashtbl.t +end + 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..924ce6b3312eb3ca4ef719345d7ee2d22a087794 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) ?(loc=Location.unknown) + global formal name typ + = let vi = { vorig_name = name; vname = name; @@ -583,7 +613,7 @@ let makeVarinfo ?(source=true) ?(temp=false) ?(referenced=false) global formal n vformal = formal; vtemp = temp; vtype = typ; - vdecl = Location.unknown; + vdecl = loc; vinline = false; vattr = []; vstorage = NoStorage; @@ -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,16 +5228,16 @@ 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) ?loc 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 ?loc false formal name typ in vi (* Make a local variable and add it to a function *) -let makeLocalVar fdec ?scope ?(temp=false) ?referenced ?(insert = true) name typ = - let vi = makeLocal ~temp ?referenced fdec name typ in +let makeLocalVar fdec ?scope ?(temp=false) ?referenced ?(insert=true) ?loc name typ = + let vi = makeLocal ~temp ?referenced ?loc fdec name typ in refresh_local_name fdec vi; if insert then begin @@ -5224,9 +5251,8 @@ let makeLocalVar fdec ?scope ?(temp=false) ?referenced ?(insert = true) name typ end; vi -let makeTempVar fdec ?insert ?(name = "__cil_tmp") ?descr ?(descrpure = true) - typ : varinfo = - let vi = makeLocalVar fdec ~temp:true ?insert name typ in +let makeTempVar fdec ?insert ?(name = "__cil_tmp") ?descr ?(descrpure = true) ?loc typ : varinfo = + let vi = makeLocalVar fdec ~temp:true ?insert ?loc name typ in vi.vdescr <- descr; vi.vdescrpure <- descrpure; vi @@ -5275,21 +5301,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 = "$") ?loc name typ : varinfo = + assert ((not fdec.svar.vghost) || ghost) ; + let makeit name = + let vi = makeLocal ~ghost ?loc ~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 @@ -5298,14 +5338,14 @@ let makeFormalVar fdec ?(where = "$") name typ : varinfo = (* Make a global variable. Your responsibility to make sure that the name * is unique *) -let makeGlobalVar ?source ?temp ?referenced name typ = - makeVarinfo ?source ?temp ?referenced true false name typ +let makeGlobalVar ?source ?temp ?referenced ?loc name typ = + makeVarinfo ?source ?temp ?referenced ?loc true false name typ let mkPureExprInstr ~fundec ~scope ?loc e = let loc = match loc with None -> e.eloc | Some l -> l in let typ = typeOf e in let descr = Format.asprintf "%a" !pp_exp_ref e in - let tmp = makeLocalVar ~temp:true ~scope fundec "tmp" typ in + let tmp = makeLocalVar ~temp:true ~scope ~loc fundec "tmp" typ in tmp.vdescr <- Some descr; tmp.vdefined <- true; Local_init(tmp, AssignInit (SingleInit e), loc) @@ -5793,6 +5833,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..38039b32d1f24f359acf784da5d35d5bc1a8628d 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,35 @@ 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 [loc] argument defaults to [Location.unknown], and corresponds to the field + [vdecl] . 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 -> ?loc:Location.t -> 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 -> ?loc:Location.t -> 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). @@ -673,8 +699,8 @@ val makeFormalVar: fundec -> ?where:string -> string -> typ -> varinfo @modify Chlorine-20180501 the name of the variable is guaranteed to be fresh. *) val makeLocalVar: - fundec -> ?scope:block -> ?temp:bool -> ?referenced:bool -> ?insert:bool - -> string -> typ -> varinfo + fundec -> ?scope:block -> ?temp:bool -> ?referenced:bool -> ?insert:bool -> + ?loc:Location.t -> string -> typ -> varinfo (** if needed, rename the given varinfo so that its [vname] does not clash with the one of a local or formal variable of the given function. @@ -686,18 +712,19 @@ val refresh_local_name: fundec -> varinfo -> unit (** Make a temporary variable and add it to a function's slocals. The name of the temporary variable will be generated based on the given name hint so that to avoid conflicts with other locals. - Optionally, you can give the variable a description of its contents. + Optionally, you can give the variable a description of its contents and + its location. Temporary variables are always considered as generated variables. If [insert] is true (the default), the variable will be inserted among other locals of the function. The value for [insert] should only be changed if you are completely sure this is not useful. *) val makeTempVar: fundec -> ?insert:bool -> ?name:string -> ?descr:string -> - ?descrpure:bool -> typ -> varinfo + ?descrpure:bool -> ?loc:Location.t -> typ -> varinfo (** Make a global variable. Your responsibility to make sure that the name is unique. [source] defaults to [true]. [temp] defaults to [false].*) -val makeGlobalVar: ?source:bool -> ?temp:bool -> ?referenced:bool -> string -> +val makeGlobalVar: ?source:bool -> ?temp:bool -> ?referenced:bool -> ?loc:Location.t -> string -> typ -> varinfo (** Make a shallow copy of a [varinfo] and assign a new identifier. @@ -1171,6 +1198,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 +1224,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/plugin_entry_points/kernel.ml b/src/kernel_services/plugin_entry_points/kernel.ml index 3bcff739e6a5064f21a7fd18923c3992c43c6ce3..651e7f1630b5c3fd3aea7c6e1823ea8bc47876c9 100644 --- a/src/kernel_services/plugin_entry_points/kernel.ml +++ b/src/kernel_services/plugin_entry_points/kernel.ml @@ -996,8 +996,8 @@ module WarnDecimalFloat = String(struct let option_name = "-warn-decimal-float" let arg_name = "freq" - let help = "[DEPRECATED: Use -kernel-warn-key decimal-float \ - (and similar options) instead] \ + let help = "[DEPRECATED: Use -kernel-warn-key \ + parser:decimal-float=active (or inactive) instead] \ Warn when floating-point constants cannot be exactly \ represented; freq must be one of none, once or all" let default = "once" 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/libraries/utils/leftistheap.ml b/src/libraries/utils/leftistheap.ml deleted file mode 100644 index 8fd7e63379504205c1246a9811d58a6437b303d7..0000000000000000000000000000000000000000 --- a/src/libraries/utils/leftistheap.ml +++ /dev/null @@ -1,81 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) Jean-Christophe Filliatre *) -(* *) -(* This software is free software; you can redistribute it and/or *) -(* modify it under the terms of the GNU Library General Public *) -(* License version 2.1, with the special exception on linking *) -(* described in file LICENSE. *) -(* *) -(* This software is distributed in the hope that it will be useful, *) -(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) -(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(* *) -(**************************************************************************) - -(* Leftist heaps. - - See for instance Chris Okasaki's "Purely Functional Data Structures" *) - - -exception Empty - -module Make(X: Set.OrderedType) : -sig - type t - val empty : t - val is_empty : t -> bool - val insert : X.t -> t -> t - val min : t -> X.t - val extract_min : t -> X.t * t - val merge : t -> t -> t - val fold: (X.t -> 'a -> 'a) -> t -> 'a -> 'a - val elements: t -> X.t list - val of_list: X.t list -> t -end -= -struct - - type t = E | T of int * X.t * t * t - - let rank = function E -> 0 | T (r,_,_,_) -> r - - let make x a b = - let ra = rank a and rb = rank b in - if ra >= rb then T (rb + 1, x, a, b) else T (ra + 1, x, b, a) - - let empty = E - - let is_empty = function E -> true | T _ -> false - - let rec merge h1 h2 = match h1,h2 with - | E, h | h, E -> - h - | T (_,x,a1,b1), T (_,y,a2,b2) -> - if X.compare x y <= 0 - then make x a1 (merge b1 h2) - else make y a2 (merge h1 b2) - - let insert x h = merge (T (1, x, E, E)) h - - let min = function E -> raise Empty | T (_,x,_,_) -> x - - let extract_min = function - | E -> raise Empty - | T (_,x,a,b) -> x, merge a b - - (* Added by CEA *) - - let rec fold f h acc = match h with - | E -> acc - | T (_, x, h1, h2) -> fold f h2 (f x (fold f h1 acc)) - - let elements h = fold (fun e l -> e :: l) h [] - - (* can probably be improved *) - let of_list l = List.fold_left (fun h x -> insert x h) E l - -end diff --git a/src/libraries/utils/leftistheap.mli b/src/libraries/utils/leftistheap.mli deleted file mode 100644 index b16d8277b8cdb6bb04de4fab269a667295b92ff4..0000000000000000000000000000000000000000 --- a/src/libraries/utils/leftistheap.mli +++ /dev/null @@ -1,56 +0,0 @@ -(**************************************************************************) -(* *) -(* Copyright (C) Jean-Christophe Filliatre *) -(* *) -(* This software is free software; you can redistribute it and/or *) -(* modify it under the terms of the GNU Library General Public *) -(* License version 2.1, with the special exception on linking *) -(* described in file LICENSE. *) -(* *) -(* This software is distributed in the hope that it will be useful, *) -(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) -(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives). *) -(* *) -(**************************************************************************) - -(** Leftist heaps. - - See for instance Chris Okasaki's "Purely Functional Data Structures" *) - -exception Empty - -module Make(X: Set.OrderedType) : -sig - type t - - val empty: t - - val is_empty: t -> bool - (** runs in O(1) *) - - val insert: X.t -> t -> t - (** runs in O(log n) *) - - val min: t -> X.t - (** runs in O(1) *) - - val extract_min: t -> X.t * t - (** runs in O(log n) *) - - val merge: t -> t -> t - (** runs in O(log max(n1, n2)) *) - - - (* Added by CEA *) - - val fold: (X.t -> 'a -> 'a) -> t -> 'a -> 'a - (** elements are presented in an arbitrary order *) - - val elements: t -> X.t list - (** the returned list is not sorted *) - - val of_list: X.t list -> t -end diff --git a/src/plugins/loop_analysis/README.org b/src/plugins/loop_analysis/README.org index 7e90c89f5c08ff7b35874f7c359e89ee128be981..6e4388ee4b5e2b4be3761f62fd1d6dc811a255d5 100644 --- a/src/plugins/loop_analysis/README.org +++ b/src/plugins/loop_analysis/README.org @@ -1,5 +1,9 @@ Loop and "slevel" analysis. +Note: this plug-in has been deprecated in favor of newer Eva features, such as + `-eva-auto-loop-unroll`, `//@ loop unroll` annotations and trace + partitioning. It will be removed in a future release. + * Overview This plugin performs two analyses. diff --git a/src/plugins/loop_analysis/options.ml b/src/plugins/loop_analysis/options.ml index 58848be42e5c1533a915fe22df28d5cc5193cf5f..7c6339d5e1fc82016a5d90fed670510fdca3bcc8 100644 --- a/src/plugins/loop_analysis/options.ml +++ b/src/plugins/loop_analysis/options.ml @@ -24,13 +24,15 @@ include Plugin.Register (struct let name = "loop" let shortname = "loop" - let help = "Find number of iterations in loops, and slevel value" + let help = "[DEPRECATED: use Eva's loop unroll annotations and options] \ + Find number of iterations in loops, and slevel value" end) module Run = False (struct let option_name = "-loop" - let help = "Launch loop analysis" + let help = "[deprecated: use Eva loop unroll annotations or \ + -eva-auto-loop-unroll] Launch loop analysis" end) module MaxIterations = Int diff --git a/src/plugins/qed/export_coq.ml b/src/plugins/qed/export_coq.ml index 0c4862c0175ea3f4310a2472b40fe20b9b1d35c8..8e06fa9404c3431e141abaf3713952d73278804f 100644 --- a/src/plugins/qed/export_coq.ml +++ b/src/plugins/qed/export_coq.ml @@ -320,7 +320,7 @@ struct (fun (c,ts) -> fprintf fmt "@ | @[<hov 2>%s : " (link_name (self#link c)) ; List.iter (fun t -> fprintf fmt "@ %a ->" self#pp_tau t) ts ; - fprintf fmt "@ %a.@]" self#pp_tau result ; + fprintf fmt "@ %a@]" self#pp_tau result ; ) cases ; fprintf fmt ".@]@\n" ; end diff --git a/src/plugins/report/tests/report/oracle/csv.csv b/src/plugins/report/tests/report/oracle/csv.csv index 18a0e92bcf745d267e58b4a630a8962646e626ed..c44a659ed70c59996a52187b9e77c2f1e8253048 100644 --- a/src/plugins/report/tests/report/oracle/csv.csv +++ b/src/plugins/report/tests/report/oracle/csv.csv @@ -1,5 +1,5 @@ directory file line function property kind status property -FRAMAC_SHARE/libc math.h 526 pow precondition Unknown finite_logic_res: \is_finite(pow(x, y)) +FRAMAC_SHARE/libc math.h 522 pow precondition Unknown finite_logic_res: \is_finite(pow(x, y)) tests/report csv.c 11 main1 signed_overflow Unknown -2147483648 ≤ x * x tests/report csv.c 11 main1 signed_overflow Unknown x * x ≤ 2147483647 tests/report csv.c 12 main1 index_bound Unknown 0 ≤ x diff --git a/src/plugins/server/configure.ac b/src/plugins/server/configure.ac index 4ab9e3f73f11ed3c98fdf85d9531e12b51368e10..47ac79512c1776c458bf245f9c1fea9160e58b6b 100644 --- a/src/plugins/server/configure.ac +++ b/src/plugins/server/configure.ac @@ -37,20 +37,6 @@ m4_ifndef([FRAMAC_M4_MACROS], [m4_include(FRAMAC_SHARE/configure.ac)]) check_plugin(server,PLUGIN_RELATIVE_PATH(plugin_file),[Server plug-in],yes) -######################################## -# Server Main Configuration # -######################################## - -AC_MSG_CHECKING(for Yojson) -SERVER_LIB_YOJSON=$($OCAMLFIND query yojson -format %v) -if test -z "$SERVER_LIB_YOJSON" -then - AC_MSG_RESULT(Server disabled (use 'opam install yojson')) - plugin_disable(server) -else - AC_MSG_RESULT(yes) -fi - ######################################## # Server ZMQ Configuration # ######################################## @@ -64,19 +50,11 @@ AC_ARG_ENABLE( if test "$SERVER_ZMQ" = "yes" ; then - AC_MSG_CHECKING(for ZeroMQ) - SERVER_LIB_ZMQ=$($OCAMLFIND query zmq -format %v) - if test -z "$SERVER_LIB_ZMQ" - then - AC_MSG_RESULT(Server support for ZeroMQ disabled (use 'opam install zmq').) - SERVER_ZMQ=no - else - AC_MSG_RESULT(yes); - fi + configure_pkg([zmq], + [Server support for ZeroMQ disabled (try 'opam install zmq').]) + plugin_use_pkg(server,zmq) fi -AC_SUBST(SERVER_ZMQ) - ####################### # Generating Makefile # ####################### diff --git a/src/plugins/server/server_batch.ml b/src/plugins/server/server_batch.ml index 87a3fd9c4907562237c4d23e495f91397a59df10..fa251825afa9c6bc1f95e1cfe39cc9d169494c55 100644 --- a/src/plugins/server/server_batch.ml +++ b/src/plugins/server/server_batch.ml @@ -42,6 +42,7 @@ module Batch = Senv.String_list end) let () = Parameter_customize.set_group batch_group +let () = Parameter_customize.do_not_save () module BatchOutputDir = Senv.Empty_string (struct let option_name = "-server-batch-output-dir" @@ -96,6 +97,8 @@ let rec execute_batch js = let execute () = begin + let files = Batch.get () in + Batch.clear () ; (* clear in any case *) List.iter begin fun file -> Senv.feedback "Script %S" file ; @@ -109,8 +112,7 @@ let execute () = let out = open_out output in Js.pretty_to_channel out response ; close_out out - end - (Batch.get()) ; + end files end (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/value/domains/octagons.ml b/src/plugins/value/domains/octagons.ml new file mode 100644 index 0000000000000000000000000000000000000000..48734821cf4f4e84353625637dc78310bdd4b867 --- /dev/null +++ b/src/plugins/value/domains/octagons.ml @@ -0,0 +1,1323 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +open Cil_types +open Eval + +(* If [true], checks invariants of the states created by most functions. *) +let debug = false + +(* Whether the domain infers non-relational intervals (ivals) to improve the + precision of the join operation: this avoids losing all relations that have + been inferred in only one side of the join. Enhances the domain accuracy + for a minimal drop in efficiency. *) +let infer_intervals = true + +(* Whether the domain saturates the octagons: from a relation between (x, y) + and a relation between (y, z), infers the relation between (x, z). + The saturation is currently partial. Improves the domain accuracy for a + minimal drop in efficiency. *) +let saturate_octagons = true + +(* Is the domain intraprocedural, according to the -eva-octagon-through-calls + option. In this case, the analysis of each function starts with an empty + state, and the relations inferred in a function are not propagated back to + the caller either. *) +let intraprocedural () = not (Value_parameters.OctagonCall.get ()) + +(* -------------------------------------------------------------------------- *) +(* Basic types: pair of variables and Ival.t *) +(* -------------------------------------------------------------------------- *) + +(* Variables of the octagons. Should be extended later to also include + symbolic lvalues. *) +module Variable = struct + include Cil_datatype.Varinfo + let id v = v.vid +end + +module VariableSet = struct + include Variable.Set + let pretty_debug = pretty +end + +(* Pairs of related variables in an octagon. + This module imposes an order between the two variables X and Y in a pair + to avoid creating octagons about X±Y *and* about Y±X. *) +module Pair = struct + module D = Datatype.Pair (Variable) (Variable) + module Info = struct + let name = "Octagons.Pair" + let dependencies = [ Ast.self ] + let initial_values = [] + end + + include State_builder.Hashcons (D) (Info) + + (* Creates a pair, and also returns a boolean that is [true] if x, y are + swapped in the pair. *) + let make x y = + assert (x.vid <> y.vid); + let pair, swap = if x.vid < y.vid then (x, y), false else (y, x), true in + hashcons pair, swap + + let fst t = fst (get t) +end + + +(* Kind of relation between two variables X and Y: X+Y or X-Y. *) +type operation = Add | Sub + +(* Extended arithmetic operations over Ival.t. *) +module Arith = struct + open Ival + + let top_float = Ival.inject_float Fval.top + + let narrow x y = + let r = narrow x y in + if is_bottom r then `Bottom else `Value r + + let widen = + let hints = Integer.zero, + (Ival.Widen_Hints.default_widen_hints, + Fc_float.Widen_Hints.default_widen_hints) + in + Ival.widen hints + + (* TODO: do not use Ival.top on floating-point value? *) + let project_float ival = + if Ival.(equal top ival) then Fval.top + else project_float ival + + let neg = function + | Float f -> inject_float (Fval.neg f) + | ival -> neg_int ival + + let int_or_float_operation i_op f_op = fun typ -> + match Cil.unrollType typ with + | TInt _ | TEnum _ -> i_op + | TFloat _ -> fun i1 i2 -> + inject_float (f_op Fval.Real (project_float i1) (project_float i2)) + | _ -> assert false + + let sub = int_or_float_operation Ival.sub_int Fval.sub + let add = int_or_float_operation Ival.add_int Fval.add + + let apply = function + | Add -> add + | Sub -> sub + + (* Creates the ival covering the integer range [range]. *) + let make_range range = + let min = Eval_typ.range_lower_bound range in + let max = Eval_typ.range_upper_bound range in + Ival.inject_range (Some min) (Some max) + + (* Does an ival represent all values of a C type [typ]? *) + let is_top_for_typ typ ival = + let open Eval_typ in + Ival.(equal top ival) || + match classify_as_scalar typ with + | None -> assert false + | Some (TSFloat _) -> Ival.equal top_float ival + | Some (TSInt range | TSPtr range) -> + (* TODO: this could be more efficient. *) + let range = make_range range in + Ival.is_included range ival || Ival.is_included range (neg_int ival) + + (* Does an ival represent all possible values of a pair of variables? *) + let is_top_for_pair pair = + let x, y = Pair.get pair in + if Cil_datatype.Typ.equal x.vtype y.vtype + then is_top_for_typ x.vtype + else fun ival -> is_top_for_typ x.vtype ival && is_top_for_typ y.vtype ival +end + +(* -------------------------------------------------------------------------- *) +(* Rewriting Cil expressions into mathematical octagons *) +(* -------------------------------------------------------------------------- *) + +(* An octagonal relation between two variables : b ≤ X±Y ≤ e *) +type octagon = + { variables: Pair.t; (* The two related variables X and Y. *) + operation: operation; (* Whether the relation is about X+Y or X-Y. *) + value: Ival.t; (* The interval of X±Y. *) + } + +let _pretty_octagon fmt octagon = + let x, y = Pair.get octagon.variables in + let op = match octagon.operation with Add -> "+" | Sub -> "-" in + Format.fprintf fmt "%a %s %a %s %a" + Printer.pp_varinfo x op Printer.pp_varinfo y + (Unicode.inset_string ()) Ival.pretty octagon.value + +(* Transforms Cil expressions into mathematical octagons. + Use Ival.t to evaluate expressions. *) +module Rewriting = struct + + (* Checks if the interval [ival] fits in the C type [typ]. + This is used to ensure that an expression cannot overflow: this module + uses the mathematical semantics of arithmetic operations, and cannot + soundly translate overflows in the C semantics. *) + let may_overflow typ ival = + let open Eval_typ in + match classify_as_scalar typ with + | None -> assert false (* This should not happen here. *) + | Some (TSFloat _) -> false + | Some (TSInt range | TSPtr range) -> + not + ((range.i_signed && Kernel.SignedOverflow.get ()) || + (not range.i_signed && Kernel.UnsignedOverflow.get ()) || + Ival.is_included ival (Arith.make_range range)) + + (* Simplified form [±X-coeff] for expressions, + where X is a variable and coeff an interval. *) + type var_coeff = { varinfo: varinfo; sign: bool; coeff: Ival.t; } + + (* Negates a simplified form. *) + let neg { varinfo; sign; coeff } = + { varinfo; sign = not sign; coeff = Arith.neg coeff } + + (* Is the interval computed for a variable a singleton? *) + let is_singleton = function + | `Top -> false + | `Value ival -> Ival.cardinal_zero_or_one ival + + (* If a needed interval is unknown, stop the current computation and return + an empty list. *) + let (>>) value f = match value with + | `Top -> [] + | `Value ival -> f ival + + (* Apply [f typ v1 v2] if the operation [e1 op e2] does not overflow, + where [v1] and [v2] are the intervals for [e1] and [e2], and [typ] is + the type of [e1]. Returns the empty list otherwise. *) + let apply_binop f evaluate typ e1 op e2 = + evaluate e1 >> fun v1 -> + evaluate e2 >> fun v2 -> + let typ_e1 = Cil.typeOf e1 in + let result = Arith.apply op typ_e1 v1 v2 in + if may_overflow typ result + then [] + else f typ_e1 v1 v2 + + (* Rewrites the Cil expression [expr] into the simplified form [±x-coeff], + where [x] is a non-singleton variable and [coeff] is an interval. The + result follows the mathematical semantics. + If such a simplified form cannot be found, the function returns an empty + list. If multiple variables occur in the expression, the function tries to + compute a list of equivalent forms [±x-coeff], one for each variable. The + function relies on an evaluation function linking each sub-expression into + an interval, used for computing sound coefficients. The evaluation may + return Top for some sub-expression, thus preventing the computation. *) + let rec rewrite evaluate expr = + match expr.enode with + | Lval (Var varinfo, NoOffset) -> + if Cil.isIntegralType varinfo.vtype + && not (Cil.typeHasQualifier "volatile" varinfo.vtype) + && not (is_singleton (evaluate expr)) + then [ { varinfo; sign = true; coeff = Ival.zero } ] + else [] + + | UnOp (Neg, e, typ) -> + evaluate e >> fun v -> + if may_overflow typ (Arith.neg v) + then [] else List.map neg (rewrite evaluate e) + + | BinOp ((PlusA | MinusA as binop), e1, e2, typ) -> + let op = if binop = PlusA then Add else Sub in + let rewrite_binop typ v1 v2 = + let inverse_op = if binop = PlusA then Arith.sub else Arith.add in + let add_v2 var = + { var with coeff = inverse_op typ var.coeff v2 } + in + let add_v1 var = + let var = if binop = MinusA then neg var else var in + { var with coeff = Arith.sub typ var.coeff v1 } + in + List.map add_v2 (rewrite evaluate e1) @ + List.map add_v1 (rewrite evaluate e2) + in + apply_binop rewrite_binop evaluate typ e1 op e2 + + | CastE (typ, e) -> + if Cil.(isIntegralType typ && isIntegralType (typeOf e)) then + evaluate e >> fun v -> + if may_overflow typ v then [] else rewrite evaluate e + else [] + + | Info (e, _) -> rewrite evaluate e + + | _ -> [] + + (* Rewrites the operation [e1 ± e2] into equivalent octagons ±(X±Y-value). *) + let rewrite_binop evaluate e1 binop e2 = + let vars1 = rewrite evaluate e1 in + let vars2 = rewrite evaluate e2 in + let vars2 = if binop = Sub then List.map neg vars2 else vars2 in + let aux acc var1 var2 = + if Cil_datatype.Varinfo.equal var1.varinfo var2.varinfo + then acc + else + let variables, swap = Pair.make var1.varinfo var2.varinfo in + let operation = if var1.sign = var2.sign then Add else Sub in + let sign = match operation with + | Add -> var1.sign + | Sub -> if swap then var2.sign else var1.sign + in + let value = Arith.add (Cil.typeOf e1) var1.coeff var2.coeff in + let value = if sign then value else Arith.neg value in + (* Do not include this rewriting if the [value] exceeds all possible + values for the type of [var1] and [var2]. *) + if Arith.is_top_for_pair variables value + then acc + else (sign, { variables; operation; value }) :: acc + in + Extlib.product_fold aux [] vars1 vars2 + + (* Returns the range of the expression X-Y when the comparison X#Y holds. *) + let comparison_range = + let open Abstract_interp.Comp in + function + | Lt -> Ival.inject_range None (Some Integer.minus_one) + | Gt -> Ival.inject_range (Some Integer.one) None + | Le -> Ival.inject_range None (Some Integer.zero) + | Ge -> Ival.inject_range (Some Integer.zero) None + | Eq -> Ival.zero + | Ne -> Ival.top + + (* Transforms the constraint [expr] ∈ [ival] into a list of octagonal + constraints. *) + let make_octagons evaluate expr ival = + let make_octagons_from_binop typ e1 op e2 ival = + (* equivalent octagonal forms ±(X±Y-v) for [e1 op e2]. *) + let rewritings = rewrite_binop evaluate e1 op e2 in + (* create the final octagon, knowning that [e1 op e2] ∈ [ival]. *) + let make_octagon (sign, octagon) = + let ival = if sign then ival else Arith.neg ival in + let value = Arith.add typ ival octagon.value in + { octagon with value } + in + List.map make_octagon rewritings + in + match expr.enode with + | BinOp ((PlusA | MinusA as binop), e1, e2, typ) -> + let op = if binop = PlusA then Add else Sub in + let make_octagons typ _ _ = make_octagons_from_binop typ e1 op e2 ival in + apply_binop make_octagons evaluate typ e1 op e2 + | BinOp ((Lt | Gt | Le | Ge | Eq | Ne as binop), e1, e2, _typ) -> + let typ = Cil.typeOf e1 in + if not (Cil.isIntegralType typ) + || (Ival.contains_zero ival && Ival.contains_non_zero ival) + then [] + else + let comp = Value_util.conv_comp binop in + let comp = + if Ival.is_zero ival then Abstract_interp.Comp.inv comp else comp + in + let range = comparison_range comp in + make_octagons_from_binop typ e1 Sub e2 range + | _ -> [] + + let overflow_alarms typ expr ival = + match Eval_typ.classify_as_scalar typ with + | Some (Eval_typ.TSInt range) -> + let signed = range.Eval_typ.i_signed in + let overflow = if signed then Alarms.Signed else Alarms.Unsigned in + let max_bound = Eval_typ.range_upper_bound range in + let min_bound = Eval_typ.range_lower_bound range in + let ival_range = Ival.inject_range (Some min_bound) (Some max_bound) in + let aux has_better_bound bound bound_kind alarms = + if has_better_bound ival ival_range >= 0 + then + let alarm = Alarms.Overflow (overflow, expr, bound, bound_kind) in + Alarmset.set alarm Alarmset.True alarms + else alarms + in + let alarms = Alarmset.all in + let alarms = + aux Ival.has_greater_min_bound min_bound Alarms.Lower_bound alarms + in + aux Ival.has_smaller_max_bound max_bound Alarms.Upper_bound alarms + | _ -> Alarmset.all + + (* Evaluates the Cil expression [expr], by rewriting it into octagonal + constraints using [evaluate_expr] to evaluate sub-expressions, and + then using [evaluate_octagon] to evaluate the octagons. *) + let evaluate_through_octagons evaluate_expr evaluate_octagon expr = + let evaluate_octagon acc (sign, octagon) = + match evaluate_octagon octagon with + | None -> acc + | Some ival -> + let ival = if sign then ival else Arith.neg ival in + Ival.narrow acc ival + in + let evaluate_octagons octagons = + List.fold_left evaluate_octagon Ival.top octagons + in + let default = Ival.top, Alarmset.all in + match expr.enode with + | BinOp ((PlusA | MinusA as binop), e1, e2, typ) -> + let op = if binop = PlusA then Add else Sub in + let octagons = rewrite_binop evaluate_expr e1 op e2 in + let ival = evaluate_octagons octagons in + if Ival.(equal top ival) then default else + let typ_e1 = Cil.typeOf e1 in + let ival2 = + match evaluate_expr e1, evaluate_expr e2 with + | `Value v1, `Value v2 -> Arith.apply op typ_e1 v1 v2 + | _, _ -> Ival.top + in + let ival = Ival.narrow ival ival2 in + if may_overflow typ ival + then default + else ival, overflow_alarms typ expr ival + | BinOp ((Lt | Gt | Le | Ge | Eq as binop), e1, e2, _typ) + when Cil.isIntegralType (Cil.typeOf e1) -> + let comp = Value_util.conv_comp binop in + (* Evaluate [e1 - e2] and compare the resulting interval to the interval + for which the comparison [e1 # e2] holds. *) + let range = comparison_range comp in + let octagons = rewrite_binop evaluate_expr e1 Sub e2 in + let ival = evaluate_octagons octagons in + if Ival.is_included ival range then Ival.one, Alarmset.all + else if not (Ival.intersects ival range) + then Ival.zero, Alarmset.all else default + | _ -> default + +end + +(* -------------------------------------------------------------------------- *) +(* Diamonds and octagons: relations between two variables *) +(* -------------------------------------------------------------------------- *) + +(* This domain infers relations between pairs of variables (X, Y), by inferring + intervals for the mathematical operations X+Y and X-Y. + It also infers non-relational intervals for the separate variables X and Y + (they could be seen as intervals for X+X and Y+Y, but we chose to store them + in another way). These intervals are used to make the join more precise. + Geometrically, in a plan, intervals for X and Y shape a straight rectangle, + while intervals for X+Y and X-Y shape a "leaning" rectangle; the intersection + of these rectangles shapes an octagon. + Using a misnomer, we call diamonds the intervals for X+Y and X-Y, and + octagons the maps from variables to diamonds, even if they do not exactly + shape octagons. *) + +(* Relation between a pair of variables (X, Y). + [add] is an interval for X+Y, and [sub] is an interval for [X-Y]. *) +type diamond = { add: Ival.t; sub: Ival.t } + +module DiamondDatatype = struct + type t = diamond + include Datatype.Serializable_undefined + + let name = "Octagons.Diamond" + let structural_descr = + Structural_descr.t_record [| Ival.packed_descr; Ival.packed_descr |] + let reprs = [ { add = Ival.top; sub = Ival.top } ] + + let compare x y = + let c = Ival.compare x.add y.add in + if c <> 0 then c else Ival.compare x.sub y.sub + + let equal = Datatype.from_compare + + let hash { add; sub } = Hashtbl.hash (Ival.hash add, Ival.hash sub) + + let pretty fmt { add; sub } = + Format.fprintf fmt "@[<hov>ADD: @[%a@] ; SUB: @[%a@]@]" + Ival.pretty add Ival.pretty sub +end + +module Diamond = struct + include Datatype.Make (DiamondDatatype) + let pretty_debug = pretty + + let top = { add = Ival.top; sub = Ival.top } + + let is_included x y = + Ival.is_included x.add y.add && Ival.is_included x.sub y.sub + + let join x y = + { add = Ival.join x.add y.add; sub = Ival.join x.sub y.sub } + + let widen x y = + { add = Arith.widen x.add y.add; sub = Arith.widen x.sub y.sub } + + let narrow x y = + Arith.narrow x.add y.add >>- fun add -> + Arith.narrow x.sub y.sub >>-: fun sub -> {add; sub} + + (* If [swap] is true, makes a diamond about (X, Y) from a diamond + about (Y, X). *) + let reverse_variables swap t = + if swap then { t with sub = Arith.neg t.sub } else t + + (* Normalizes a diamond for the pair of variables [pair]: replaces too large + ivals by Ival.top. Returns None if both ivals are meaningless. *) + let trim pair t = + let is_top = Arith.is_top_for_pair pair in + match is_top t.add, is_top t.sub with + | true, true -> None + | true, false -> Some { t with add = Ival.top } + | false, true -> Some { t with sub = Ival.top } + | false, false -> Some t +end + + +(* Maps linking pairs of variables (X, Y) to intervals for X+Y and X-Y. *) +module Octagons = struct + module Initial_Values = struct let v = [[]] end + module Dependencies = struct let l = [ Ast.self ] end + + include Hptmap.Make (Pair) (Diamond) + (Hptmap.Comp_unused) (Initial_Values) (Dependencies) + + let internal_join = join + + let pretty fmt t = + let iter f = iter (fun k v -> f (k, v)) in + let pretty fmt (pair, diamond) = + let x, y = Pair.get pair in + let pretty_one op ival = + if not Ival.(equal top ival) + then + Format.fprintf fmt "@[@[%a %s %a@] %s @[%a@]@]@," + Variable.pretty x op Variable.pretty y + (Unicode.inset_string ()) Ival.pretty ival + in + pretty_one "+" diamond.add; + pretty_one "-" diamond.sub + in + Pretty_utils.pp_iter + ~pre:"@[<v 3>{[ " ~suf:" ]}@]" ~sep:"" + iter pretty fmt t + + let top = empty + + let is_included = + let cache = Hptmap_sig.PersistentCache "Octagons.Octagons.is_included" in + let decide_fst _ _ = true in + let decide_snd _ _ = false in + let decide_both _ x y = Diamond.is_included x y in + let decide_fast t1 t2 = decide_fast_inclusion t2 t1 in + binary_predicate cache UniversalPredicate + ~decide_fast ~decide_fst ~decide_snd ~decide_both + + exception EBottom + + let narrow_exc = + let cache = Hptmap_sig.NoCache in + let decide _pair x y = + match Diamond.narrow x y with + | `Value v -> v + | `Bottom -> raise EBottom + in + join ~cache ~symmetric:true ~idempotent:true ~decide + + let narrow x y = try `Value (narrow_exc x y) with EBottom -> `Bottom + + let simple_join = + let cache = Hptmap_sig.PersistentCache "Octagons.Octagons.join" in + let decide pair x y = Diamond.trim pair (Diamond.join x y) in + inter ~cache ~symmetric:true ~idempotent:true ~decide + + let join ~decide_left ~decide_right = + let cache = Hptmap_sig.NoCache in + let decide_left = Traversing decide_left + and decide_right = Traversing decide_right in + let decide_both pair x y = Diamond.trim pair (Diamond.join x y) in + merge ~cache ~symmetric:false ~idempotent:true + ~decide_left ~decide_right ~decide_both + + let simple_widen = + let cache = Hptmap_sig.PersistentCache "Octagons.Octagons.widen" in + let decide pair x y = Diamond.trim pair (Diamond.widen x y) in + inter ~cache ~symmetric:false ~idempotent:true ~decide + + let widen ~decide_left ~decide_right = + let cache = Hptmap_sig.NoCache in + let decide_left = Traversing decide_left + and decide_right = Traversing decide_right in + let decide_both pair x y = Diamond.trim pair (Diamond.widen x y) in + merge ~cache ~symmetric:false ~idempotent:true + ~decide_left ~decide_right ~decide_both + + let unsafe_add = add + + let add variables diamond t = + try + Diamond.narrow diamond (find variables t) >>-: fun diamond -> + add variables diamond t + with Not_found -> `Value (add variables diamond t) + + let add_octagon { variables; operation; value; } t = + let diamond = + try find variables t + with Not_found -> Diamond.top + in + let diamond = + match operation with + | Add -> + Arith.narrow diamond.add value >>-: fun add -> + { diamond with add } + | Sub -> + Arith.narrow diamond.sub value >>-: fun sub -> + { diamond with sub } + in + diamond >>-: fun diamond -> unsafe_add variables diamond t + + let evaluate octagon t = + try + let diamond = find octagon.variables t in + let ival = match octagon.operation with + | Add -> diamond.add + | Sub -> diamond.sub + in + if Ival.(equal top ival) + then None + else + let typ = (Pair.fst octagon.variables).vtype in + let ival = Arith.sub typ ival octagon.value in + Some ival + with Not_found -> None +end + +(* -------------------------------------------------------------------------- *) +(* Relations *) +(* -------------------------------------------------------------------------- *) + +(* Keep track of related variables in an octagon state. *) +module Relations = struct + module Initial_Values = struct let v = [[]] end + module Dependencies = struct let l = [ Ast.self ] end + + include Hptmap.Make (Variable) (VariableSet) + (Hptmap.Comp_unused) (Initial_Values) (Dependencies) + + let inter = + let cache = Hptmap_sig.PersistentCache "Octagons.Relations.inter" in + let decide _pair x y = + let r = Variable.Set.inter x y in + if Variable.Set.is_empty r then None else Some r + in + inter ~cache ~symmetric:true ~idempotent:true ~decide + + let union = + let cache = Hptmap_sig.PersistentCache "Octagons.Relations.union" in + let decide _pair x y = Variable.Set.union x y in + join ~cache ~symmetric:true ~idempotent:true ~decide + + (* Marks y as related to x. *) + let relate_aux x y t = + let related = + try find x t + with Not_found -> VariableSet.empty + in + let updated = VariableSet.add y related in + add x updated t + + (* Marks x and y as mutually related. *) + let relate pair t = + let x, y = Pair.get pair in + relate_aux y x (relate_aux x y t) + + let add variable set t = + if VariableSet.is_empty set + then remove variable t + else add variable set t +end + +(* -------------------------------------------------------------------------- *) +(* Non-relational intervals *) +(* -------------------------------------------------------------------------- *) + +module Intervals = struct + module Initial_Values = struct let v = [[]] end + module Dependencies = struct let l = [ Ast.self ] end + + include Hptmap.Make (Variable) (Ival) + (Hptmap.Comp_unused) (Initial_Values) (Dependencies) + + let internal_join = join + + let top = empty + + let is_included = + let cache = Hptmap_sig.PersistentCache "Octagons.Intervals.is_included" in + let decide_fst _ _ = true in + let decide_snd _ _ = false in + let decide_both _ x y = Ival.is_included x y in + let decide_fast t1 t2 = decide_fast_inclusion t2 t1 in + binary_predicate cache UniversalPredicate + ~decide_fast ~decide_fst ~decide_snd ~decide_both + + exception EBottom + + let narrow_exc = + let cache = Hptmap_sig.NoCache in + let decide _varinfo x y = + let ival = Ival.narrow x y in + if Ival.is_bottom ival then raise EBottom else ival + in + join ~cache ~symmetric:true ~idempotent:true ~decide + + let narrow x y = try `Value (narrow_exc x y) with EBottom -> `Bottom + + let join = + let cache = Hptmap_sig.PersistentCache "Octagons.Intervals.join" in + let decide _varinfo x y = + let r = Ival.join x y in + if Ival.(equal top r) then None else Some r + in + inter ~cache ~symmetric:true ~idempotent:true ~decide + + let widen = + let cache = Hptmap_sig.PersistentCache "Octagons.Intervals.widen" in + let decide _varinfo x y = + let r = Arith.widen x y in + if Ival.(equal top r) then None else Some r + in + inter ~cache ~symmetric:false ~idempotent:true ~decide +end + +(* -------------------------------------------------------------------------- *) +(* Octagon states *) +(* -------------------------------------------------------------------------- *) + +module Zone = Locations.Zone + +module State = struct + + type state = + { octagons: Octagons.t; (* The intervals for X±Y. *) + intervals: Intervals.t; (* The intervals for the variables X,Y… *) + relations: Relations.t; (* The related variables in [octagons]. *) + modified: Locations.Zone.t; (* The memory zone modified by a function. *) + } + + include Datatype.Make_with_collections + (struct + type t = state + include Datatype.Serializable_undefined + + let name = "Octagons.State" + let structural_descr = + Structural_descr.t_record + [| Octagons.packed_descr; + Intervals.packed_descr; + Relations.packed_descr; + Zone.packed_descr |] + let reprs = + [ { octagons = Octagons.top; + intervals = Intervals.empty; + relations = Relations.empty; + modified = Zone.bottom } ] + + let compare s1 s2 = + let c = Octagons.compare s1.octagons s2.octagons in + if c <> 0 then c else + let c = Intervals.compare s1.intervals s2.intervals in + if c <> 0 then c else + Zone.compare s1.modified s2.modified + + let equal = Datatype.from_compare + + let hash t = + Hashtbl.hash (Octagons.hash t.octagons, + Relations.hash t.relations, + Zone.hash t.modified) + + let pretty fmt { octagons } = + Format.fprintf fmt "@[%a@]" Octagons.pretty octagons + end) + + let pretty_debug fmt { octagons; intervals; relations } = + Format.fprintf fmt "@[<v> Octagons: %a@; Intervals: %a@; Relations: %a@]" + Octagons.pretty octagons Intervals.pretty intervals + Relations.pretty relations + + (* Verify the internal structure of a state [t], depending on the boolean + variable [debug]. *) + let check = + if not debug + then fun _ t -> t + else fun msg t -> + (* Checks that an octagon is properly registered in [t.relations]. This is + mandatory for the soundness of the domain. On the other hand, two + variables can be related in [t.relations] without an actual octagon + between them. *) + let check_octagon pair _ = + let x, y = Pair.get pair in + try VariableSet.mem x (Relations.find y t.relations) + && VariableSet.mem y (Relations.find x t.relations) + with Not_found -> false + in + if Octagons.for_all check_octagon t.octagons + then t + else + Value_parameters.abort + "Incorrect octagon state computed by function %s:@ %a" + msg pretty_debug t + + (* ------------------------------ Lattice --------------------------------- *) + + let top = + { octagons = Octagons.top; + intervals = Intervals.top; + relations = Relations.empty; + modified = Zone.top; } + + let empty () = + { octagons = Octagons.top; + intervals = Intervals.top; + relations = Relations.empty; + modified = Zone.bottom; } + + let is_included t1 t2 = + Octagons.is_included t1.octagons t2.octagons + && Intervals.is_included t1.intervals t2.intervals + && Zone.is_included t1.modified t2.modified + + let join t1 t2 = + let octagons = + if not infer_intervals + then Octagons.simple_join t1.octagons t2.octagons + else + let decide_empty intervals pair diamond = + let v1, v2 = Pair.get pair in + try + let i1 = Intervals.find v1 intervals + and i2 = Intervals.find v2 intervals in + let add = Arith.add v1.vtype i1 i2 + and sub = Arith.sub v1.vtype i1 i2 in + let diamond = Diamond.join diamond { add; sub } in + Diamond.trim pair diamond + with Not_found -> None + in + let decide_left = decide_empty t2.intervals + and decide_right = decide_empty t1.intervals in + Octagons.join ~decide_left ~decide_right t1.octagons t2.octagons + in + let relations = + if infer_intervals + then Relations.union t1.relations t2.relations + else Relations.inter t1.relations t2.relations + in + let state = + { octagons; relations; + intervals = Intervals.join t1.intervals t2.intervals; + modified = Zone.join t1.modified t2.modified; } + in + check "join" state + + let widen _kf _hints t1 t2 = + let octagons = + if not infer_intervals + then Octagons.simple_widen t1.octagons t2.octagons + else + let decide_empty b intervals pair diamond = + let v1, v2 = Pair.get pair in + try + let i1 = Intervals.find v1 intervals + and i2 = Intervals.find v2 intervals in + let add = Arith.add v1.vtype i1 i2 + and sub = Arith.sub v1.vtype i1 i2 in + let diamond = + if b + then Diamond.widen { add; sub } diamond + else Diamond.widen diamond { add; sub } + in + Diamond.trim pair diamond + with Not_found -> None + in + let decide_left = decide_empty false t2.intervals + and decide_right = decide_empty true t1.intervals in + Octagons.widen ~decide_left ~decide_right t1.octagons t2.octagons + in + let relations = + if infer_intervals + then Relations.union t1.relations t2.relations + else Relations.inter t1.relations t2.relations + in + let state = + { octagons; relations; + intervals = Intervals.widen t1.intervals t2.intervals; + modified = Zone.join t1.modified t2.modified; } + in + check "widen" state + + let narrow t1 t2 = + Octagons.narrow t1.octagons t2.octagons >>- fun octagons -> + Intervals.narrow t1.intervals t2.intervals >>- fun intervals -> + let relations = Relations.union t1.relations t2.relations in + let modified = Zone.narrow t1.modified t2.modified in + `Value { octagons; intervals; relations; modified; } + + (* -------------- Transitive closure when adding an octagon --------------- *) + + type relation = + { vars: varinfo * varinfo; + diamond: diamond; } + + let add_diamond state pair diamond = + match Diamond.trim pair diamond with + | None -> `Value state + | Some diamond -> + Octagons.add pair diamond state.octagons >>-: fun octagons -> + let relations = Relations.relate pair state.relations in + { state with octagons; relations } + + let inverse { vars; diamond } = + let var1, var2 = vars in + { vars = var2, var1; diamond = Diamond.reverse_variables true diamond } + + let transitive_relation y rel1 rel2 = + let rel1 = + if Variable.equal y (snd rel1.vars) then rel1 else inverse rel1 + and rel2 = + if Variable.equal y (fst rel2.vars) then rel2 else inverse rel2 + in + (* rel1 is about X±Y, rel2 is about Y±Z. *) + let typ = y.vtype in + (* X+Z = (X+Y) - (Y-Z) and X+Y = (X-Y) + (Y+Z) *) + let add = + Ival.narrow + (Arith.sub typ rel1.diamond.add rel2.diamond.sub) + (Arith.add typ rel1.diamond.sub rel2.diamond.add) + (* X-Z = (X+Y) - (Y+Z) and X-Z = (X-Y) + (Y-Z) *) + and sub = + Ival.narrow + (Arith.sub typ rel1.diamond.add rel2.diamond.add) + (Arith.add typ rel1.diamond.sub rel2.diamond.sub) + in + let diamond = {add; sub} in + let pair, swap = Pair.make (fst rel1.vars) (snd rel2.vars) in + let diamond = Diamond.reverse_variables swap diamond in + pair, diamond + + let saturate state x y rel1 = + try + let y_related = Relations.find y state.relations in + let y_related = VariableSet.remove x y_related in + let aux z state = + state >>- fun state -> + try + let pair, _ = Pair.make y z in + let diamond = Octagons.find pair state.octagons in + let vars = Pair.get pair in + let rel2 = { vars; diamond } in + let pair, diamond = transitive_relation y rel1 rel2 in + add_diamond state pair diamond + with Not_found -> `Value state + in + VariableSet.fold aux y_related (`Value state) + with Not_found -> `Value state + + let add_octagon state octagon = + if Arith.is_top_for_pair octagon.variables octagon.value + then `Value state + else + let state = + if saturate_octagons + then + let x, y = Pair.get octagon.variables in + let diamond = match octagon.operation with + | Add -> { add = octagon.value; sub = Ival.top } + | Sub -> { add = Ival.top; sub = octagon.value } + in + let relation = { vars = x, y; diamond } in + saturate state y x relation >>- fun state -> + saturate state x y relation + else `Value state + in + state >>- fun state -> + Octagons.add_octagon octagon state.octagons >>-: fun octagons -> + let relations = Relations.relate octagon.variables state.relations in + { state with octagons; relations } + + let remove state x = + let intervals = Intervals.remove x state.intervals in + let state = { state with intervals } in + try + let relations = Relations.find x state.relations in + let remove_one y state = + try + let yrelations = Relations.find y state.relations in + let yrelations = VariableSet.remove x yrelations in + let relations = Relations.add y yrelations state.relations in + let pair, _ = Pair.make x y in + let octagons = Octagons.remove pair state.octagons in + { state with octagons; relations } + with Not_found -> state + in + let state = VariableSet.fold remove_one relations state in + let relations = Relations.remove x state.relations in + { state with relations } + with Not_found -> state + + let related_octagons state x = + try + let related = Relations.find x state.relations in + let aux y acc = + let pair, swap = Pair.make x y in + try + let diamond = Octagons.find pair state.octagons in + let diamond = Diamond.reverse_variables swap diamond in + (y, diamond) :: acc + with Not_found -> acc + in + VariableSet.fold aux related [] + with Not_found -> [] + + (* x' = ±x - delta *) + let sub_delta ~inverse state x delta = + let intervals = Intervals.remove x state.intervals in + let state = { state with intervals } in + let x_related = Relations.find x state.relations in + let aux y state = + let pair, swap = Pair.make x y in + try + let diamond = Octagons.find pair state.octagons in + let diamond = + if inverse + then + let op = if swap then fun x -> x else Arith.neg in + { add = op diamond.sub; + sub = op diamond.add } + else diamond + in + let typ = x.vtype in + let op = if swap then Arith.add else Arith.sub in + let add = + if Ival.(equal top diamond.add) + then diamond.add + else Arith.sub typ diamond.add delta + and sub = + if Ival.(equal top diamond.sub) + then diamond.sub + else op typ diamond.sub delta + in + let diamond' = { add; sub } in + let octagons = Octagons.unsafe_add pair diamond' state.octagons in + { state with octagons } + with Not_found -> state + in + VariableSet.fold aux x_related state +end + +(* -------------------------------------------------------------------------- *) +(* Octagon domain *) +(* -------------------------------------------------------------------------- *) + +module Domain = struct + + include State + + type value = Cvalue.V.t + type location = Precise_locs.precise_location + + type origin = unit + let top_value = `Value (Cvalue.V.top, ()), Alarmset.all + + let extract_expr oracle state expr = + let evaluate_expr expr = + match fst (oracle expr) with + | `Bottom -> `Top (* should not happen *) + | `Value cvalue -> + try `Value (Cvalue.V.project_ival cvalue) + with Cvalue.V.Not_based_on_null -> `Top + in + let evaluate_octagon octagon = Octagons.evaluate octagon state.octagons in + let ival, alarms = + Rewriting.evaluate_through_octagons evaluate_expr evaluate_octagon expr + in + if Ival.(equal ival top) + then top_value + else if Ival.is_bottom ival + then `Bottom, Alarmset.all + else `Value (Cvalue.V.inject_ival ival, ()), alarms + + let extract_lval _oracle _t _lval _typ _loc = top_value + + let backward_location _t _lval _typ loc value = `Value (loc, value) + + let reduce_further state expr value = + match expr.enode with + | Lval (Var x, NoOffset) when Cil.isIntegralType x.vtype -> + begin + try + let x_ival = Cvalue.V.project_ival value in + let octagons = State.related_octagons state x in + let reduce acc (y, octagons) = + let y_ival1 = + if Ival.(equal top octagons.add) + then Ival.top + else Arith.sub x.vtype octagons.add x_ival + in + let y_ival2 = + if Ival.(equal top octagons.sub) + then Ival.top + else Arith.sub x.vtype x_ival octagons.sub + in + let y_ival = Ival.narrow y_ival1 y_ival2 in + if Ival.(equal top y_ival) then acc else + let y_enode = Lval (Var y, NoOffset) in + let y_expr = Cil.new_exp ~loc:expr.eloc y_enode in + let y_cvalue = Cvalue.V.inject_ival y_ival in + (y_expr, y_cvalue) :: acc + in + List.fold_left reduce [] octagons + with Cvalue.V.Not_based_on_null -> [] + end + | _ -> [] + + + let kill_base base state = + try + let varinfo = Base.to_varinfo base in + State.remove state varinfo + with Base.Not_a_C_variable -> state + + let kill zone state = + if Locations.Zone.(equal zone top) + then top + else + let modified = Locations.Zone.join state.modified zone in + let state = Zone.fold_bases kill_base zone state in + { state with modified } + + module Transfer + (Valuation: Abstract_domain.Valuation with type value = value + and type loc = location) + = struct + + (* Evaluation function of expressions to ival, from a [valuation]. *) + let evaluation_function valuation = fun expr -> + match Valuation.find valuation expr with + | `Top -> `Top + | `Value record -> + match record.Eval.value.v with + | `Bottom -> `Top (* TODO: why this keeps happening? *) + | `Value cvalue -> + try `Value (Cvalue.V.project_ival cvalue) + with Cvalue.V.Not_based_on_null -> `Top + + exception EBottom + + let infer_octagons evaluate expr ival state = + let octagons = Rewriting.make_octagons evaluate expr ival in + let add_octagon state octagon = + match State.add_octagon state octagon with + | `Bottom -> raise EBottom + | `Value state -> state + in + List.fold_left add_octagon state octagons + + let infer_interval expr ival state = + if not infer_intervals + then state + else + match expr.enode with + | Lval (Var varinfo, NoOffset) + when Cil.isIntegralType varinfo.vtype -> + let intervals = Intervals.add varinfo ival state.intervals in + { state with intervals } + | _ -> state + + let update valuation state = + let evaluate = evaluation_function valuation in + let aux expr record state = + let value = record.Eval.value in + match record.reductness, value.v, value.initialized, value.escaping with + | (Created | Reduced), `Value cvalue, true, false -> + begin + try + let ival = Cvalue.V.project_ival cvalue in + let state = infer_octagons evaluate expr ival state in + infer_interval expr ival state + with Cvalue.V.Not_based_on_null -> state + end + | _ -> state + in + try `Value (check "update" (Valuation.fold aux valuation state)) + with EBottom -> `Bottom + + let assign_interval varinfo assigned state = + if not infer_intervals + then state + else + match assigned with + | Assign v + | Copy (_, { v = `Value v; initialized = true; escaping = false }) -> + begin + try + let ival = Cvalue.V.project_ival v in + let intervals = Intervals.add varinfo ival state.intervals in + { state with intervals } + with Cvalue.V.Not_based_on_null -> state + end + | _ -> state + + let assign_variable varinfo expr assigned valuation state = + let evaluate = evaluation_function valuation in + (* TODO: redundant with rewrite_binop below. *) + let vars = Rewriting.rewrite evaluate expr in + let equal_varinfo v = Variable.equal varinfo v.Rewriting.varinfo in + let state = + try + let var = List.find equal_varinfo vars in + let inverse = not var.Rewriting.sign in + State.sub_delta ~inverse state varinfo var.Rewriting.coeff + with Not_found -> State.remove state varinfo + in + let state = assign_interval varinfo assigned state in + let enode = Lval (Var varinfo, NoOffset) in + let left_expr = Cil.new_exp ~loc:expr.eloc enode in + (* On the assignment X = E; if X-E can be rewritten as ±(X±Y-v), + then the octagonal constraint [X±Y ∈ v] holds. *) + let octagons = Rewriting.rewrite_binop evaluate left_expr Sub expr in + let state = + List.fold_left + (fun acc (_sign, octagon) -> + acc >>- fun state -> State.add_octagon state octagon) + (`Value state) octagons + in + state >>-: check "precise assign" + + let assign _kinstr left_value expr assigned valuation state = + update valuation state >>- fun state -> + match left_value.lval with + | Var varinfo, NoOffset when Cil.isIntegralType varinfo.vtype -> + assign_variable varinfo expr assigned valuation state + | _ -> + let written_loc = Precise_locs.imprecise_location left_value.lloc in + let written_zone = + Locations.(enumerate_valid_bits Write written_loc) + in + let state = kill written_zone state in + `Value (check "imprecise assign" state) + + let assume _stmt _exp _bool = update + + let start_call _stmt call valuation state = + if intraprocedural () + then `Value (empty ()) + else + let state = { state with modified = Locations.Zone.bottom } in + let assign_formal state { formal; concrete; avalue } = + state >>- assign_variable formal concrete avalue valuation + in + List.fold_left assign_formal (`Value state) call.arguments + + let finalize_call _stmt _call ~pre ~post = + if intraprocedural () + then `Value (kill post.modified pre) + else + let modified = Locations.Zone.join post.modified pre.modified in + `Value { post with modified } + + let show_expr _valuation _state _fmt _expr = () + end + + let logic_assign _logic_assign location ~pre:_ state = + let loc = Precise_locs.imprecise_location location in + let zone = Locations.(enumerate_valid_bits Write loc) in + let state = kill zone state in + check "logic_assign" state + + let evaluate_predicate _env _state _pred = Alarmset.Unknown + let reduce_by_predicate _env state _pred _positive = `Value state + + let enter_scope _kf _varinfos state = state + let leave_scope _kf varinfos state = + let state = List.fold_left State.remove state varinfos in + check "leave_scope" state + + let enter_loop _stmt state = state + let incr_loop_counter _stmt state = state + let leave_loop _stmt state = state + + let introduce_globals _varinfos state = state + let initialize_variable _lval _location ~initialized:_ _value state = state + let initialize_variable_using_type _kind _varinfo state = state + + let relate _kf bases state = + if intraprocedural () + then Base.SetLattice.empty + else + let aux base acc = + try + let varinfo = Base.to_varinfo base in + let varset = Relations.find varinfo state.relations in + let baseset = + VariableSet.fold + (fun vi acc -> Base.Hptset.add (Base.of_varinfo vi) acc) + varset Base.Hptset.empty + in + Base.SetLattice.(join (inject baseset) acc) + with Base.Not_a_C_variable | Not_found -> acc + in + Base.Hptset.fold aux bases Base.SetLattice.empty + + let filter _kf _kind bases state = + if intraprocedural () + then state + else + let mem_vi varinfo = Base.Hptset.mem (Base.of_varinfo varinfo) bases in + let mem_pair pair = + let x, y = Pair.get pair in + mem_vi x && mem_vi y + in + let octagons = Octagons.filter mem_pair state.octagons in + let intervals = Intervals.filter mem_vi state.intervals in + let relations = Relations.filter mem_vi state.relations in + { state with octagons; intervals; relations; } + + let reuse = + let cache = Hptmap_sig.PersistentCache "Octagons.reuse" + and symmetric = false + and idempotent = true + and decide _key left _right = left in + let join_oct = Octagons.internal_join ~cache ~symmetric ~idempotent ~decide + and join_itv = Intervals.internal_join ~cache ~symmetric ~idempotent ~decide + and join_rel = Relations.union in + fun _kf _bases ~current_input ~previous_output -> + if intraprocedural () + then previous_output + else + let current_input = kill previous_output.modified current_input in + let prev_output = previous_output in + check "reuse result" + { octagons = join_oct prev_output.octagons current_input.octagons; + intervals = join_itv prev_output.intervals current_input.intervals; + relations = join_rel prev_output.relations current_input.relations; + modified = current_input.modified } + + let name = "Octagon domain" + let log_category = Value_parameters.register_category "d-octagon" + + let storage () = true +end + +include Domain_builder.Complete (Domain) diff --git a/src/plugins/value/domains/octagons.mli b/src/plugins/value/domains/octagons.mli new file mode 100644 index 0000000000000000000000000000000000000000..88ba3269a6afbba3a7785bf5e4b4dc903a1969b9 --- /dev/null +++ b/src/plugins/value/domains/octagons.mli @@ -0,0 +1,25 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +include Abstract_domain.Leaf + with type value = Cvalue.V.t + and type location = Precise_locs.precise_location diff --git a/src/plugins/value/engine/abstractions.ml b/src/plugins/value/engine/abstractions.ml index 5781d60bf7672faf0129790ab98f89cde419dd68..4261513ad85956b5344086030abbb39c7cef4759 100644 --- a/src/plugins/value/engine/abstractions.ml +++ b/src/plugins/value/engine/abstractions.ml @@ -98,6 +98,7 @@ module Config = struct let cvalue = make 9 "cvalue" CvalueDomain.get (module Cvalue_domain.State) let gauges = make 6 "gauges" GaugesDomain.get (module Gauges_domain.D) + let octagon = make 6 "octagon" OctagonDomain.get (module Octagons) let inout = make 5 "inout" InoutDomain.get (module Inout_domain.D) let traces = make 2 "traces" TracesDomain.get (module Traces_domain.D) let printer = make 2 "printer" PrinterDomain.get (module Printer_domain) diff --git a/src/plugins/value/engine/abstractions.mli b/src/plugins/value/engine/abstractions.mli index 4c2909dbb757e52966e0dab66ec42e86473b87b2..3d4ebe9e437fdf5e913e368f9a5a9a0976ac5d69 100644 --- a/src/plugins/value/engine/abstractions.mli +++ b/src/plugins/value/engine/abstractions.mli @@ -132,6 +132,7 @@ module Config : sig val equality: flag val symbolic_locations: flag val gauges: flag + val octagon: flag val bitwise: flag val inout: flag val sign: flag diff --git a/src/plugins/value/engine/mem_exec.ml b/src/plugins/value/engine/mem_exec.ml index 17adb02719337ef16ce67e9b106b1ac74647c4e8..83629ab5fc926f6d2d59ee2a77e93208b3df5d6a 100644 --- a/src/plugins/value/engine/mem_exec.ml +++ b/src/plugins/value/engine/mem_exec.ml @@ -240,18 +240,22 @@ module Make raise [Result_found] when this execution exists, or do nothing. *) let find_match_in_previous kf (map_inputs: InputBasesToCallEffect.t) state = let aux_previous_call binputs hstates = - (* restrict [state] to the inputs of this call *) - let st_filtered = Domain.filter kf `Pre binputs state in - try - let bases, outputs, i = Domain.Hashtbl.find hstates st_filtered in - (* We have found a previous execution, in which the outputs are - [outputs]. Copy them in [state] and return this result. *) - let process output = - Domain.reuse kf bases ~current_input:state ~previous_output:output - in - let outputs = List.map process outputs in - raise (Result_found (outputs, i)) - with Not_found -> () + let brelated = Domain.relate kf binputs state in + if not Base.SetLattice.(is_included brelated (inject binputs)) + then () + else + (* restrict [state] to the inputs of this call *) + let st_filtered = Domain.filter kf `Pre binputs state in + try + let bases, outputs, i = Domain.Hashtbl.find hstates st_filtered in + (* We have found a previous execution, in which the outputs are + [outputs]. Copy them in [state] and return this result. *) + let process output = + Domain.reuse kf bases ~current_input:state ~previous_output:output + in + let outputs = List.map process outputs in + raise (Result_found (outputs, i)) + with Not_found -> () in Base.Hptset.Hashtbl.iter aux_previous_call map_inputs diff --git a/src/plugins/value/legacy/eval_terms.ml b/src/plugins/value/legacy/eval_terms.ml index 35f3c5c6ac8f1294f13ae513e625884ac38f6d30..089f3c93a5eadaca570d79802bec072a5d689b64 100644 --- a/src/plugins/value/legacy/eval_terms.ml +++ b/src/plugins/value/legacy/eval_terms.ml @@ -446,9 +446,13 @@ let einteger v = (* Note: some reals cannot be exactly represented as floats; in which case we do not know their under-approximation. *) -let ereal v = +let efloating_point etype fval = + let v = V.inject_float fval in let eunder = under_from_over v in - { etype = Cil.doubleType; eunder; eover = v; ldeps = empty_logic_deps } + { etype; eunder; eover = v; ldeps = empty_logic_deps } + +let ereal = efloating_point Cil.doubleType +let efloat = efloating_point Cil.floatType let is_true = function | `True | `TrueReduced _ -> true @@ -637,6 +641,8 @@ let known_logic_funs = [ let known_predicates = [ "\\warning", ACSL; "\\is_finite", ACSL; + "\\is_plus_infinity", ACSL; + "\\is_minus_infinity", ACSL; "\\is_NaN", ACSL; "\\eq_float", ACSL; "\\ne_float", ACSL; @@ -719,11 +725,14 @@ let rec eval_term ~alarm_mode env t = | _ -> ast_error "non-evaluable constant") | TConst (LChr c) -> einteger (Cvalue.V.inject_int (Cil.charConstToInt c)) - | TConst (LReal { r_lower ; r_upper }) -> begin - let r_lower = Fval.F.of_float r_lower in - let r_upper = Fval.F.of_float r_upper in - let f = Fval.inject Fval.Real r_lower r_upper in - ereal (V.inject_ival (Ival.inject_float f)) + | TConst (LReal { r_nearest; r_lower ; r_upper }) -> begin + if Fc_float.is_nan r_nearest + then ereal Fval.nan + else + let r_lower = Fval.F.of_float r_lower in + let r_upper = Fval.F.of_float r_upper in + let f = Fval.inject Fval.Real r_lower r_upper in + ereal f end (* | TConst ((CStr | CWstr) Missing cases *) @@ -742,9 +751,15 @@ let rec eval_term ~alarm_mode env t = eunder = loc_bits_to_loc_bytes_under r.eunder; eover = loc_bits_to_loc_bytes r.eover } - (* Special case for the constants \pi and \e. *) - | TLval (TVar {lv_name = "\\pi"}, _) -> ereal (V.inject_float Fval.pi) - | TLval (TVar {lv_name = "\\e"}, _) -> ereal (V.inject_float Fval.e) + (* Special case for the constants \pi, \e, \infinity and \NaN. *) + | TLval (TVar {lv_name = "\\pi"}, _) -> ereal Fval.pi + | TLval (TVar {lv_name = "\\e"}, _) -> ereal Fval.e + | TLval (TVar {lv_name = "\\plus_infinity"}, _) -> + efloat Fval.(pos_infinity Single) + | TLval (TVar {lv_name = "\\minus_infinity"}, _) -> + efloat Fval.(neg_infinity Single) + | TLval (TVar {lv_name = "\\NaN"}, _) -> efloat Fval.nan + | TLval _ -> let lval = eval_tlval ~alarm_mode env t in let typ = lval.etype in @@ -1271,7 +1286,6 @@ and eval_known_logic_function ~alarm_mode env li labels args = | "\\max", Some Lreal, _, [t1; t2] -> let backward = Cvalue.V.backward_comp_float_left_true Comp.Ge Fval.Real in eval_extremum Cil.doubleType backward ~alarm_mode env t1 t2 - | _ -> assert false and eval_float_builtin_arity2 ~alarm_mode env name arg1 arg2 = @@ -1747,53 +1761,67 @@ let rec reduce_by_relation ~alarm_mode env positive t1 rel t2 = May raise LogicEvalError or Not_an_exact_loc, when no reduction can be done, and Reduce_to_bottom, in which case the reduction leads to bottom. *) let reduce_by_known_papp ~alarm_mode env positive li _labels args = - match positive, li.l_var_info.lv_name, args with - | true, "\\is_finite", [arg] - | false, "\\is_NaN", [arg] -> begin - let fval_reduce = - (* positive is true for is_finite, false for is_NaN. *) - if positive - then Fval.backward_is_finite - else (fun _fkind -> Fval.backward_is_not_nan) - in - try - let alarm_mode = alarm_reduce_mode () in - let typ_loc, locs = eval_term_as_exact_locs ~alarm_mode env arg in - let aux loc env = - let state = env_current_state env in - let v = find_or_alarm ~alarm_mode state loc in - let v = Cvalue_forward.reinterpret typ_loc v in - let v = match Cil.unrollType typ_loc with - | TFloat (fkind,_) -> begin - let v = Cvalue.V.project_float v in - let kind = Fval.kind fkind in - match fval_reduce kind v with - | `Value f -> V.inject_float f - | `Bottom -> V.bottom - end - | _ -> (* Better safe than sorry, we may have e.g. en int location - here *) - raise Not_an_exact_loc - in - let state' = Cvalue.Model.reduce_previous_binding state loc v in - overwrite_current_state env state' + (* If the term [arg] is a floating-point lvalue with an exact location, + reduces its value in [env] by using the backward propagator on fval + [fval_reduce]. *) + let reduce_float fval_reduce arg = + try + let typ_loc, locs = eval_term_as_exact_locs ~alarm_mode env arg in + let aux loc env = + let state = env_current_state env in + let v = find_or_alarm ~alarm_mode state loc in + let v = Cvalue_forward.reinterpret typ_loc v in + let v = match Cil.unrollType typ_loc with + | TFloat (fkind,_) -> begin + let v = Cvalue.V.project_float v in + let kind = Fval.kind fkind in + match fval_reduce kind v with + | `Value f -> V.inject_float f + | `Bottom -> V.bottom + end + | _ -> (* Better safe than sorry, we may have e.g. en int location + here *) + raise Not_an_exact_loc in - Eval_op.apply_on_all_locs aux locs env - with Cvalue.V.Not_based_on_null -> env - end - | _ , ("\\eq_float" | "\\eq_double"), [t1;t2] -> + let state' = Cvalue.Model.reduce_previous_binding state loc v in + overwrite_current_state env state' + in + Eval_op.apply_on_all_locs aux locs env + with Cvalue.V.Not_based_on_null -> env + in + (* Reduces [f] to positive or negative infinity (according to [pos]), + or to the complement if [positive] is false. *) + let reduce_by_infinity ~pos prec f = + let inf = if pos then Fval.pos_infinity prec else Fval.neg_infinity prec in + let fval = + if positive + then inf + else Fval.(join nan (join (Fval.neg inf) (top_finite prec))) + in + Fval.narrow fval f + in + match li.l_var_info.lv_name, args with + | "\\is_finite", [arg] -> + reduce_float (Fval.backward_is_finite ~positive) arg + | "\\is_plus_infinity", [arg] -> + reduce_float (reduce_by_infinity ~pos:true) arg + | "\\is_minus_infinity", [arg] -> + reduce_float (reduce_by_infinity ~pos:false) arg + | "\\is_NaN", [arg] -> + reduce_float (fun _fkind -> Fval.backward_is_nan ~positive) arg + | ("\\eq_float" | "\\eq_double"), [t1;t2] -> reduce_by_relation ~alarm_mode env positive t1 Req t2 - | _ , ("\\ne_float" | "\\ne_double"), [t1;t2] -> + | ("\\ne_float" | "\\ne_double"), [t1;t2] -> reduce_by_relation ~alarm_mode env positive t1 Rneq t2 - | _ , ("\\lt_float" | "\\lt_double"), [t1;t2] -> + | ("\\lt_float" | "\\lt_double"), [t1;t2] -> reduce_by_relation ~alarm_mode env positive t1 Rlt t2 - | _ , ("\\le_float" | "\\le_double"), [t1;t2] -> + | ("\\le_float" | "\\le_double"), [t1;t2] -> reduce_by_relation ~alarm_mode env positive t1 Rle t2 - | _ , ("\\gt_float" | "\\gt_double"), [t1;t2] -> + | ("\\gt_float" | "\\gt_double"), [t1;t2] -> reduce_by_relation ~alarm_mode env positive t1 Rgt t2 - | _ , ("\\ge_float" | "\\ge_double"), [t1;t2] -> + | ("\\ge_float" | "\\ge_double"), [t1;t2] -> reduce_by_relation ~alarm_mode env positive t1 Rge t2 - | true, "\\subset", [argl;argr] -> + | "\\subset", [argl;argr] when positive -> let alarm_mode = alarm_reduce_mode () in let vr = (eval_term ~alarm_mode env argr).eover in let _typ, locsl = eval_term_as_exact_locs ~alarm_mode env argl in @@ -2274,6 +2302,12 @@ and eval_predicate env pred = in match li.l_var_info.lv_name, args with | "\\is_finite", [arg] -> unary_float Fval.is_finite arg + | "\\is_plus_infinity", [arg] -> + let pos_inf = Fval.pos_infinity Float_sig.Single in + unary_float (fun f -> Fval.forward_comp Comp.Eq f pos_inf) arg + | "\\is_minus_infinity", [arg] -> + let neg_inf = Fval.neg_infinity Float_sig.Single in + unary_float (fun f -> Fval.forward_comp Comp.Eq f neg_inf) arg | "\\is_NaN", [arg] -> inv_truth (unary_float Fval.is_not_nan arg) | ("\\eq_float" | "\\eq_double"), [arg1;arg2] -> fval_cmp Comp.Eq arg1 arg2 | ("\\ne_float" | "\\ne_double"), [arg1;arg2] -> fval_cmp Comp.Ne arg1 arg2 diff --git a/src/plugins/value/partitioning/auto_loop_unroll.ml b/src/plugins/value/partitioning/auto_loop_unroll.ml new file mode 100644 index 0000000000000000000000000000000000000000..37e2b81bbcb2bc8aa15f66167cb37d4ac62fd1e4 --- /dev/null +++ b/src/plugins/value/partitioning/auto_loop_unroll.ml @@ -0,0 +1,452 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(* Heuristic for automatic loop unrolling: when the number of iterations of a + loop can be bounded under a given limit, then unroll the loop. + The limit is defined by the option -eva-auto-loop-unroll. *) + +(* Gist of the heuristic: + - find a loop exit condition, in the form of a statement "if(cond) break;". + such that exactly one lvalue [lval] in the condition [cond] is modified + within the loop; all other lvalues must be constant in the loop. + - find a value [v_exit] such that [lval] ∈ [v_exit] ⇒ [cond] holds. + - evaluate [lval] to its initial value [v_init] in the loop entry state. + - compute an over-approximation of the increment [v_delta] of [lval] in one + iteration of the loop. + + If [v_init] + k × [v_delta] ⊂ [v_exit], then the number of iterations + is bounded by the limit [k]. + + The heuristic is syntactic and limited to the current function: it does not + handle assignment through pointers or function calls. + Thus, the condition [cond] should only contains direct accesses to variables + whose address is never taken (they cannot be modified through pointers). If + the loop contains a function call, the condition [cond] should not contain + global variables (as they may be modified in the function called). + A first analyze of the loop gathers all such variables modified within the + loop; all others are constant, and can be evaluated in the loop entry state. + + When computing the increment [v_delta] of a lvalue [v] in the loop, the + heuristic searches assignments "v = v ± i;". Any other assignment of [v] + cancels the heuristic. *) + +open Cil_types + +(* Is a statement a loop exit condition? If so, returns the condition and + whether the condition must hold to exit the loop. Otherwise, returns None. *) +let is_conditional_break stmt = + match stmt.skind with + | If (cond, {bstmts=[{skind=Break _}]}, _, _) -> Some (cond, true) + | If (cond, _, {bstmts=[{skind=Break _}]}, _) -> Some (cond, false) + | _ -> None + +(* Returns a loop exit condition, as the conditional expression and whether + the condition must be zero or non-zero to exit the loop. *) +let find_loop_exit_condition loop = + let rec aux = function + | [] -> None + | stmt :: tl -> + match is_conditional_break stmt with + | Some _ as x -> x + | None -> aux tl + in + aux loop.bstmts + +(* Effects of a loop: + - set of varinfos that are directly modified within the loop. Pointer + accesses are ignored. + - does the loop contain a call? If so, any global variable may also be + modified in the loop. *) +type loop_effect = + { written_vars: Cil_datatype.Varinfo.Set.t; + call: bool; } + +(* Visitor to compute the effects of a loop. *) +let loop_effect_visitor = object (self) + inherit Visitor.frama_c_inplace + + val mutable written_vars = Cil_datatype.Varinfo.Set.empty + val mutable call = false + val mutable assembly = false + + (* Returns None if the loop contains assembly code. *) + method compute_effect block = + written_vars <- Cil_datatype.Varinfo.Set.empty; + call <- false; + assembly <- false; + ignore Visitor.(visitFramacBlock (self :> frama_c_inplace) block); + if assembly then None else Some { written_vars; call; } + + method !vinst instr = + let () = match instr with + | Set ((Var varinfo, _), _, _) + | Call (Some (Var varinfo, _), _, _, _) -> + written_vars <- Cil_datatype.Varinfo.Set.add varinfo written_vars; + | _ -> () + in + let () = match instr with + | Asm _ -> assembly <- true + | Call _ -> call <- true + | _ -> () + in + Cil.SkipChildren +end + +(* The status of a lvalue for the automatic loop unroll heuristic. *) +type var_status = + | Constant (* The lvalue is probably constant within the loop. *) + | Candidate (* The lvalue is a good candidate for the heuristic: + integer type, access to a varinfo whose address is not taken, + modified within the loop but not in another function called + in the loop. *) + | Unsuitable (* Cannot be used for the heuristic. *) + +let is_integer lval = Cil.isIntegralType (Cil.typeOfLval lval) + +(* Computes the status of a lvalue for the heuristic, according to the + loop effects. *) +let classify loop_effect lval = + let rec is_const_expr expr = + match expr.enode with + | Lval lval -> classify_lval lval = Constant + | UnOp (_, e, _) | CastE (_, e) | Info (e, _) -> is_const_expr e + | BinOp (_, e1, e2, _) -> is_const_expr e1 && is_const_expr e2 + | Const _ | SizeOf _ | SizeOfE _ | SizeOfStr _ + | AlignOf _ | AlignOfE _ | AddrOf _ | StartOf _ -> true + and classify_lval = function + | Var varinfo, offset -> + if (varinfo.vglob && loop_effect.call) + || not (is_const_offset offset) + then Unsuitable + else if Cil_datatype.Varinfo.Set.mem varinfo loop_effect.written_vars + then + if is_integer lval && not varinfo.vaddrof then Candidate else Unsuitable + else + (* If the address of the variable is taken, it could be modified within + the loop. We suppose here that this is not the case, but this could + lead to some loop unrolling. *) + Constant + | Mem _, _ -> Unsuitable (* Pointers are not supported by the heuristic. *) + and is_const_offset = function + | NoOffset -> true + | Field (_, offset) -> is_const_offset offset + | Index (e, offset) -> is_const_expr e && is_const_offset offset + in + classify_lval lval + +(* Returns the list of all lvalues appearing in an expression. *) +let rec get_lvalues expr = + match expr.enode with + | Lval lval -> [ lval ] + | UnOp (_, e, _) | CastE (_, e) | Info (e, _) -> get_lvalues e + | BinOp (_op, e1, e2, _typ) -> get_lvalues e1 @ get_lvalues e2 + | Const _ | SizeOf _ | SizeOfE _ | SizeOfStr _ + | AlignOf _ | AlignOfE _ | AddrOf _ | StartOf _ -> [] + +(* Finds the unique candidate lvalue for the automatic loop unrolling + heuristic in the expression [expr], if it exists. Returns None otherwise. *) +let find_lonely_candidate loop_effect expr = + let lvalues = get_lvalues expr in + let rec aux acc list = + match list with + | [] -> acc + | lval :: tl -> + match classify loop_effect lval with + | Unsuitable -> None + | Constant -> aux acc tl + | Candidate -> if acc = None then aux (Some lval) tl else None + in + aux None lvalues + +(* Returns true if the instruction assigns [lval]. *) +let is_safe_instruction lval = function + | Set (lv, _, _) + | Call (Some lv, _, _, _) -> not (Cil_datatype.LvalStructEq.equal lval lv) + | Call (None, _, _, _) | Local_init _ | Skip _ | Code_annot _ -> true + | Asm _ -> false + +(* Returns true if the statement may assign [lval] during an iteration of the + loop [loop]. [lval] is a candidate for the automatic loop unroll heuristic, + and thus is modified within the loop. *) +let is_safe lval ~loop stmt = + (* The current block being checked for a goto statement. *) + let current_block = ref None in + let rec is_safe_stmt stmt = + match stmt.skind with + | Instr instr -> is_safe_instruction lval instr + | Return _ | Break _ | Continue _ -> true + | If (_, b_then, b_else, _) -> is_safe_block b_then && is_safe_block b_else + | Block b + | Switch (_, b, _, _) + | Loop (_, b, _, _, _) -> is_safe_block b + | UnspecifiedSequence list -> + List.for_all (fun (stmt, _, _, _, _) -> is_safe_stmt stmt) list + | Goto (dest, _) -> begin + let dest_blocks = Kernel_function.find_all_enclosing_blocks !dest in + (* If the goto leaves the loop, then it is safe. *) + if List.mem loop dest_blocks then true else + (* If the goto moves into the block currently being checked, then it + is safe if the block is safe (which we are currently checking). *) + match !current_block with + | Some current_block when List.mem current_block dest_blocks -> true + | _ -> + (* Otherwise, we need to check that the whole block englobing + both the source and the destination of the goto is safe. *) + let block = Kernel_function.common_block !dest stmt in + current_block := Some block; + (* If this block is the loop itself, then it is not safe, as [lval] + is modified within the loop. *) + not (block = loop) && is_safe_block block + end + | _ -> false + (* A block is safe if all its statements are safe. *) + and is_safe_block block = List.for_all is_safe_stmt block.bstmts in + is_safe_stmt stmt + + +module Make (Abstract: Abstractions.Eva) = struct + + open Eval + open Abstract + module Valuation = Abstract.Eval.Valuation + module Clear_Valuation = Clear_Valuation (Valuation) + + let (>>) v f = match v with `Value v -> f v | _ -> None + let (>>=) v f = match v with Some v -> f v | None -> None + + let cvalue_complement typ cvalue = + let open Eval_typ in + match Eval_typ.classify_as_scalar typ with + | Some (TSFloat _ | TSPtr _) | None -> None + | Some (TSInt ik) -> + try + let ival = Cvalue.V.project_ival cvalue in + Ival.complement_int_under ~size:ik.i_bits ~signed:ik.i_signed ival + >> fun ival -> Some (Cvalue.V.inject_ival ival) + with Cvalue.V.Not_based_on_null -> None + + (* Reduces the condition "[condition] = [positive]" to a sufficient hypothesis + on the value of the expression [expr]: computes a value [v] such that + if the expression [expr] evaluates to [v], then [condition] = [positive]. + [valuation] contains additional hypotheses, i.e. the value of some constant + lvalues of the [condition]. All computations must be done in the top state + and in the given valuation. *) + let reduce_to_expr valuation ~expr ~condition ~positive = + let state = Abstract.Dom.top in + (* Reduces [expr] by assuming that [condition] is [positive]. *) + let reduce positive = + (* Assumes that [condition] is [positive]. *) + fst (Eval.reduce ~valuation state condition positive) >> fun valuation -> + (* Finds the value of [expr] in the resulting valuation. *) + Valuation.find valuation expr >> fun record -> + record.value.v >> fun value -> + (* If the new value of [expr] is top, no reduction has been performed. *) + if Val.(equal top value) then None else Some (value, record) + in + (* Different strategies whether cvalue is present. *) + match Val.get Main_values.CVal.key with + | Some get_cvalue -> + (* Assumes that [condition] is NOT [positive]. *) + reduce (not positive) >>= fun (value, _record) -> + (* [value] is an over-approximation of the values of [expr] for which + [condition] is NOT positive; its complement is an under-approximation + of the values for which [condition] is positive. *) + let cvalue = get_cvalue value in + cvalue_complement (Cil.typeOf expr) cvalue >>= fun cvalue -> + Some (Val.set Main_values.CVal.key cvalue Val.top) + | None -> + (* Assumes that [condition] is [positive]. Returns an over-approximation + of the values for which [condition] is [positive]. *) + reduce positive >>= fun (value, record) -> + (* Evaluates [condition] with the hypothesis [expr] ∈ [value], to check + whether [expr] ∈ [value] ⇒ [condition] = [positive]. *) + let valuation = Valuation.add valuation expr record in + fst (Eval.evaluate ~valuation ~reduction:false state condition) + >> fun (_valuation, v) -> + let satisfied = + if positive + then not Val.(is_included zero v) + else Val.(equal zero v) + in + if satisfied then Some value else None + + (* Same as [reduce_to_expr] above, but builds the proper valuation from the + [state]. [state] is the entry state of the loop, and [expr] is the only + part of [condition] that is not constant within the loop. [state] can thus + be used to evaluate all other subparts of [condition], before computing + the value of [expr] that satisfies [condition]. *) + let reduce_to_lval_from_state state lval condition positive = + let expr = Cil.new_exp ~loc:condition.eloc (Lval lval) in + (* Evaluate the [condition] in the given [state]. *) + fst (Eval.evaluate state condition) >> fun (valuation, _v) -> + (* In the resulting valuation, replace the value of [expr] by [top_int] + and removes all expressions depending on [expr]. *) + Valuation.find valuation expr >> fun record -> + let value = { record.value with v = `Value Val.top_int } in + let record = { record with value } in + let valuation = + Clear_Valuation.clear_englobing_exprs + valuation ~expr:condition ~subexpr:expr + in + let valuation = Valuation.add valuation expr record in + reduce_to_expr valuation ~expr ~condition ~positive + + (* Over-approximation of the increment of a lvalue in one loop iteration.*) + type delta = + { current: Val.t or_bottom; (* current delta being computed*) + final: Val.t or_bottom; (* final delta after a continue statement. *) + } + + let join_delta d1 d2 = + { current = Bottom.join Val.join d1.current d2.current; + final = Bottom.join Val.join d1.final d2.final; } + + let final_delta delta = Bottom.join Val.join delta.current delta.final + + (* Raised when no increment can be computed for the given lvalue in one + loop iteration. *) + exception NoIncrement + + (* Adds or subtracts the integer value of [expr] to the current delta + [delta.current], according to [binop] which can be PlusA or MinusA. + Raises NoIncrement if [expr] is not a constant integer expression. *) + let add_to_delta binop delta expr = + let typ = Cil.typeOf expr in + match Cil.constFoldToInt expr with + | None -> raise NoIncrement + | Some i -> + let value = Val.inject_int typ i in + let current = match delta.current with + | `Bottom -> `Value value + | `Value v -> Val.forward_binop typ binop v value + in + { delta with current } + + (* Adds to [delta] the increment from the assignement of [lval] to the value + of [expr]. Raises NoIncrement if this is not an increment of [lval]. *) + let rec delta_assign lval delta expr = + (* Is the expression [e] equal to the lvalue [lval] (modulo cast)? *) + let rec is_lval e = match e.enode with + | Lval lv -> Cil_datatype.LvalStructEq.equal lval lv + | CastE (typ, e) -> Cil.isIntegralType typ && is_lval e + | Info (e, _) -> is_lval e + | _ -> false + in + match expr.enode with + | BinOp ((PlusA | MinusA) as binop, e1, e2, _) -> + if is_lval e1 + then add_to_delta binop delta e2 + else if is_lval e2 && binop = PlusA + then add_to_delta binop delta e1 + else raise NoIncrement + | CastE (typ, e) when Cil.isIntegralType typ -> delta_assign lval delta e + | Info (e, _) -> delta_assign lval delta e + | _ -> raise NoIncrement + + let delta_instruction lval delta = function + | Set (lv, expr, _loc) -> + if Cil_datatype.LvalStructEq.equal lval lv + then delta_assign lval delta expr + else delta + | Call (Some lv, _, _, _) -> + if Cil_datatype.LvalStructEq.equal lval lv + then raise NoIncrement (* No increment can be computed for a call. *) + else delta + | Call (None, _, _, _) | Local_init _ | Skip _ | Code_annot _ -> delta + | Asm _ -> raise NoIncrement + + (* Computes an over-approximation of the increment of [lval] in the block + [loop]. Only syntactic assignments of [lval] are considered, so [lval] + should be a direct access to a variable whose address is not taken, + and which should not be global if the loop contains function calls. + Returns None if no increment can be computed. *) + let compute_delta lval loop = + let rec delta_stmt acc stmt = + match stmt.skind with + | Instr instr -> delta_instruction lval acc instr + | Break _ -> + (* No increment, as the statement leaves the loop. *) + { current = `Bottom; final = `Bottom } + | Continue _ -> + (* The current increment becomes the final increment. *) + { current = `Bottom; final = final_delta acc } + | If (_e, b1, b2, _loc) -> + join_delta (delta_block acc b1) (delta_block acc b2) + | Block b -> delta_block acc b + | _ -> + (* For other statements, we only check that they do not modify [lval]. *) + if is_safe lval ~loop stmt then acc else raise NoIncrement + and delta_block acc block = + List.fold_left delta_stmt acc block.bstmts + in + try + let zero_delta = { current = `Value Val.zero; final = `Bottom; } in + let delta = delta_block zero_delta loop in + final_delta delta >> fun d -> Some d + with NoIncrement -> None + + (* Evaluates the lvalue [lval] in the state [state]. Returns None if the value + may be undeterminate. *) + let evaluate_lvalue state lval = + fst (Eval.copy_lvalue state lval) >> fun (_valuation, flagged_value) -> + if not flagged_value.initialized || flagged_value.escaping + then None + else flagged_value.v >> fun v -> Some v + + (* Is the number of iterations of a loop bounded by [limit]? + [state] is the loop entry state, and [loop_block] the block of the loop. *) + let is_bounded_loop state limit loop_block = + (* Computes the effect of the loop. Stops if it contains assembly code. *) + loop_effect_visitor#compute_effect loop_block >>= fun loop_effect -> + (* Finds the first loop exit condition, or stops. *) + find_loop_exit_condition loop_block >>= fun (condition, positive) -> + (* Finds the unique integer lvalue modified within the loop in [condition]. + Stops if it does not exist is not a good candidate for the heuristic. *) + find_lonely_candidate loop_effect condition >>= fun lval -> + (* Reduce [condition] to a sufficient hypothesis over the [lval] value: + if [lval] ∈ [v_exit] then [condition = positive]. *) + reduce_to_lval_from_state state lval condition positive >>= fun v_exit -> + (* Evaluates the initial value [v_init] of [lval] in the loop entry state. *) + evaluate_lvalue state lval >>= fun v_init -> + (* Computes an over-approximation [v_delta] of the increment of [lval] + in one iteration of the loop. *) + compute_delta lval loop_block >>= fun v_delta -> + let typ = Cil.typeOfLval lval in + let limit = Val.inject_int typ (Integer.of_int limit) in + (* Checks whether [v_init] + [limit] × [v_delta] ⊂ [v_exit]. *) + let binop op v1 v2 = Bottom.non_bottom (Val.forward_binop typ op v1 v2) in + let value = binop PlusA v_init (binop Mult limit v_delta) in + Some (Val.is_included value v_exit) + + (* Computes an automatic loop unrolling for statement [stmt] in state [state], + with a maximum limit. Returns None for no automatic loop unrolling. *) + let compute ~max_unroll state stmt = + try + let kf = Kernel_function.find_englobing_kf stmt in + let loop_stmt = Kernel_function.find_enclosing_loop kf stmt in + match loop_stmt.skind with + | Loop (_code_annot, block, _loc, _, _) -> + is_bounded_loop state max_unroll block >>= fun bounded -> + if bounded then Some max_unroll else None + | _ -> None + with Not_found -> None +end diff --git a/src/plugins/value/partitioning/auto_loop_unroll.mli b/src/plugins/value/partitioning/auto_loop_unroll.mli new file mode 100644 index 0000000000000000000000000000000000000000..e16a7ec2e1d1f7e3567de026e8d35441c9e1cd75 --- /dev/null +++ b/src/plugins/value/partitioning/auto_loop_unroll.mli @@ -0,0 +1,30 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2019 *) +(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* alternatives) *) +(* *) +(* you can redistribute it and/or modify it under the terms of the GNU *) +(* Lesser General Public License as published by the Free Software *) +(* Foundation, version 2.1. *) +(* *) +(* It is distributed in the hope that it will be useful, *) +(* but WITHOUT ANY WARRANTY; without even the implied warranty of *) +(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) +(* GNU Lesser General Public License for more details. *) +(* *) +(* See the GNU Lesser General Public License version 2.1 *) +(* for more details (enclosed in the file licenses/LGPLv2.1). *) +(* *) +(**************************************************************************) + +(** Heuristic for automatic loop unrolling. *) + +module Make (Abstract: Abstractions.Eva) : sig + + val compute: + max_unroll:int -> Abstract.Dom.t -> Cil_types.stmt -> int option + +end diff --git a/src/plugins/value/engine/partition.ml b/src/plugins/value/partitioning/partition.ml similarity index 96% rename from src/plugins/value/engine/partition.ml rename to src/plugins/value/partitioning/partition.ml index 644e3bf20b5a617f34df40a686b12dadabab3bf4..eb378dc20bbd738c1af9512c6a722d57450098c7 100644 --- a/src/plugins/value/engine/partition.ml +++ b/src/plugins/value/partitioning/partition.ml @@ -164,6 +164,7 @@ let to_list (p : 'a partition) : 'a list = type unroll_limit = | ExpLimit of Cil_types.exp | IntLimit of int + | AutoUnroll of Cil_types.stmt * int * int type split_kind = Static | Dynamic @@ -219,7 +220,11 @@ struct let union (p1 : t) (p2 : t) : t = p1 @ p2 - (* --- Evalution and split functions -------------------------------------- *) + (* --- Automatic loop unrolling ------------------------------------------- *) + + module AutoLoopUnroll = Auto_loop_unroll.Make (Abstract) + + (* --- Evaluation and split functions ------------------------------------- *) (* Domains transfer functions. *) module TF = Abstract.Dom.Transfer (Abstract.Eval.Valuation) @@ -403,6 +408,14 @@ struct let limit = try match limit_kind with | ExpLimit exp -> eval_exp_to_int x exp | IntLimit i -> i + | AutoUnroll (stmt, min_unroll, max_unroll) -> + match AutoLoopUnroll.compute ~max_unroll x stmt with + | None -> min_unroll + | Some i -> + Value_parameters.warning ~once:true ~current:true + ~wkey:Value_parameters.wkey_loop_unroll + "Automatic loop unrolling."; + i with | Operation_failed -> 0 in diff --git a/src/plugins/value/engine/partition.mli b/src/plugins/value/partitioning/partition.mli similarity index 95% rename from src/plugins/value/engine/partition.mli rename to src/plugins/value/partitioning/partition.mli index 2a5177c756849b8abeb1bebb32e939066a11374f..cf1c7426b1d5a4dffcf9f10ce5b9278579ca45a9 100644 --- a/src/plugins/value/engine/partition.mli +++ b/src/plugins/value/partitioning/partition.mli @@ -76,12 +76,16 @@ type rationing (** Creates a new rationing, that can be used successively on several flows. *) val new_rationing: limit:int -> merge:bool -> rationing -(** The unroll limit of a loop can be specified as an integer, or as a C - expression, which is evaluated when entering the loop in each incoming - state. The expression must always evaluate to a singleton integer. *) +(** The unroll limit of a loop. *) type unroll_limit = | ExpLimit of Cil_types.exp + (** Value of the expression for each incoming state. The expression must + evaluate to a singleton integer in each state. *) | IntLimit of int + (** Integer limit. *) + | AutoUnroll of Cil_types.stmt * int * int + (** [AutoUnroll(stmt, min, max)] requests to find a "good" unrolling limit + between [min] and [max] for the loop [stmt]. *) (** Splits on an expression can be static or dynamic: - static splits are processed once: the expression is only evaluated at the diff --git a/src/plugins/value/engine/partitioning_index.ml b/src/plugins/value/partitioning/partitioning_index.ml similarity index 100% rename from src/plugins/value/engine/partitioning_index.ml rename to src/plugins/value/partitioning/partitioning_index.ml diff --git a/src/plugins/value/engine/partitioning_index.mli b/src/plugins/value/partitioning/partitioning_index.mli similarity index 100% rename from src/plugins/value/engine/partitioning_index.mli rename to src/plugins/value/partitioning/partitioning_index.mli diff --git a/src/plugins/value/engine/partitioning_parameters.ml b/src/plugins/value/partitioning/partitioning_parameters.ml similarity index 95% rename from src/plugins/value/engine/partitioning_parameters.ml rename to src/plugins/value/partitioning/partitioning_parameters.ml index b480f4e425da2b3ce6f1dd62384c0ffd326a1151..33ad321a5cba2cdbbf4c053b7f77fb153a91656b 100644 --- a/src/plugins/value/engine/partitioning_parameters.ml +++ b/src/plugins/value/partitioning/partitioning_parameters.ml @@ -58,7 +58,7 @@ struct !Db.Properties.Interp.term_to_exp ~result:None term let min_loop_unroll = MinLoopUnroll.get () - + let auto_loop_unroll = AutoLoopUnroll.get () let default_loop_unroll = DefaultLoopUnroll.get () let warn_no_loop_unroll stmt = @@ -76,7 +76,11 @@ struct "%s loop without unroll annotation" loop_kind let unroll stmt = - let default = Partition.IntLimit min_loop_unroll in + let default = + if auto_loop_unroll > min_loop_unroll + then Partition.AutoUnroll (stmt, min_loop_unroll, auto_loop_unroll) + else Partition.IntLimit min_loop_unroll + in match get_unroll_annot stmt with | [] -> warn_no_loop_unroll stmt; default | [None] -> Partition.IntLimit default_loop_unroll diff --git a/src/plugins/value/engine/partitioning_parameters.mli b/src/plugins/value/partitioning/partitioning_parameters.mli similarity index 100% rename from src/plugins/value/engine/partitioning_parameters.mli rename to src/plugins/value/partitioning/partitioning_parameters.mli diff --git a/src/plugins/value/slevel/per_stmt_slevel.ml b/src/plugins/value/partitioning/per_stmt_slevel.ml similarity index 100% rename from src/plugins/value/slevel/per_stmt_slevel.ml rename to src/plugins/value/partitioning/per_stmt_slevel.ml diff --git a/src/plugins/value/slevel/per_stmt_slevel.mli b/src/plugins/value/partitioning/per_stmt_slevel.mli similarity index 100% rename from src/plugins/value/slevel/per_stmt_slevel.mli rename to src/plugins/value/partitioning/per_stmt_slevel.mli diff --git a/src/plugins/value/engine/split_return.ml b/src/plugins/value/partitioning/split_return.ml similarity index 100% rename from src/plugins/value/engine/split_return.ml rename to src/plugins/value/partitioning/split_return.ml diff --git a/src/plugins/value/engine/split_return.mli b/src/plugins/value/partitioning/split_return.mli similarity index 100% rename from src/plugins/value/engine/split_return.mli rename to src/plugins/value/partitioning/split_return.mli diff --git a/src/plugins/value/slevel/split_strategy.ml b/src/plugins/value/partitioning/split_strategy.ml similarity index 100% rename from src/plugins/value/slevel/split_strategy.ml rename to src/plugins/value/partitioning/split_strategy.ml diff --git a/src/plugins/value/slevel/split_strategy.mli b/src/plugins/value/partitioning/split_strategy.mli similarity index 100% rename from src/plugins/value/slevel/split_strategy.mli rename to src/plugins/value/partitioning/split_strategy.mli diff --git a/src/plugins/value/engine/trace_partitioning.ml b/src/plugins/value/partitioning/trace_partitioning.ml similarity index 100% rename from src/plugins/value/engine/trace_partitioning.ml rename to src/plugins/value/partitioning/trace_partitioning.ml diff --git a/src/plugins/value/engine/trace_partitioning.mli b/src/plugins/value/partitioning/trace_partitioning.mli similarity index 100% rename from src/plugins/value/engine/trace_partitioning.mli rename to src/plugins/value/partitioning/trace_partitioning.mli diff --git a/src/plugins/value/utests b/src/plugins/value/utests index bce097c3b1cfcea2ffac3282c750f757bd950bae..0b2cfea613cd1024532c5bbff89cae377bc921b5 100755 --- a/src/plugins/value/utests +++ b/src/plugins/value/utests @@ -12,7 +12,7 @@ if [ $res -ne 0 ]; then fi TESTS=(float value idct builtins) -CONFIGS=(apron equalities bitwise symblocs gauges) +CONFIGS=(apron equalities bitwise symblocs gauges octagons) for C in ${CONFIGS[@]} do diff --git a/src/plugins/value/utils/value_results.ml b/src/plugins/value/utils/value_results.ml index 4ec633c711ce24d107fbb2ec27359d5bf788f63a..4363193a1b51f6a8de4275dde0e0a23aa1f4434e 100644 --- a/src/plugins/value/utils/value_results.ml +++ b/src/plugins/value/utils/value_results.ml @@ -368,30 +368,32 @@ let consider_function vi = || Cil.hasAttribute "fc_stdlib_generated" vi.vattr) let print_coverage fmt = - let ignored, analyzed = ref 0, ref 0 - and dead, reachable = ref 0, ref 0 in - let is_reachable = Db.Value.is_reachable_stmt in - let do_stmt stmt = incr (if is_reachable stmt then reachable else dead) in + let dead_function, reachable_function = ref 0, ref 0 + and dead_stmt, reachable_stmt = ref 0, ref 0 in + let do_stmt stmt = + incr (if Db.Value.is_reachable_stmt stmt then reachable_stmt else dead_stmt) + in let visit fundec = if consider_function fundec.svar then if is_called (Globals.Functions.get fundec.svar) - then (incr analyzed; List.iter do_stmt fundec.sallstmts) - else incr ignored + then (incr reachable_function; List.iter do_stmt fundec.sallstmts) + else incr dead_function in Globals.Functions.iter_on_fundecs visit; - let all = !dead + !analyzed in - if all = 0 + let total_function = !dead_function + !reachable_function in + if total_function = 0 then Format.fprintf fmt "No function to be analyzed.@;" else Format.fprintf fmt "%i function%s analyzed (out of %i): %i%% coverage.@;" - !analyzed (plural !analyzed) all (!analyzed * 100 / all); - let total = !dead + !reachable in - if !analyzed > 0 && total > 0 then + !reachable_function (plural !reachable_function) total_function + (!reachable_function * 100 / total_function); + let total_stmt = !dead_stmt + !reachable_stmt in + if !reachable_function > 0 && total_stmt > 0 then Format.fprintf fmt "In %s, %i statements reached (out of %i): %i%% coverage.@;" - (if !analyzed > 1 then "these functions" else "this function") - !reachable total (!reachable * 100 / total) + (if !reachable_function > 1 then "these functions" else "this function") + !reachable_stmt total_stmt (!reachable_stmt * 100 / total_stmt) let print_warning fmt = let eva_warnings, eva_errors = ref 0, ref 0 diff --git a/src/plugins/value/value_parameters.ml b/src/plugins/value/value_parameters.ml index 1de1430a7c101b4894bd7aa0176476f575738ee8..2c829ea382f7cea3c49c45905f714a1bc22261c3 100644 --- a/src/plugins/value/value_parameters.ml +++ b/src/plugins/value/value_parameters.ml @@ -167,6 +167,13 @@ module SymbolicLocsDomain = Domain_Parameter let default = false end) +module OctagonDomain = Domain_Parameter + (struct + let option_name = "-eva-octagon-domain" + let help = "Use the octagon domain of Eva." + let default = false + end) + module BitwiseOffsmDomain = Domain_Parameter (struct let option_name = "-eva-bitwise-domain" @@ -312,6 +319,21 @@ module EqualityCallFunction = end) let () = add_precision_dep EqualityCallFunction.parameter +let () = Parameter_customize.set_group domains +module OctagonCall = + Bool + (struct + let option_name = "-eva-octagon-through-calls" + let help = "Whether the relations inferred by the octagon domain are \ + propagated through function calls. Disabled by default: \ + the octagon analysis is intra-procedural, starting \ + each function with an empty octagon state, \ + and losing the octagons inferred at the end. \ + The interprocedural analysis is more precise but slower." + let default = false + end) +let () = add_precision_dep OctagonCall.parameter + let () = Parameter_customize.set_group domains module Numerors_Real_Size = Int @@ -790,6 +812,20 @@ module MinLoopUnroll = let () = add_precision_dep MinLoopUnroll.parameter let () = MinLoopUnroll.set_range 0 max_int +let () = Parameter_customize.set_group precision_tuning +module AutoLoopUnroll = + Int + (struct + let option_name = "-eva-auto-loop-unroll" + let arg_name = "n" + let default = 0 + let help = "limit of the automatic loop unrolling: all loops whose \ + number of iterations can be easily bounded by <n> \ + are completely unrolled." + end) +let () = add_precision_dep AutoLoopUnroll.parameter +let () = AutoLoopUnroll.set_range 0 max_int + let () = Parameter_customize.set_group precision_tuning module DefaultLoopUnroll = Int @@ -1501,26 +1537,31 @@ let bind (type t) (module P: Parameter_sig.S with type t = t) f = let set = set (module P) in configures := (fun n -> set ~default:(n < 0) (f n)) :: !configures -(* power 0 1 2 3 4 5 6 7 8 9 10 11 *) -let slevel_power = [| 0; 10; 20; 50; 75; 100; 200; 500; 1000; 2000; 5000; 10000 |] -let ilevel_power = [| 8; 12; 16; 24; 32; 64; 128; 256; 256; 256; 256; 256 |] -let plevel_power = [| 10; 20; 40; 70; 100; 150; 200; 300; 500; 700; 1000; 2000 |] +(* power 0 1 2 3 4 5 6 7 8 9 10 11 *) +let slevel_power = [| 0; 10; 20; 35; 60; 100; 160; 250; 500; 1000; 2000; 5000 |] +let ilevel_power = [| 8; 12; 16; 24; 32; 48; 64; 128; 192; 256; 256; 256 |] +let plevel_power = [| 10; 20; 40; 70; 100; 150; 200; 300; 500; 700; 1000; 2000 |] +let auto_unroll = [| 0; 16; 32; 64; 96; 128; 192; 256; 384; 512; 768; 1024 |] let get array n = if n < 0 then 0 else array.(n) let () = - bind (module MinLoopUnroll) (fun n -> max 0 (n - 4)); - bind (module SemanticUnrollingLevel) (get slevel_power); + bind (module MinLoopUnroll) (fun n -> max 0 (n - 7)); + bind (module AutoLoopUnroll) (get auto_unroll); bind (module WideningDelay) (fun n -> 1 + n / 2); + bind (module HistoryPartitioning) (fun n -> (n - 1) / 5); + bind (module SemanticUnrollingLevel) (get slevel_power); bind (module ILevel) (get ilevel_power); bind (module ArrayPrecisionLevel) (get plevel_power); bind (module LinearLevel) (fun n -> n * 20); bind (module RmAssert) (fun n -> n > 0); bind (module SymbolicLocsDomain) (fun n -> n > 0); bind (module EqualityDomain) (fun n -> n > 1); - bind (module EqualityCall) (fun n -> if n > 2 then "formals" else "none"); - bind (module GaugesDomain) (fun n -> n > 3); - bind (module SplitReturn) (fun n -> if n > 4 then "auto" else ""); + bind (module GaugesDomain) (fun n -> n > 2); + bind (module SplitReturn) (fun n -> if n > 3 then "auto" else ""); + bind (module OctagonDomain) (fun n -> n > 4); + bind (module EqualityCall) (fun n -> if n > 4 then "formals" else "none"); + bind (module OctagonCall) (fun n -> n > 6); () let set_analysis n = diff --git a/src/plugins/value/value_parameters.mli b/src/plugins/value/value_parameters.mli index 3e0fb860496b052159093bf18d4239e97379081a..7ead8310a01f463bd9cd8f75d995a2ecce1af21a 100644 --- a/src/plugins/value/value_parameters.mli +++ b/src/plugins/value/value_parameters.mli @@ -32,6 +32,7 @@ module CvalueDomain: Parameter_sig.Bool module EqualityDomain: Parameter_sig.Bool module GaugesDomain: Parameter_sig.Bool module SymbolicLocsDomain: Parameter_sig.Bool +module OctagonDomain: Parameter_sig.Bool module BitwiseOffsmDomain: Parameter_sig.Bool module InoutDomain: Parameter_sig.Bool module SignDomain: Parameter_sig.Bool @@ -50,6 +51,8 @@ module EqualityCallFunction: Parameter_sig.Map with type key = Cil_types.kernel_function and type value = string +module OctagonCall: Parameter_sig.Bool + module TracesUnrollLoop: Parameter_sig.Bool module TracesUnifyLoop: Parameter_sig.Bool module TracesDot: Parameter_sig.String @@ -90,6 +93,7 @@ module SlevelFunction: module SlevelMergeAfterLoop: Parameter_sig.Kernel_function_set module MinLoopUnroll : Parameter_sig.Int +module AutoLoopUnroll : Parameter_sig.Int module DefaultLoopUnroll : Parameter_sig.Int module HistoryPartitioning : Parameter_sig.Int module ValuePartitioning : Parameter_sig.String_set diff --git a/src/plugins/value/values/cvalue_forward.ml b/src/plugins/value/values/cvalue_forward.ml index 81f7f5347720eb559045328300b58485b67d2e40..92edcb72aae965853432a24d2f97c0c99cc88c35 100644 --- a/src/plugins/value/values/cvalue_forward.ml +++ b/src/plugins/value/values/cvalue_forward.ml @@ -206,8 +206,8 @@ let assume_not_nan ~assume_finite fkind v = let kind = Fval.kind fkind in let evaluate, backward_propagate = if assume_finite - then Fval.is_finite, Fval.backward_is_finite - else Fval.is_not_nan, fun _fkind -> Fval.backward_is_not_nan + then Fval.is_finite, Fval.backward_is_finite ~positive:true + else Fval.is_not_nan, fun _fkind -> Fval.backward_is_nan ~positive:false in match Cvalue.V.project_float v with | exception Cvalue.V.Not_based_on_null -> @@ -470,28 +470,31 @@ let make_volatile ?typ v = else v let eval_float_constant f fkind fstring = - let fl, fu = match fstring with - | Some string when fkind = Cil_types.FLongDouble || - Value_parameters.AllRoundingModesConstants.get () -> - let open Floating_point in - let {f_lower; f_upper} = snd (parse string) in - (* Computations are done in double. For long double constants, if we - reach infinity, we must use the interval [max_double..infty] to be - sound. Here we even use [-infty..infty]. *) - if Fc_float.is_infinite f_lower && Fc_float.is_infinite f_upper - then - begin - Value_util.warning_once_current - "cannot parse floating-point constant, returning imprecise result"; - neg_infinity, infinity - end - else f_lower, f_upper - | None | Some _ -> f, f - in - let fl = Fval.F.of_float fl - and fu = Fval.F.of_float fu in - let af = Fval.inject (Fval.kind fkind) fl fu in - V.inject_float af + if Fc_float.is_nan f + then V.inject_float Fval.nan + else + let fl, fu = match fstring with + | Some string when fkind = Cil_types.FLongDouble || + Value_parameters.AllRoundingModesConstants.get () -> + let open Floating_point in + let {f_lower; f_upper} = snd (parse string) in + (* Computations are done in double. For long double constants, if we + reach infinity, we must use the interval [max_double..infty] to be + sound. Here we even use [-infty..infty]. *) + if Fc_float.is_infinite f_lower && Fc_float.is_infinite f_upper + then + begin + Value_util.warning_once_current + "cannot parse floating-point constant, returning imprecise result"; + neg_infinity, infinity + end + else f_lower, f_upper + | None | Some _ -> f, f + in + let fl = Fval.F.of_float fl + and fu = Fval.F.of_float fu in + let af = Fval.inject (Fval.kind fkind) fl fu in + V.inject_float af (* diff --git a/src/plugins/value/vtests b/src/plugins/value/vtests index f03eac0072fb247668a1005922ae6f62319a7af6..2962dae8d845919d715d58362f08e97b0fd984d0 100755 --- a/src/plugins/value/vtests +++ b/src/plugins/value/vtests @@ -1,7 +1,7 @@ #!/bin/bash -eu DEFAULT_TESTS=(float value idct builtins) -CONFIGS=( apron equalities bitwise symblocs gauges) +CONFIGS=( apron equalities bitwise symblocs gauges octagons) ARGS=("${@-}") 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/printf.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/printf.res.oracle index 832567d64f6290b9c371111691b52b65e7c1926c..ebb217fac029c7ecff4322210ffa55295ce48b7d 100644 --- a/src/plugins/variadic/tests/erroneous/oracle/printf.res.oracle +++ b/src/plugins/variadic/tests/erroneous/oracle/printf.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/erroneous/printf.c:8: Warning: Multiple usage of flag '-'. [variadic] tests/erroneous/printf.c:8: Warning: 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.res.oracle b/src/plugins/variadic/tests/known/oracle/printf.res.oracle index 95d6cf5297f29e539893f37b6ec3b2469440b761..83d6f21822edc4f5972f9e493f12f9c4aac08a1d 100644 --- a/src/plugins/variadic/tests/known/oracle/printf.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/printf.res.oracle @@ -1,30 +1,30 @@ -[variadic] FRAMAC_SHARE/libc/wchar.h:195: +[variadic] FRAMAC_SHARE/libc/wchar.h:265: Declaration of variadic function fwprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:197: +[variadic] FRAMAC_SHARE/libc/wchar.h:267: Declaration of variadic function swprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:199: +[variadic] FRAMAC_SHARE/libc/wchar.h:269: Declaration of variadic function wprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:202: +[variadic] FRAMAC_SHARE/libc/wchar.h:272: Declaration of variadic function wscanf. -[variadic] FRAMAC_SHARE/libc/wchar.h:204: +[variadic] FRAMAC_SHARE/libc/wchar.h:274: Declaration of variadic function fwscanf. -[variadic] FRAMAC_SHARE/libc/wchar.h:206: +[variadic] FRAMAC_SHARE/libc/wchar.h:276: Declaration of variadic function swscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/printf.c:37: Translating call to printf to a call to the specialized version printf_va_1. @@ -162,6 +162,8 @@ #include "stdio.c" #include "stdio.h" #include "stdlib.h" +#include "string.h" +#include "strings.h" #include "time.h" #include "wchar.h" /*@ requires valid_read_string(format); diff --git a/src/plugins/variadic/tests/known/oracle/printf_garbled_mix.res.oracle b/src/plugins/variadic/tests/known/oracle/printf_garbled_mix.res.oracle index 25e8c3610196c5963f1c9e911eb1e8f829319bfe..ec9df06d3ed29feb21b4fef6d0321d049ac1d8aa 100644 --- a/src/plugins/variadic/tests/known/oracle/printf_garbled_mix.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/printf_garbled_mix.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/printf_garbled_mix.c:8: Variadic builtin Frama_C_show_each_nb_printed left untransformed. 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/oracle/printf_wrong_arity.res.oracle b/src/plugins/variadic/tests/known/oracle/printf_wrong_arity.res.oracle index d322a92f77e082966e1f3ba31a4096c403113f6b..f04220bcfaad7d57eea618f3fd406d3c3bf88e24 100644 --- a/src/plugins/variadic/tests/known/oracle/printf_wrong_arity.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/printf_wrong_arity.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/printf_wrong_arity.c:8: Translating call to printf to a call to the specialized version printf_va_1. diff --git a/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle b/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle index 12097cda98fa628de6c3431143db25fd7544f16c..48af02448ee3c902d99e1bbda933bbb555bba0aa 100644 --- a/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/printf_wrong_pointers.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/printf_wrong_pointers.c:14: Translating call to printf to a call to the specialized version printf_va_1. diff --git a/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle b/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle index 40db9d7dbbf143e9c8ced207fd7ac8ac2ebe8d23..b720645e9345e20e4a5ecb05b2d3e6d7bd35b43f 100644 --- a/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/printf_wrong_types.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/printf_wrong_types.c:18: Translating call to printf to a call to the specialized version printf_va_1. @@ -410,21 +410,21 @@ int main(void) } -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/printf_wrong_types.c:18: Translating call to printf to a call to the specialized version printf_va_1. diff --git a/src/plugins/variadic/tests/known/oracle/scanf.res.oracle b/src/plugins/variadic/tests/known/oracle/scanf.res.oracle index 22a8fdf1bb42bb62dcd300c2b8a68f3e8d281426..cd8ae9652f370cfb52d0d3cde3e03835ed894acf 100644 --- a/src/plugins/variadic/tests/known/oracle/scanf.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/scanf.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/scanf.c:7: Translating call to scanf to a call to the specialized version scanf_va_1. diff --git a/src/plugins/variadic/tests/known/oracle/scanf_loop.res.oracle b/src/plugins/variadic/tests/known/oracle/scanf_loop.res.oracle index 0a7a3cb2f389a34ab022bcfa82d62fb3908882ef..db959e60948ec7b6831aea0217bbe8f926e20e25 100644 --- a/src/plugins/variadic/tests/known/oracle/scanf_loop.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/scanf_loop.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/scanf_loop.c:6: Translating call to scanf to a call to the specialized version scanf_va_1. diff --git a/src/plugins/variadic/tests/known/oracle/scanf_wrong.res.oracle b/src/plugins/variadic/tests/known/oracle/scanf_wrong.res.oracle index 0ad1522b6520cd7aa591efda0f9f72657c9162b1..b468aea8acafdcac55a9e2c8f2df1e0152df8ea3 100644 --- a/src/plugins/variadic/tests/known/oracle/scanf_wrong.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/scanf_wrong.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/scanf_wrong.c:8: Translating call to scanf to a call to the specialized version scanf_va_1. diff --git a/src/plugins/variadic/tests/known/oracle/snprintf.res.oracle b/src/plugins/variadic/tests/known/oracle/snprintf.res.oracle index cf8814488a75dd118d8e8abac81f3bab09ad9baa..2b2dd3e7684dc91bc32669a14ae8cb0c8bfb8435 100644 --- a/src/plugins/variadic/tests/known/oracle/snprintf.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/snprintf.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/snprintf.c:12: Translating call to snprintf to a call to the specialized version snprintf_va_1. diff --git a/src/plugins/variadic/tests/known/oracle/stdio_print.res.oracle b/src/plugins/variadic/tests/known/oracle/stdio_print.res.oracle index 41f785ff02c2f035754f6d27cb48445c435a0f04..0cacefc0330324049f21defc8287bd88133d15c7 100644 --- a/src/plugins/variadic/tests/known/oracle/stdio_print.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/stdio_print.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/stdio_print.c:9: Warning: Call to function fprintf with non-static format argument: diff --git a/src/plugins/variadic/tests/known/oracle/stdio_scan.res.oracle b/src/plugins/variadic/tests/known/oracle/stdio_scan.res.oracle index 23148c803852e714e6e6460bbb3584c014a6662f..671f5bf3f3583974376171a38a07521abc4f5cca 100644 --- a/src/plugins/variadic/tests/known/oracle/stdio_scan.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/stdio_scan.res.oracle @@ -1,18 +1,18 @@ -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/stdio_scan.c:10: Warning: Call to function fscanf with non-static format argument: diff --git a/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle b/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle index f4694f2f3632e5e0d4fdbcdf9ef2ef527a077e69..79025ff0d26ed6ef5e13f3c3ab32bf758d978cae 100644 --- a/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle @@ -1,30 +1,30 @@ -[variadic] FRAMAC_SHARE/libc/wchar.h:195: +[variadic] FRAMAC_SHARE/libc/wchar.h:265: Declaration of variadic function fwprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:197: +[variadic] FRAMAC_SHARE/libc/wchar.h:267: Declaration of variadic function swprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:199: +[variadic] FRAMAC_SHARE/libc/wchar.h:269: Declaration of variadic function wprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:202: +[variadic] FRAMAC_SHARE/libc/wchar.h:272: Declaration of variadic function wscanf. -[variadic] FRAMAC_SHARE/libc/wchar.h:204: +[variadic] FRAMAC_SHARE/libc/wchar.h:274: Declaration of variadic function fwscanf. -[variadic] FRAMAC_SHARE/libc/wchar.h:206: +[variadic] FRAMAC_SHARE/libc/wchar.h:276: Declaration of variadic function swscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/swprintf.c:12: Translating call to swprintf to a call to the specialized version swprintf_va_1. @@ -57,6 +57,8 @@ #include "signal.h" #include "stdarg.h" #include "stdio.h" +#include "string.h" +#include "strings.h" #include "time.h" #include "wchar.h" int volatile nondet; diff --git a/src/plugins/variadic/tests/known/oracle/wchar.res.oracle b/src/plugins/variadic/tests/known/oracle/wchar.res.oracle index a5376947d85456fcb47acfbcc4979db23dd1eb7a..0e93065e23f4b5b463c55d01b9ba31a7d3e0f759 100644 --- a/src/plugins/variadic/tests/known/oracle/wchar.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/wchar.res.oracle @@ -1,30 +1,30 @@ -[variadic] FRAMAC_SHARE/libc/wchar.h:195: +[variadic] FRAMAC_SHARE/libc/wchar.h:265: Declaration of variadic function fwprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:197: +[variadic] FRAMAC_SHARE/libc/wchar.h:267: Declaration of variadic function swprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:199: +[variadic] FRAMAC_SHARE/libc/wchar.h:269: Declaration of variadic function wprintf. -[variadic] FRAMAC_SHARE/libc/wchar.h:202: +[variadic] FRAMAC_SHARE/libc/wchar.h:272: Declaration of variadic function wscanf. -[variadic] FRAMAC_SHARE/libc/wchar.h:204: +[variadic] FRAMAC_SHARE/libc/wchar.h:274: Declaration of variadic function fwscanf. -[variadic] FRAMAC_SHARE/libc/wchar.h:206: +[variadic] FRAMAC_SHARE/libc/wchar.h:276: Declaration of variadic function swscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:165: +[variadic] FRAMAC_SHARE/libc/stdio.h:207: Declaration of variadic function fprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:167: +[variadic] FRAMAC_SHARE/libc/stdio.h:209: Declaration of variadic function fscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:169: +[variadic] FRAMAC_SHARE/libc/stdio.h:211: Declaration of variadic function printf. -[variadic] FRAMAC_SHARE/libc/stdio.h:170: +[variadic] FRAMAC_SHARE/libc/stdio.h:212: Declaration of variadic function scanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:171: +[variadic] FRAMAC_SHARE/libc/stdio.h:213: Declaration of variadic function snprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:173: +[variadic] FRAMAC_SHARE/libc/stdio.h:215: Declaration of variadic function sprintf. -[variadic] FRAMAC_SHARE/libc/stdio.h:175: +[variadic] FRAMAC_SHARE/libc/stdio.h:217: Declaration of variadic function sscanf. -[variadic] FRAMAC_SHARE/libc/stdio.h:369: +[variadic] FRAMAC_SHARE/libc/stdio.h:521: Declaration of variadic function dprintf. [variadic] tests/known/wchar.c:11: Translating call to wprintf to a call to the specialized version wprintf_va_1. @@ -86,6 +86,8 @@ #include "signal.h" #include "stdarg.h" #include "stdio.h" +#include "string.h" +#include "strings.h" #include "time.h" #include "wchar.h" /*@ requires valid_read_wstring(format); 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/src/plugins/wp/Cfloat.ml b/src/plugins/wp/Cfloat.ml index 4e61af7fd092bd2873d5525f0c931e07fbb44446..39aa508ee32fa5f528ad703960827edae45accab 100644 --- a/src/plugins/wp/Cfloat.ml +++ b/src/plugins/wp/Cfloat.ml @@ -175,6 +175,69 @@ let code_lit ulp value original = | Real , _ , None -> F.e_float value | Real , _ , Some r -> F.e_real (parse_literal ~model:Real value r) +(* -------------------------------------------------------------------------- *) +(* --- Literal Output --- *) +(* -------------------------------------------------------------------------- *) + +let printers = [ + Printf.sprintf "%.0g" ; + Printf.sprintf "%.1g" ; + Printf.sprintf "%.2g" ; + Printf.sprintf "%.3g" ; + Printf.sprintf "%.4g" ; + Printf.sprintf "%.5g" ; + Printf.sprintf "%.6g" ; + Printf.sprintf "%.9g" ; + Printf.sprintf "%.12g" ; + Printf.sprintf "%.15g" ; + Printf.sprintf "%.18g" ; + Printf.sprintf "%.21g" ; + Printf.sprintf "%.32g" ; + Printf.sprintf "%.64g" ; +] + +let re_int = Str.regexp "[0-9]+" + +let force_float r = + if Str.string_match re_int r 0 && + Str.match_end () = String.length r + then (r ^ ".0") else r + +let float_lit ulp (q : Q.t) = + let v = match ulp with + | Float32 -> rfloat @@ Transitioning.Q.to_float q + | Float64 -> Transitioning.Q.to_float q in + let reparse ulp r = + match ulp with + | Float32 -> rfloat @@ float_of_string r + | Float64 -> float_of_string r + in + let rec lookup ulp v = function + | [] -> Pretty_utils.to_string Floating_point.pretty v + | pp::pps -> + let r = force_float @@ pp v in + if reparse ulp r = v then r else + lookup ulp v pps + in lookup ulp v printers + +(* -------------------------------------------------------------------------- *) +(* --- Finites --- *) +(* -------------------------------------------------------------------------- *) + +let fclass value _args = + match Context.get model with + | Real -> F.e_bool value + | Float -> raise Not_found + +let () = Context.register + begin fun () -> + LogicBuiltins.hack "\\is_finite" (fclass true) ; + LogicBuiltins.hack "\\is_NaN" (fclass false) ; + LogicBuiltins.hack "\\is_infinite" (fclass false) ; + LogicBuiltins.hack "\\is_plus_infinity" (fclass false) ; + LogicBuiltins.hack "\\is_minus_infinity" (fclass false) ; + end + (* -------------------------------------------------------------------------- *) (* --- Computations --- *) (* -------------------------------------------------------------------------- *) @@ -186,13 +249,23 @@ let rec exact e = | Qed.Logic.Fun( f , [ q ] ) when f == fq32 || f == fq64 -> exact q | _ -> raise Not_found -let compute op ulp xs = +let round ulp e = + match F.repr e with + | Qed.Logic.Fun( f , [ b ] ) -> + begin + match find f with + | REAL , ulp2 when ulp2 = ulp -> b + | _ -> qmake ulp (exact e ) + end + | _ -> qmake ulp (exact e) + +let compute_float op ulp xs = match op , xs with | NEG , [ x ] -> qmake ulp (Q.neg (exact x)) | ADD , [ x ; y ] -> qmake ulp (Q.add (exact x) (exact y)) | MUL , [ x ; y ] -> qmake ulp (Q.mul (exact x) (exact y)) | DIV , [ x ; y ] -> qmake ulp (Q.div (exact x) (exact y)) - | ROUND , [ x ] -> qmake ulp (exact x) + | ROUND , [ x ] -> round ulp x | REAL , [ x ] -> F.e_real (exact x) | LE , [ x ; y ] -> F.e_bool (Q.leq (exact x) (exact y)) | LT , [ x ; y ] -> F.e_bool (Q.lt (exact x) (exact y)) @@ -200,6 +273,24 @@ let compute op ulp xs = | NE , [ x ; y ] -> F.e_bool (not (Q.equal (exact x) (exact y))) | _ -> raise Not_found +let compute_real op xs = + match op , xs with + | NEG , [ x ] -> F.e_opp x + | ADD , [ x ; y ] -> F.e_add x y + | MUL , [ x ; y ] -> F.e_mul x y + | DIV , [ x ; y ] -> F.e_div x y + | (ROUND|REAL) , [ x ] -> x + | LE , [ x ; y ] -> F.e_leq x y + | LT , [ x ; y ] -> F.e_lt x y + | EQ , [ x ; y ] -> F.e_eq x y + | NE , [ x ; y ] -> F.e_neq x y + | _ -> raise Not_found + +let compute op ulp xs = + match Context.get model with + | Real -> compute_real op xs + | Float -> compute_float op ulp xs + (* -------------------------------------------------------------------------- *) (* --- Operations --- *) (* -------------------------------------------------------------------------- *) @@ -250,35 +341,34 @@ let register_builtin_comparison suffix ft = add_builtin ("\\le_" ^ suffix) signature (flt_le ft) ; add_builtin ("\\gt_" ^ suffix) signature gt ; add_builtin ("\\ge_" ^ suffix) signature ge ; - Context.register - begin fun () -> - let converse phi x y = e_fun phi [y;x] in - Lang.F.set_builtin_2 gt (converse (flt_lt ft)) ; - Lang.F.set_builtin_2 ge (converse (flt_le ft)) ; - end + let converse phi x y = e_fun phi [y;x] in + Lang.F.set_builtin_2 gt (converse (flt_lt ft)) ; + Lang.F.set_builtin_2 ge (converse (flt_le ft)) ; end let () = - begin - register_builtin_comparison "float" Float32 ; - register_builtin_comparison "double" Float64 ; - end + Context.register + begin fun () -> + register_builtin_comparison "float" Float32 ; + register_builtin_comparison "double" Float64 ; + end (* -------------------------------------------------------------------------- *) (* --- Models --- *) (* -------------------------------------------------------------------------- *) let () = - begin - let open LogicBuiltins in - let register_builtin ft = - add_builtin "\\model" [F ft] (f_model ft) ; - add_builtin "\\delta" [F ft] (f_delta ft) ; - add_builtin "\\epsilon" [F ft] (f_epsilon ft) ; - in - register_builtin Float32 ; - register_builtin Float64 ; - end + Context.register + begin fun () -> + let open LogicBuiltins in + let register_builtin ft = + add_builtin "\\model" [F ft] (f_model ft) ; + add_builtin "\\delta" [F ft] (f_delta ft) ; + add_builtin "\\epsilon" [F ft] (f_epsilon ft) ; + in + register_builtin Float32 ; + register_builtin Float64 ; + end (* -------------------------------------------------------------------------- *) (* --- Conversion Symbols --- *) diff --git a/src/plugins/wp/Cfloat.mli b/src/plugins/wp/Cfloat.mli index f1f46e5950f89fe509e97f6015f2dbf0c5906338..debed76a027159ea32212882699c09fae9de164d 100644 --- a/src/plugins/wp/Cfloat.mli +++ b/src/plugins/wp/Cfloat.mli @@ -57,6 +57,9 @@ val find : lfun -> op * c_float val code_lit : c_float -> float -> string option -> term val acsl_lit : Cil_types.logic_real -> term +val float_lit : c_float -> Q.t -> string +(** Returns a string literal in decimal notation (without suffix) + that reparses to the same value (when added suffix). *) val float_of_int : c_float -> unop val float_of_real : c_float -> unop diff --git a/src/plugins/wp/GuiGoal.ml b/src/plugins/wp/GuiGoal.ml index cc032908626fc5ab3b8730a3758382693ed8b470..e88783bd3830cc6ae6295d6a397b186c69b72fd3 100644 --- a/src/plugins/wp/GuiGoal.ml +++ b/src/plugins/wp/GuiGoal.ml @@ -69,6 +69,17 @@ class iformat = ] end +class rformat = + object inherit [Plang.rformat] menu + ~key:"GuiGoal.rformat" + ~default:`Ratio + ~data:[ + `Ratio , "Real" , "REAL" ; + `Float , "Float (32 bits)" , "F32" ; + `Double , "Float (64 bits)" , "F64" ; + ] + end + (* -------------------------------------------------------------------------- *) (* --- Goal Panel --- *) (* -------------------------------------------------------------------------- *) @@ -101,6 +112,7 @@ class pane (gprovers : GuiConfig.provers) = ~icon:`SAVE ~tooltip:"Save Script" () in let autofocus = new autofocus in let iformat = new iformat in + let rformat = new rformat in let strategies = new GuiTactic.strategies () in let native = List.mem "native:alt-ergo" (Wp_parameters.Provers.get ()) in object(self) @@ -114,7 +126,7 @@ class pane (gprovers : GuiConfig.provers) = let toolbar = Wbox.(toolbar [ w prev ; w next ; w cancel ; w forward ; - w autofocus ; w iformat ; + w autofocus ; w iformat ; w rformat ; w play_script ; w save_script ; w ~padding:6 icon ; h ~padding:6 status ] [ w help ; w delete ]) in @@ -156,6 +168,7 @@ class pane (gprovers : GuiConfig.provers) = play_script#connect (fun () -> self#play_script) ; autofocus#connect self#autofocus ; iformat#connect self#iformat ; + rformat#connect self#rformat ; composer#connect (fun () -> self#update) ; browser#connect (fun () -> self#update) ; help#connect (fun () -> self#open_help) ; @@ -225,6 +238,7 @@ class pane (gprovers : GuiConfig.provers) = | `Main | `Internal _ -> () method private iformat f = printer#set_iformat f ; self#update + method private rformat f = printer#set_rformat f ; self#update method private autofocus = function | `Autofocus -> diff --git a/src/plugins/wp/GuiSequent.ml b/src/plugins/wp/GuiSequent.ml index a84217082a5b073db44c8bf11a3e38ec0950d3be..767ad74f138699ae260592ecb0853aa696bbc828 100644 --- a/src/plugins/wp/GuiSequent.ml +++ b/src/plugins/wp/GuiSequent.ml @@ -529,6 +529,9 @@ class focused (wtext : Wtext.text) = method set_iformat = plang#set_iformat method get_iformat = plang#get_iformat + method set_rformat = plang#set_rformat + method get_rformat = plang#get_rformat + method selected = begin self#set_target self#selection ; diff --git a/src/plugins/wp/GuiSequent.mli b/src/plugins/wp/GuiSequent.mli index b11d583cdf96a71bb0e8379df39f930610c2de04..71ce89c7a80366b57f6ca8607c62fd5c5bd022f1 100644 --- a/src/plugins/wp/GuiSequent.mli +++ b/src/plugins/wp/GuiSequent.mli @@ -37,9 +37,13 @@ class focused : Wtext.text -> method set_focus_mode : bool -> unit method get_state_mode : bool method set_state_mode : bool -> unit + method get_iformat : Plang.iformat method set_iformat : Plang.iformat -> unit + method get_rformat : Plang.rformat + method set_rformat : Plang.rformat -> unit + method selected : unit method unselect : target method restore : target -> unit diff --git a/src/plugins/wp/LogicBuiltins.ml b/src/plugins/wp/LogicBuiltins.ml index fff1b748fed5e2ca7d55c098b84beb803e30639b..8fa7c5044b492f4ace85077d97fbcd48fa0213ee 100644 --- a/src/plugins/wp/LogicBuiltins.ml +++ b/src/plugins/wp/LogicBuiltins.ml @@ -141,7 +141,14 @@ let hacks = Hashtbl.create 8 let hack name phi = Hashtbl.replace hacks name phi let lookup name kinds = - try HACK (Hashtbl.find hacks name) + try + let hack = Hashtbl.find hacks name in + let compute es = + try hack es with Not_found -> + match lookup_driver name kinds with + | ACSLDEF | HACK _ -> Warning.error "No fallback for hacked '%s'" name + | LFUN p -> F.e_fun p es + in HACK compute with Not_found -> lookup_driver name kinds let register ?source name kinds link = @@ -285,11 +292,11 @@ let builtin_driver = { } let add_builtin name kinds lfun = - begin - Context.set driver builtin_driver; - register name kinds (LFUN lfun); - Context.clear driver; - end + let phi = LFUN lfun in + if Context.defined driver then + register name kinds phi + else + Context.bind driver builtin_driver (register name kinds) phi let create ~id ?(descr=id) ?(includes=[]) () = { @@ -303,3 +310,5 @@ let create ~id ?(descr=id) ?(includes=[]) () = let init ~id ?descr ?includes () = Context.set driver (create ~id ?descr ?includes ()) + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/LogicCompiler.ml b/src/plugins/wp/LogicCompiler.ml index 516a6b801459774ca3bb8a74661a75deefa645a3..69e3a0ea22a775b3f89247091212618447289c0e 100644 --- a/src/plugins/wp/LogicCompiler.ml +++ b/src/plugins/wp/LogicCompiler.ml @@ -878,14 +878,18 @@ struct | LFUN phi -> e_fun phi [] ~result:(Lang.tau_of_ltype x.lv_type) in Cvalues.plain x.lv_type v with Not_found -> - Wp_parameters.fatal "Unbound logic variable '%a'" - Printer.pp_logic_var x + if Logic_env.is_logic_function x.lv_name then + Warning.error "Lambda-functions not yet implemented (at '%s')" + x.lv_name + else + Wp_parameters.fatal "Name '%a' has no definition in term" + Printer.pp_logic_var x let logic_info env f = try match Logic_var.Map.find f.l_var_info env.vars with | Vexp p -> Some (F.p_bool p) - | _ -> Wp_parameters.fatal "Logic variable '%a' is not a predicate" + | _ -> Wp_parameters.fatal "Variable '%a' is not a predicate" Logic_info.pretty f with Not_found -> None diff --git a/src/plugins/wp/Plang.ml b/src/plugins/wp/Plang.ml index bc6277756c078987be36f7cf5b8b7946d6d57aed..c4584f71d87cd65aab24e28102810fa450f7c54b 100644 --- a/src/plugins/wp/Plang.ml +++ b/src/plugins/wp/Plang.ml @@ -68,6 +68,7 @@ module Env = E.Env type scope = Qed.Engine.scope type iformat = [ `Dec | `Hex | `Bin ] +type rformat = [ `Ratio | `Float | `Double ] let sanitizer = Qed.Export.sanitize ~to_lowercase:false class engine = @@ -76,10 +77,6 @@ class engine = inherit Lang.idprinting method infoprover w = w.altergo - val mutable iformat : iformat = `Dec - method get_iformat = iformat - method set_iformat (f : iformat) = iformat <- f - (* --- Types --- *) method t_int = "Z" @@ -98,11 +95,17 @@ class engine = method pp_datatype a fmt ts = Qed.Plib.pp_call_var ~f:(self#datatype a) self#pp_tau fmt ts - (* --- Primitives --- *) + (* --- Booleans --- *) method e_true _ = "true" method e_false _ = "false" + (* --- Integers --- *) + + val mutable iformat : iformat = `Dec + method get_iformat = iformat + method set_iformat (f : iformat) = iformat <- f + method pp_int _ fmt z = try let n = Integer.to_int z in @@ -116,6 +119,12 @@ class engine = | `Hex -> Integer.pp_hex ~sep:"," fmt z | `Bin -> Integer.pp_bin ~sep:"," fmt z + (* --- Reals --- *) + + val mutable rformat : rformat = `Ratio + method get_rformat = rformat + method set_rformat (f : rformat) = rformat <- f + method pp_real fmt q = match Q.classify q with | Q.ZERO -> Format.pp_print_string fmt ".0" @@ -123,11 +132,19 @@ class engine = | Q.MINF -> Format.pp_print_string fmt "(-1/.0)" | Q.UNDEF -> Format.pp_print_string fmt "(.0/.0)" | Q.NZERO -> - let { Q.num = num ; Q.den = den } = q in - if Z.equal den Z.one then - Format.fprintf fmt "%s.0" (Z.to_string num) - else - Format.fprintf fmt "(%s.0/%s)" (Z.to_string num) (Z.to_string den) + match rformat with + | `Ratio -> + let { Q.num = num ; Q.den = den } = q in + if Z.equal den Z.one then + Format.fprintf fmt "%s.0" (Z.to_string num) + else + Format.fprintf fmt "(%s.0/%s)" + (Z.to_string num) + (Z.to_string den) + | `Float -> + Format.fprintf fmt "%sf" (Cfloat.float_lit Ctypes.Float32 q) + | `Double -> + Format.fprintf fmt "%sd" (Cfloat.float_lit Ctypes.Float64 q) (* --- Atomicity --- *) diff --git a/src/plugins/wp/Plang.mli b/src/plugins/wp/Plang.mli index 3dd2bf095125c2c298443944d4eb8e32aeedd74f..058414e9e42f50aa19b67f9f804be315beb680a3 100644 --- a/src/plugins/wp/Plang.mli +++ b/src/plugins/wp/Plang.mli @@ -37,12 +37,15 @@ val alloc_domain : pool -> Vars.t val sanitizer : string -> string type iformat = [ `Hex | `Dec | `Bin ] +type rformat = [ `Ratio | `Float | `Double ] class engine : object inherit [Z.t,ADT.t,Field.t,Fun.t,tau,var,term,Env.t] Qed.Engine.engine method get_iformat : iformat method set_iformat : iformat -> unit + method get_rformat : rformat + method set_rformat : rformat -> unit method marks : Env.t * Lang.F.marks method pp_pred : Format.formatter -> pred -> unit method lookup : term -> scope diff --git a/src/plugins/wp/RefUsage.ml b/src/plugins/wp/RefUsage.ml index 99ff308844e40829b59d021f5589426226507d0e..0f0291f96b028d234ccf00561f7e3e37fd93ac6d 100644 --- a/src/plugins/wp/RefUsage.ml +++ b/src/plugins/wp/RefUsage.ml @@ -145,6 +145,16 @@ type model = | Val_comp of varinfo * value (* x.f[_].g... *) | Val_shift of varinfo * value (* (x + E) *) +[@@@ warning "-32" ] +let pp_model fmt = function + | E v -> E.pretty fmt v + | Loc_var x -> Format.fprintf fmt "&%a" Varinfo.pretty x + | Loc_shift(x,v) -> Format.fprintf fmt "&%a.(%a)" Varinfo.pretty x E.pretty v + | Val_var x -> Varinfo.pretty fmt x + | Val_comp(x,v) -> Format.fprintf fmt "%a.(%a)" Varinfo.pretty x E.pretty v + | Val_shift(x,v) -> Format.fprintf fmt "%a+(%a)" Varinfo.pretty x E.pretty v +[@@@ warning "+32" ] + let nothing = E E.bot let v_model v = if E.is_bot v then nothing else E v @@ -203,8 +213,12 @@ let field = function | m -> shift m E.bot let load = function - | Loc_var x -> Val_var x - | Loc_shift(x,e) -> E (E.access x ByValue e) + | Loc_var x -> Val_var x (* E.access x ByValue E.bot *) + | Loc_shift(x,e) -> + if Cil.isArithmeticOrPointerType x.vtype then + E (E.access x ByAddr e) + else + E (E.access x ByValue e) | Val_var x -> E (E.access x ByRef E.bot) | Val_comp(x,e) -> E (E.access x ByRef e) | Val_shift(x,e) -> E (E.access x ByArray e) @@ -693,17 +707,17 @@ let param a m = match a with | ByArray -> e_value (load (shift m E.bot)) let update_call_env (env:global_ctx) v = - let r,differ = E.cup_differ env.code v - in env.code <- r ; - differ + let r,differ = E.cup_differ env.code v in + env.code <- r ; differ let call_kf (env:global_ctx) (formals:access list) (models:model list) (reached:bool) = let unmodified = ref reached in let rec call xs ms = match xs, ms with - | [] , _ | _ , [] -> () | x::xs , m::ms -> - if update_call_env env (param x m) then unmodified := false; + let actual = param x m in + if update_call_env env actual then unmodified := false; call xs ms + | _ -> () in call formals models; !unmodified @@ -748,10 +762,11 @@ let compute_usage () = in (* update from accesses of formals of the called spec for each calls*) let specs_formals = called.spec_formals in - let formals = Kernel_function.get_formals called_kf in - let formals = List.map (fun vi -> E.get vi specs_formals) formals in + let params = Kernel_function.get_formals called_kf in + let formals = List.map (fun vi -> E.get vi specs_formals) params in let kf_call reached call = call_kf env formals call reached in - List.fold_left kf_call reached calls in + List.fold_left kf_call reached calls + in state_fp.todo <- KFmap.remove kf state_fp.todo ; let cphi = env.cphi in let reached = KFmap.fold kf_calls cphi true in diff --git a/src/plugins/wp/doc/manual/wp_builtins.tex b/src/plugins/wp/doc/manual/wp_builtins.tex index a556ab01a823cbaf618c55adf9d5bf414628c671..c5df277c89c59b1a6e60f9227438a53b73e72689 100644 --- a/src/plugins/wp/doc/manual/wp_builtins.tex +++ b/src/plugins/wp/doc/manual/wp_builtins.tex @@ -31,10 +31,6 @@ The \textsf{ACSL} built-ins supported by \textsf{Frama-C/WP} are listed in Figur In the table, the reference implementation of the function is given in terms of the \textsf{Why-3} standard library\footnote{Available online \texttt{http://why3.lri.fr/stdlib}}, from which all the properties are automatically imported and communicated to the provers. -For the natively supported provers \textsf{Alt-Ergo} and \textsf{Coq}, those properties are also available, even -if \textsf{Why-3} is not installed on your machine. They are statically installed by \textsf{Frama-C} in the -shared directory of \textsf{WP}% -\footnote{Usually \texttt{/usr/local/share/frama-c/wp} ; otherwise \texttt{`frama-c -print-share-path`/wp}}. \begin{figure}[htbp] \begin{center} diff --git a/src/plugins/wp/doc/manual/wp_intro.tex b/src/plugins/wp/doc/manual/wp_intro.tex index 1e3c5e076a67cc3e3d8a823eceda35a8c64bcd7d..87cf5ca2b52496de946fe09bdd591d0ce4e17656 100644 --- a/src/plugins/wp/doc/manual/wp_intro.tex +++ b/src/plugins/wp/doc/manual/wp_intro.tex @@ -25,7 +25,7 @@ heterogeneous casts, are involved. Moreover, \textsf{Jessie} operates by compiling the \textsf{C} program to \textsf{Why}, a solution that prevents the user from combining \textit{weakest precondition calculus} with other techniques, such as the -\textsf{Value} analysis plug-in. +\textsf{Eva} analysis plug-in. The \textsf{WP} plug-in has been designed with cooperation in mind. That is, you may use \textsf{WP} for proving some annotations of @@ -39,9 +39,10 @@ the \textsf{WP} plug-in, the \emph{Weakest Precondition} calculus and \emph{Memory Models}. Then, Chapter~\ref{wp-plugin} details how to use and tune the plug-in within the \textsf{Frama-C} platform. Chapter~\ref{wp-models} provides a description for the -included memory models. Finally, we present in -Chapter~\ref{wp-simplifier} the simplifier module and the efficient weakest -precondition engine implemented in the \textsf{WP} plug-in. +included memory models. We present in Chapter~\ref{wp-simplifier} the +simplifier module and the efficient weakest precondition engine implemented +in the \textsf{WP} plug-in. Finally, in Chapter~\ref{wp-builtins}, we +provide additional information on the supported ACSL built-in symbols. \clearpage @@ -51,12 +52,14 @@ precondition engine implemented in the \textsf{WP} plug-in. %----------------------------------------------------------------------------- The \textsf{WP} plug-in is distributed with the \textsf{Frama-C} -platform. However, you should install at least one external prover in +platform. However, it also requires the \textsf{Why-3} platform and +you should install at least one external prover in order to fulfill proof obligations. An easy choice is to install the -\textsf{Alt-Ergo} theorem prover developed at -\textsc{inria}\footnote{\textsf{Alt-Ergo}: - \url{http://alt-ergo.lri.fr}}. See section~\ref{wp-install-provers} -for installing other provers. +\textsf{Alt-Ergo} theorem prover originally developed at +\textsc{inria} and now by \textsc{OcamlPro}\footnote{\textsf{Alt-Ergo}: + \url{https://alt-ergo.ocamlpro.com/}}. When using the \textsf{Opam} package + manager, these tools are automatically installed with \textsf{Frama-C}. +See the documentation of \textsf{Why-3} to install other provers. %----------------------------------------------------------------------------- @@ -94,7 +97,7 @@ should be valid. By default, the \textsf{WP} plug-in does not generate any proof obligation for verifying the absence of runtime errors in your code. Absence of runtime errors can be proved with other techniques, for instance by running -the \textsf{Value} plug-in, or by generating all the necessary annotations +the \textsf{Eva} plug-in, or by generating all the necessary annotations with the \textsf{RTE} plug-in. The simple contract for the \texttt{swap} function above is not strong enough to @@ -196,8 +199,8 @@ Regarding runtime errors, the proof obligations generated by \textsf{WP} assume your program never raises any of them. As illustrated in the short tutorial example of section~\ref{wp-tutorial}, you should enforce the absence of runtime -errors on your own, for instance by running the \emph{value analysis} -plug-in or the \emph{rte generation} one and proving the generated assertions. +errors on your own, for instance by running the \textsf{Eva} +plug-in or the \textsf{RTE} one and proving the generated assertions. %----------------------------------------------------------------------------- \section{Memory Models} @@ -294,11 +297,11 @@ Chapter~\ref{wp-models} is dedicated to a more detailed description of memory models, and how the \textsf{WP} plug-in uses and \emph{combines} them to generate efficient proof obligations. -\paragraph{Remark.} -The original \texttt{Store} and \texttt{Runtime} memory models are no -longer available since \textsf{WP} version \verb+0.7+ (Fluorine); the \texttt{Typed} model -replaces the \texttt{Store} one; the \texttt{Runtime} model will be entirely -re-implemented as \texttt{Bytes} model in some future release. +% \paragraph{Remark.} +% The original \texttt{Store} and \texttt{Runtime} memory models are no +% longer available since \textsf{WP} version \verb+0.7+ (Fluorine); the \texttt{Typed} model +% replaces the \texttt{Store} one; the \texttt{Runtime} model will be entirely +% re-implemented as \texttt{Bytes} model in some future release. \clearpage \section{Arithmetic Models} @@ -361,5 +364,5 @@ For tackling this complexity, the \textsf{WP} plug-in relies on several \paragraph{Remark:} with all models, there are conditions to meet for WP proofs to be correct. Depending on the model used and the kernel options, those conditions may change. WP do not generate proof obligations for runtime errors on its own. Instead, it can -discharge the annotations generated by the Value analysis plug-in, or by the RTE plug-in. +discharge the annotations generated by the \textsf{Eva} analysis plug-in, or by the \textsf{RTE} plug-in. Consider also using \textsf{-wp-rte} option. diff --git a/src/plugins/wp/doc/manual/wp_plugin.tex b/src/plugins/wp/doc/manual/wp_plugin.tex index d3d4fb60a65a2ad5b148354b37efdd95c47830b2..3d0330f4f5b5917ddd50e6ab4c77cfed1bbfa1a3 100644 --- a/src/plugins/wp/doc/manual/wp_plugin.tex +++ b/src/plugins/wp/doc/manual/wp_plugin.tex @@ -34,12 +34,12 @@ The recommended versions for external provers are: \begin{tabular}{crlc} Prover & Versions & Download &\\ \hline - \textsf{Alt-Ergo} & \verb|2.0.0| & - \url{http://alt-ergo.ocamlpro.com} & \cite{AltErgo2006}\\ - \textsf{Coq} & \verb|8.9.0| & - \url{http://coq.inria.fr} & \cite{Coq84}\\ \textsf{Why3} & \verb|1.2.0| & \url{http://why3.lri.fr} & \cite{Why3}\\ + \textsf{Alt-Ergo} & \verb|2.0.0| & + \url{http://alt-ergo.ocamlpro.com} & \cite{AltErgo2006}\\ + % \textsf{Coq} & \verb|8.9.0| & + % \url{http://coq.inria.fr} & \cite{Coq84}\\ \end{tabular} \end{center} @@ -47,38 +47,15 @@ Recent \textsf{OPAM}-provided versions should work smoothly. Other versions might be supported as well, typically, as far as we know: \begin{itemize} \item \textsf{Alt-Ergo} \verb+2.2.0+ and \verb+2.3.0+, although distributed under a non-commercial licence. -\item \textsf{Coq} \verb+8.7.2+ and \verb+8.8.2+, although proof scripts compatibility can be an issue. +% \item \textsf{Coq} \verb+8.7.2+ and \verb+8.8.2+, although proof scripts compatibility can be an issue. \item \textsf{Why3} \verb+1.0.0+ and \verb+1.1.1+, although only \verb+1.2.0+ is provided with Coq support. \end{itemize} -Other provers, like \textsf{Gappa}, \textsf{Z3}, \textsf{CVC3}, +Other provers, like \textsf{Coq}, \textsf{Gappa}, \textsf{Z3}, \textsf{CVC3}, \textsf{CVC4}, \textsf{PVS}, and many others, are accessible from \textsf{WP} through \textsf{Why3}. We refer the user to the manual of \textsf{Why3} to handle specific configuration tasks. -Provers can be installed at any time, before or after the installation -of \textsf{Frama-C/WP}. However, when using \textsf{Coq} and -\textsf{Why-3}, it is better to install them before, or to -re-configure and re-install \textsf{WP}, as explained below. - -\paragraph{Configuration.} When using \textsf{Coq} and \textsf{Why-3}, pre-compiled -libraries are built during the compilation of \textsf{Frama-C}, which -speed up the proof process in a significant way. This behavior can be -turned on/off at configure time, typically: -\begin{logs} -# configure --disable-wp-coq --disable-wp-why3 -\end{logs} - -\paragraph{Compilation.} If you want to compile the \textsf{Coq} and \textsf{Why-3} -libraries manually, you can still run the following commands: -\begin{logs} -# make wp-coq wp-why3 -# [sudo] make wp-coq-install -\end{logs} - -\paragraph{Remark.} The \textsf{Why}~\cite{Filliatre2003} prover is no longer supported -since \textsf{WP} version \verb+0.7+ (Fluorine). - \clearpage %----------------------------------------------------------------------------- \section{Graphical User Interface} @@ -100,7 +77,7 @@ described in section~\ref{wp-cmdline}: \begin{center} \includegraphics[width=\textwidth]{wp-gui-main.png} \end{center} -\caption{WP in the Frama-C GUI} +\caption{\textsf{WP} in the Frama-C GUI} \label{wp-gui-panel} \end{figure} @@ -108,7 +85,7 @@ described in section~\ref{wp-cmdline}: \begin{center} \includegraphics[width=\textwidth]{wp-gui-run.png} \end{center} -\caption{WP run from the GUI} +\caption{\textsf{WP} run from the GUI} \label{wp-gui-run} \end{figure} @@ -150,13 +127,12 @@ in the general user's manual of the platform. The status emitted by the \textsf{ \end{tabular} \end{center} -\paragraph{WP Goals Panel.} +\paragraph{\textsf{WP} Goals Panel.} This panel is dedicated to the \textsf{WP} plug-in. It shows the generated proof obligations and their status for each prover. By clicking on a prover column, you can also submit a proof obligation to a prover by -hand. Right-click provides more options depending on the prover, such -as proof-script editing for \textsf{Coq}. +hand. Right-click provides more options depending on the prover. \paragraph{Interactive Proof Editor.} From the Goals Panel view, you can double-click on a row and open the \emph{interactive proof editor} panel as described in section~\ref{wp-proof-editor}. @@ -311,7 +287,7 @@ c. Consolidating the Bench. frama-c [...] -wp-prover script,alt-ergo \end{logs} -This mode replays the automated proofs and the interactive ones, re-running Alt-Ergo on every WP goals and every proof tactic sub-goals. The user scripts are never modified — this is a replay mode only. +This mode replays the automated proofs and the interactive ones, re-running Alt-Ergo on every \textsf{WP} goals and every proof tactic sub-goals. The user scripts are never modified — this is a replay mode only. \clearpage \subsection{Available Tactics} @@ -550,7 +526,7 @@ of the \texttt{iota} integer domain. \subsection{Strategies} Strategies are heuristics that generate a prioritized bunch of tactics to be tried on the current goal. -Few built-in strategies are provided by the WP plug-in ; however, the user can extends the proof editor with +Few built-in strategies are provided by the \textsf{WP} plug-in ; however, the user can extends the proof editor with custom ones, as explained in section~\ref{wp-custom-tactics} below. To run strategies, the interactive proof editor provide a single button \texttt{Strategies} in the tactic panel. @@ -580,7 +556,7 @@ The name of registered strategies is printed on console by using \texttt{-wp-aut The proof editor and script runner can be extended by loading additional plug-ins. These plug-ins are regular OCaml files to be loaded with the kernel \texttt{-load-module} option. They will be compiled by \textsf{Frama-C} against its API. The \textsf{WP} plug-in exports a rich API to extend the proof editor with new tactics, strategies, and even term-composer tools. -It is not possible to reproduce here the complete API ; it is better to use the automatically generated HTML documentation from WP's sources. We only provide here a quick tour of this API, as a tutorial on how to implement a basic custom strategy. +It is not possible to reproduce here the complete API ; it is better to use the automatically generated HTML documentation from \textsf{WP}'s sources. We only provide here a quick tour of this API, as a tutorial on how to implement a basic custom strategy. The main extension points of the \textsf{WP} plug-in's API are the following ones: \begin{center} @@ -751,7 +727,7 @@ interface of the programmatic API. \item [\tt -wp] generates proof obligations for all (selected) properties. \item [\tt -wp-fct <f$_1$,...,f$_n$>] selects annotations of functions \texttt{f$_1$},...,\texttt{f$_n$} (defaults to all functions). -\item [\tt -wp-skip-fct <f$_1$,...,f$_n$>] removes annotations of +\item [\tt -wp-skip-fct <f$_1$,...,f$_n$>] ignores functions \texttt{f$_1$},...,\texttt{f$_n$} (defaults to none). \item [\tt -wp-bhv <b$_1$,...,b$_n$>] selects annotations for behaviors \texttt{b$_1$},...\texttt{b$_n$} (defaults to all behaviors) of the @@ -772,7 +748,7 @@ interface of the programmatic API. and \texttt{loop assigns} properties from the selection. \\ \textbf{Remark:} properties with name \verb+no_wp:+ are always and automatically - filtered and never proved by WP. + filtered and never proved by \textsf{WP}. \item [\tt -wp-(no)-status-all] includes in the goal selection all properties regardless of their current status (default is: \texttt{no}). \item [\tt -wp-(no)-status-valid] includes in the goal selection those properties @@ -862,14 +838,6 @@ The available \textsf{WP} command-line options related to model selection are: in \textsf{ACSL} contracts to ensure type-checking but are related to identity-casts from the code. The option is \texttt{off} by default. -\item[\tt -wp-bool-range] experimental support for \verb+_Bool+ range. This option assumes - there is no \emph{trap representations} - in considering valid the related assertions generated by \texttt{-wp-rte} (those tagged with \texttt{bool\_value:}). - Hence, integer values with boolean type are - either equal to \verb+0+ or \verb+1+. Actually, the only way to forge other values - is \emph{via} union types and heterogeneous pointer casts, which is currently not allowed - in the memory models of \textsf{WP}. - \item[\tt -wp-literals] exports the contents of string literals to provers (default: \texttt{no}). \item[\tt -wp-extern-arrays] gives an arbitrary large size to arrays @@ -884,6 +852,7 @@ The available \textsf{WP} command-line options related to model selection are: \texttt{ref}: & the variable is a constant pointer and is modeled by the \texttt{Ref}.\\ \texttt{context}: & the variable is initially non-aliased and uses a fresh global in \texttt{Typed}.\\ \end{tabular} +\item[\tt -wp-(no)-alias-init] Use initializers for aliasing propagation (default is: yes). \item[\tt -wp-(no)-volatile] this option (de)activate the correct handling of volatile access. By default, accessing a volatile l-value returns an undefined value, and writing to a volatile l-value is modeled like an \textsf{ACSL} assigns clause. @@ -914,12 +883,18 @@ weakest precondition calculus. to generate guards, and they might be not strong enough to meet the natural model requirements. In this case, a warning is emitted for potential runtime errors. Refer to Section~\ref{wp-model-arith} for details. +\item[\tt -wp-(no)-init-const] use initializers for global const variables + (defaut is: \texttt{yes}). \item[\tt -wp-(no)-split] conjunctions in generated proof obligations are recursively split into sub-goals. The generated goal names are suffixed by ``{\tt part<{\it n}>}'' (defaults to \texttt{no}). +\item[\tt -wp-split-depth <d>] sets the depth of exploration for the + \texttt{-wp-split} option. ``-1'' stands for unlimited depth. Default is 0. \item[\tt -wp-(no)-callee-precond] includes preconditions of the callee after\footnote{Proof obligations are always generated to check preconditions.} a call (default is: \texttt{yes}). +\item[\tt -wp-(no)-precond-weakening] discard pre-conditions of side behaviours (sound but + incomplete optimisation, default is: \texttt{no}). \item[\tt -wp-(no)-unfold-assigns] prove assigns goal of \texttt{struct} compound types field by field. This allows for proving that assigning a complete structure is still included into an assignment field by field. @@ -929,7 +904,7 @@ weakest precondition calculus. \item[\tt -wp-(no)-dynamic] handles calls \textit{via} function pointers thanks to the dedicated \verb+@calls f1,...,fn+ code annotation. For each call to a function pointer \texttt{fp} - in the instruction or block under the annotaion, + in the instruction or block under the annotation, \texttt{fp} is required to belongs to the set \texttt{f1,\ldots,fn} and a case analysis is performed with the contract of each provided function (default is: \texttt{yes}). @@ -959,6 +934,8 @@ controlled by the following options: expressions and tautologies (default is: \texttt{yes}). \item[\tt -wp-(no)-let] propagates equalities by substitutions and let-bindings (default is: \texttt{yes}). +\item[\tt -wp-(no)-filter] filter non used variables and related hypotheses + (default is: \texttt{yes}). \item[\tt -wp-(no)-core] factorize common properties between branches (default is: \texttt{yes}). \item[\tt -wp-(no)-pruning] eliminates trivial branches of conditionals @@ -967,6 +944,8 @@ controlled by the following options: proof obligations (default is: \texttt{yes}). \item[\tt -wp-(no)-ground] replace ground values in equalities (default is: \texttt{yes}). +\item[\tt -wp-(no)-extensional] use extensional equality on compounds + (default is: \texttt{yes}). \item[\tt -wp-(no)-reduce] replace functions with precedence to constructors and operators (default is: \texttt{yes}). \item[\tt -wp-(no)-parasite] eliminate parasite variables @@ -994,10 +973,12 @@ controlled by the following options: \label{wp-provers} The generated proof obligations are submitted to external decision -procedures. If proof obligations have just been generated, by using -\texttt{-wp}, \texttt{-wp-fct}, \texttt{-wp-bhv} or \texttt{-wp-prop}, -then only the new proof obligations are sent. Otherwise, all unproved -proof obligations are sent to external decision procedures. +procedures run through the \textsf{Why-3} platform. If proof obligations have +just been generated, by using \texttt{-wp}, \texttt{-wp-fct}, \texttt{-wp-bhv} +or \texttt{-wp-prop}, then only the new proof obligations are sent. Otherwise, +all unproved proof obligations are sent to external decision procedures. + +Support for \textsf{Why-3 IDE} is no longer provided. \begin{description} \item[\tt -wp-prover <dp,...>] selects the decision procedures used to @@ -1009,8 +990,11 @@ proof obligations are sent to external decision procedures. It is possible to ask for several decision procedures to be tried. For each goal, the first decision procedure that succeeds cancels the other attempts. -\item[\tt -wp-proof <dp,...>] \textbf{deprecated} alias for \texttt{-wp-prover} for - backward compatibility with \textsf{WP} version \verb+0.6+. +\item[\tt -wp-detect] lists the provers available for \textsf{Why-3}. + This command can only work if \textsf{why3} API was installed before building and + installing \textsf{Frama-C}. + The option reads your \textsf{Why-3} configuration and prints the available + provers with their \verb+-wp-prover <p>+ code names. \item[\tt -wp-gen] only generates proof obligations, does not run provers. See option \texttt{-wp-out} to obtain the generated proof obligations. \item[\tt -wp-par <n>] limits the number of parallel process runs for @@ -1021,11 +1005,9 @@ proof obligations are sent to external decision procedures. obligation files to the first \texttt{n} characters. Since numbers can be added as suffixes to ensure unique filenames, their length can be longer than \texttt{n}. - No truncation is performed when the value equals zero. + No truncation is performed when the value equals zero. (default is: 60) \item[\tt -wp-(no)-proof-trace] asks for provers to output extra information on proved goals when available (default is: \texttt{no}). -\item[\tt -wp-(no)-unsat-model] asks for provers to output extra information - when goals are not proved (default is: \texttt{no}). \item[\tt -wp-timeout <n>] sets the timeout (in seconds) for the calls to the decision prover (defaults to 10 seconds). \item[\tt -wp-time-extra <n>] additional time allocated to provers when @@ -1037,122 +1019,31 @@ proof obligations are sent to external decision procedures. by prover \verb+tip+ to register the proof time. This is used to decrease the impact of machine load when proof time is closed to the timeout. Default is \verb+5s+. -\end{description} - -\hrule -\paragraph{Alt-Ergo.} -Direct support for the \textsf{Alt-Ergo} prover is provided. You need at least -version \verb+0.99+ of the prover, but more recent versions \verb+1.01+ or -\verb+1.30+ are preferrable. It is also the default selected prover. -\begin{description} -\item[\tt -wp-prover alt-ergo] selects \textsf{Alt-Ergo}. -\item[\tt -wp-prover altgr-ergo] opens the graphical interface of - \textsf{Alt-Ergo} when the goal is not proved. -\item[\tt -wp-steps <$n$>] sets the maximal number of \textsf{Alt-Ergo} +\item[\tt -wp-steps <$n$>] sets the maximal number of prover steps. This can be used as a machine-independent alternative to timeout. -\item[\tt -wp-depth <$n$>] sets '\textit{stop}' and - '\textit{age-limit}' parameters of \textsf{Alt-Ergo} such that $n$ cycles of - quantifier instantiations are enabled. -\item[\tt -wp-alt-ergo-opt <opt,...>] passes additional options to \textsf{Alt-Ergo} - (default: none). -\item[\tt -wp-alt-ergo='<cmd>'] override the \verb+alt-ergo+ command. -\item[\tt -wp-altgr-ergo='<cmd>'] override the \verb+altgr-ergo+ command. -\end{description} - -\hrule -\paragraph{Coq.} -Direct support for the \textsf{Coq} proof assistant is provided. The -generated proof obligations are accepted by \textsf{Coq} version \verb+8.4+. -When working with \textsf{Coq}, you will enter an interactive session, -then save the proof scripts in order to replay them in batch mode. - -\begin{description} -\item[\tt -wp-prover coq] runs \texttt{coqc} with the default tactic or - with the available proof script (see below). -\item[\tt -wp-prover coqide] first tries to replay some known proof - script (if any). If it does not succeed, then a new interactive - session for \texttt{coqide} is opened. As soon as \texttt{coqide} - exits, the edited proof script is saved back (see below) and finally - checked by \texttt{coqc}.\par - The only part of the edited file retained by \textsf{WP} is the proof script - between ``\texttt{Proof}\ldots\texttt{Qed.}''. -\item[\tt -wp-script <f.script>] specifies the file which proof scripts - are retrieved from, or saved to. The format of this file is private to - the \textsf{WP} plug-in. It is, however, a regular text file from which - you can cut and paste part of previously written script proofs. - The \textsf{WP} plug-in manages the content of this file for you. -\item[\tt -wp-(no)-update-script] if turned off, the user's script - file will \emph{not} be modified. A warning is emitted if the script data base - changed. -\item[\tt -wp-tactic <ltac>] specifies the \textsf{Coq} tactic to try - with when no user script is found. The default tactic is - \verb+"auto with zarith"+. See also how to load external libraries - and user-defined tactics in section~\ref{prooflibs}. -\item[\tt -wp-tryhints] When both the user-provided script and the - default tactic fail to solve the goal, other scripts for similar goals can - be tried instead. -\item[\tt -wp-hints <n>] sets the maximal number of suggested proof scripts. -\item[\tt -wp-coq-timeout <n>] sets the maximal time in seconds for running - the \texttt{coqc} checker. Does not apply to \texttt{coqide} (default: 30s). -\item[\tt -wp-coq-opt <opt,...>] additional options for \texttt{coqc} and \texttt{coqide} - (default: none). -\item[\tt -wp-coqc='<cmd>'] override the \verb+coqc+ command. -\item[\tt -wp-coqide='<cmd>'] override the \verb+coqide+ command. - If the command line contains the \verb+emacs+ word (case-insensitive), - coq-options are not passed to the command, but a coq-project is used instead. - This conforms to Proof General 4.3 settings. - The project file can be changed (see below). -\item[\tt -wp-coq-project='<name>'] override the \verb+_CoqProject+ file name - for Emacs and Proof General. -\end{description} -\hrule - -\pagebreak -\paragraph{Why-3.} -Native support for \textsf{Why-3} is provided (for versions 1.0 and newer). -\\ -Support for \textsf{Why-3 IDE} is no longer provided. -\begin{description} -\item[\tt -wp-prover "why3:<p>"] runs a \textsf{Why-3} prover named \texttt{<p>}, and - exactly behaves like invoking \verb+why3 prover -P <p>+. The list of prover - names \verb+<p>+ must be extracted from the \verb+[alias]+ section of your \textsf{Why-3} - configuration, which \verb+frama-c -wp-detect+ does for you (see below). -\item[\tt -wp-prover "<p>"] can also be used instead of \verb+-wp-prover "why3:<p>"+ - when \verb+<p>+ is not natively supported by \textsf{WP}, like \texttt{alt-ergo}, - \texttt{altgr-ergo}, \texttt{coq}, \texttt{coqide}, \texttt{script} and \texttt{tip}. -\item[\tt -wp-detect] lists the provers available for \textsf{Why-3}. - This command can only work if \textsf{why3} API was installed before building and - installing \textsf{Frama-C}. - The option reads your \textsf{Why-3} configuration and prints the available - provers with their \verb+-wp-prover <p>+ code names. -\item[\tt -wp-why3='<cmd>'] overrides the path to the \verb+why3+ command. +\item[\tt -wp-why3-opt='options,...'] provides additional options to the + \verb+why3+ command. \end{description} -\paragraph{Example of using Why-3.} +\paragraph{Example of using provers.} Suppose you have the following configuration: \begin{logs} # frama-c -wp-detect [wp] Why3 provers detected: - - Alt-Ergo 2.0.0 [why3:alt-ergo,altergo] + - Alt-Ergo 2.0.0 [alt-ergo,altergo] - CVC4 1.6 [cvc4] - CVC4 1.6 (counterexamples) [cvc4-ce] - - Coq 8.9.0 [why3:coq] + - Coq 8.9.0 [coq] - Z3 4.6.0 [z3] - Z3 4.6.0 (counterexamples) [z3-ce] - Z3 4.6.0 (noBV) [z3-nobv] \end{logs} Then, to use (for instance) \textsf{CVC4 1.6}, -you can use \verb+-wp-prover cvc4+ (since this name is not conflicting -with any native prover). Alternatively, you can also use the less ambiguous -name \verb+-wp-prover why3:cvc4+ if you prefer. -Similarly, if you want to use \textsf{Z3 4.6.0} without bitvectors, you can use \verb+-wp-prover z3-nobv+ -or \verb+-wp-prover why3:z3-nobv+. - -However, to use \textsf{Alt-Ergo 2.0.0} \emph{via} \textsf{Why-3}, you shall use -\verb+-wp-prover why3:alt-ergo+, since \verb+-wp-prover alt-ergo+ would select -the native support of \textsf{Alt-Ergo} prover. Finally, since \textsf{Why-3} also provides the alias +you can use \verb+-wp-prover cvc4+. +Similarly, if you want to use \textsf{Z3 4.6.0} without bitvectors, you can use \verb+-wp-prover z3-nobv+. +Finally, since \textsf{Why-3} also provides the alias \verb+altergo+ for this prover, \verb+-wp-prover altergo+ will also run it \emph{via} \textsf{Why-3}. Notice that \textsf{Why-3} provers benefit from a cache management when used in combination with a \textsf{WP}-session, see Section~\ref{wp-cache} for more details. @@ -1196,33 +1087,11 @@ obligations are: \label{prooflibs} It is possible to add additional bases of knowledge to decision -procedures. This support is provided for \textsf{Alt-Ergo}, -\textsf{Why3} and \textsf{Coq} thanks to the following options: +procedures thanks to the following option: \begin{description} \item[\tt -wp-share <dir>] modifies the default directory where resources are found. This option can be useful for running a modified or patched distribution of \textsf{WP}. -\item[\tt -wp-include <dir,\ldots,++sharedir>] (\textbf{deprecated} use driver instead) sets the directories where external - libraries and driver files are looked for. - The current directory (implicitly added to that list) is always looked up - first. - Relative directory names are relative to the current directory except - for names prefixed by the characters \texttt{++}. - In such a name, the directory is relative to the main \texttt{FRAMAC\_SHARE} - directory. -\item[\tt -wp-alt-ergo-lib <f,\ldots>] (\textbf{deprecated} use altergo.file - in driver instead) looks for \textsf{Alt-Ergo} - library files \verb+"f.mlw"+ and inlines them into the proof - obligation files for \textsf{Alt-Ergo}. -\item[\tt -wp-coq-lib <f,\ldots>] (\textbf{deprecated} use coq.file - in driver instead) looks for \textsf{Coq} files - \verb+"f.v"+ or \verb+"f.vo"+. If - \verb+"f.vo"+ is not found, then \textsf{WP} copies \verb+"f.v"+ - into its working directory (see option - \texttt{-wp-out}) and compiles it locally. -\item[\tt -wp-why-lib <f,\ldots>] (\textbf{deprecated} use why3.file in driver instead) looks for \textsf{Why3} library file - \verb+"f.why"+ and opens the library \verb+"f.F"+ for the proving the - goals. \end{description} \subsection{Linking \textsf{ACSL} Symbols to External Libraries} @@ -1236,8 +1105,7 @@ if any, are not exported by \textsf{WP}s. External linkage is specified in \emph{driver files}. It is possible to load one or several drivers with the following \textsf{WP} plug-in option: \begin{description} -\item[\tt -wp-driver <file,\ldots>] load specified driver files, - replacing deprecated features from section~\ref{prooflibs}. +\item[\tt -wp-driver <file,\ldots>] load specified driver files. \end{description} @@ -1283,7 +1151,7 @@ resets the option to the singleton of the given string and binding with the \verb'+=' operator adds the given string to the current value of the option. The following options are defined by the plugin: -\texttt{coq.file}, \texttt{altergo.file}, \texttt{why3.file} and \texttt{why3.import}. +\texttt{why3.file} and \texttt{why3.import}. \textsf{C}-Comments are allowed in the file. For overloaded \textsf{ACSL} symbols, it is necessary to provide one \user{link} symbol for @@ -1291,29 +1159,22 @@ each existing signature. The same \user{link} symbol is used for all provers, and must be defined in the specified libraries, or in the external ones (see~\ref{prooflibs}). -It is also possible to specify different names -for each prover, with the following syntax: -\texttt{\{coq=\user{a};altergo=\user{b};why3=\user{c}\}}. Alternatively, a link-name can be an arbitrary string with patterns substituted by arguments, \verb="(%1+%2)"= for instance. When a library \user{lib} is specified, the loaded module depends on the -target solver: +option: \begin{center}\tt - \begin{tabular}{llll} - & \textrm{Option} & \textrm{Format} \\ + \begin{tabular}{lll} + \textrm{Option} & \textrm{Format} \\ \hline - \textsf{Coq}: & coq.file & \verb+[dir:]path.v+ \\ - \textsf{Alt-Ergo}: & altergo.file & \verb+path.mlw+ \\ - \textsf{Why3}: & why3.file & \verb+path.why[:name][:as]+ \\ - & why3.import & \verb+theory[:as]+ \\ + why3.file & \verb+path.why[:name][:as]+ \\ + why3.import & \verb+theory[:as]+ \\ \end{tabular} \end{center} Precise meaning of formats is given by the following examples (all filenames are relatives to the driver file's directory): \begin{description} -\item[\tt coq.file="mydir/bar.v"] Imports module \verb+Bar+ from file \verb+mydir/bar.vo+. -\item[\tt coq.file="mydir/foo:Foo.v"] Loads coq library \verb+foo.Foo+ from file \verb+mydir/foo/Foo.vo+. \item[\tt why3.file="mydir/foo.why"] Imports theory \verb+foo.Foo+ from directory \verb+mydir+. \item[\tt why3.file="mydir/foo.why:Bar"] Imports theory \verb+foo.Bar+ from directory \verb+mydir+. \item[\tt why3.file="mydir/foo.why:Bar:T"] Imports theory \verb+foo.Bar as T+ from directory \verb+mydir+. @@ -1324,7 +1185,7 @@ Precise meaning of formats is given by the following examples (all filenames are See also the default \textsf{WP} driver file, in \verb+[wp-share]/wp.driver+. Optional \textit{property-tags} can be given to -\texttt{logic} \user{link} symbols to allow the WP to perform +\texttt{logic} \user{link} symbols to allow the \textsf{WP} plugin to perform additional simplifications (See section~\ref{wp-simplifier}). Tags consist of an identifier with column (`\verb+:+'), sometimes followed by a link (`\user{link};'). The available tags are depicted on figure~\ref{wp-driver-tags}. @@ -1380,17 +1241,15 @@ interactively or incrementally, it is often the case where most proof obligation from one \textsf{WP} execution to the other. To reduce this costs, a cache of prover results can be used and stored in your session. -The cache can only be used with \textsf{Why-3} provers, it does not work with native \textsf{Alt-Ergo} -and \textsf{Coq} provers -- although proof scripts works with both. +% The cache can only be used with \textsf{Why-3} provers, it does not work with native \textsf{Alt-Ergo} and \textsf{Coq} provers. There are different ways of using the cache, depending on your precise needs. - -The \textsf{WP} options to control session and cache are \verb+-wp-session+ and \verb+-wp-cache+, as documented below: +The main option to control cache usage is \verb+-wp-cache+, documented below: \begin{description} \item[\tt -wp-session <dir>] select the directory where cached results and proof scripts are stored. If the local directory \verb+'.frama-c'+ already exists, the default session directory \verb+'.frama-c/wp'+ will be used to setup the \textsf{WP} session. -\item[\tt -wp-cache <mode>] selects the cache mode to use with why3 provers. The default mode is \verb'update' +\item[\tt -wp-cache <mode>] selects the cache mode to use with \textsf{Why-3} provers. The default mode is \verb'update' if a \textsf{WP} session is set, and \verb+none+ otherwise. The cache entries are stored in the session directory, which is \verb+./.frama-c/wp/cache+ by default. \end{description} @@ -1401,7 +1260,7 @@ The available cache modes are described below: \item [\tt -wp-cache cleanup]: same as \verb+update+ mode but at the end of \textsf{Frama-C} execution, any cache entry that was not used nor updated will be deleted. This mode shall be only used when you want to cleanup your cache with old useless entries, typically at the end of an interactive session. \item [\tt -wp-cache replay]: same as \verb+update+ mode but new results are \emph{not} stored in the cache. This mode is useful for continuous integration, when you are not sure your cache is complete but don't want to modify it. \item [\tt -wp-cache offline]: similar to \verb+replay+ mode but cache entries are the unique source of results. Provers are never run and missing cache entries would result in a «~Failed~» verdict. This mode is useful to fasten continuous integration and enforcing cache completeness. -\item [\tt -wp-cache rebuild]: force prover execution and store all results in the cache. Previous results will be replaced with new onces, but entries for non relevant proofs would be kept and you might need a cleanup stage after. This mode is useful when you modify you why3 or prover installation and you don't want to reuse your previous cache entries. +\item [\tt -wp-cache rebuild]: force prover execution and store all results in the cache. Previous results will be replaced with new onces, but entries for non relevant proofs would be kept and you might need a cleanup stage after. This mode is useful when you modify your \textsf{Why-3} or prover installation and you don't want to reuse your previous cache entries. \item [\tt -wp-cache none]: do not use nor modify cache entries; provers are run normally. This option must be used if you have a session set and you don't want to use the cache, since the default is mode \verb+update+ in this case. But you probably always to benefit from a cache when you have an (interactive) session. \end{description} @@ -1411,13 +1270,8 @@ Cached usage is indicated on the standard output, unless you specify \verb+-wp-m \section{Plug-in Developer Interface} \label{wp-api} -The \textsf{WP} plug-in has several entry points registered in the -\texttt{Dynamic}\footnote{See the \emph{plug-in development guide}} -module of \textsf{Frama-C}. - -Those entry points are however deprecated. -Instead, a full featured \textsf{OCaml} API is now exported with the -\textsf{Wp} plug-in. As documented in the \textsf{Frama-C} user manual, simply add the directive \verb!PLUGIN_DEPENDENCIES+=Wp! to the Makefile of your plug-in. +A full featured \textsf{OCaml} API is exported with the +\textsf{WP} plug-in. As documented in the \textsf{Frama-C} user manual, simply add the directive \verb!PLUGIN_DEPENDENCIES+=Wp! to the Makefile of your plug-in. The high-level API for generating and proving properties is exported in module \textsf{Wp.API}. The logical interface, compilers, and memory models are also accessible. See the generated \textsf{HTML} documentation of the platform for details. diff --git a/src/plugins/wp/tests/wp_acsl/classify_float.c b/src/plugins/wp/tests/wp_acsl/classify_float.c index 56d2e6eb231a27cdf34dc5af45d905a5570d4df7..570d50707379b44f32c2c6f1cb71d2723f202a35 100644 --- a/src/plugins/wp/tests/wp_acsl/classify_float.c +++ b/src/plugins/wp/tests/wp_acsl/classify_float.c @@ -2,6 +2,7 @@ OPT: -wp-prover alt-ergo OPT: -wp-prover native:alt-ergo OPT: -wp-prover native:coq -wp-coq-script tests/wp_acsl/classify_float.script + OPT: -wp-model real */ /*@ diff --git a/src/plugins/wp/tests/wp_acsl/float_compare.i b/src/plugins/wp/tests/wp_acsl/float_compare.i index 6abdcffafafa069a0139033e6fd83e41313f8e29..5a51c59c107c89515c77d25111d88c3dfee3d582 100644 --- a/src/plugins/wp/tests/wp_acsl/float_compare.i +++ b/src/plugins/wp/tests/wp_acsl/float_compare.i @@ -1,5 +1,6 @@ /* run.config_qualif OPT: -wp-prover why3:alt-ergo + OPT: -wp-model real */ /*@ lemma test_float_compare: diff --git a/src/plugins/wp/tests/wp_acsl/oracle/float_compare.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/float_compare.res.oracle index 0fc794250f024d6e9e85362c6e510e2ef6e11813..b43e2d4a8152b36cd0531f01f796d4665b036ec1 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle/float_compare.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle/float_compare.res.oracle @@ -121,13 +121,13 @@ Prove: lt_f64(a_1, b) <-> (r < of_f64(b)). ------------------------------------------------------------ -Goal Assertion (file tests/wp_acsl/float_compare.i, line 62): +Goal Assertion (file tests/wp_acsl/float_compare.i, line 63): Assume { (* Pre-condition *) Have: is_finite_f32(a) /\ is_finite_f64(b). } Prove: is_finite_f64(to_f64(of_f32(a))). ------------------------------------------------------------ -Goal Assertion (file tests/wp_acsl/float_compare.i, line 63): +Goal Assertion (file tests/wp_acsl/float_compare.i, line 64): Let r = of_f32(a). Let a_1 = to_f64(r). Assume { diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/classify_float.3.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/classify_float.3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ab4451e7b05126a076003f9d0c98f00efca996ef --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/classify_float.3.res.oracle @@ -0,0 +1,16 @@ +# frama-c -wp -wp-model 'Typed (Real)' [...] +[kernel] Parsing tests/wp_acsl/classify_float.c (with preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] 3 goals scheduled +[wp] [Qed] Goal typed_real_lemma_InfN_not_finite : Valid +[wp] [Qed] Goal typed_real_lemma_InfP_not_finite : Valid +[wp] [Qed] Goal typed_real_lemma_NaN_not_finite : Valid +[wp] Proved goals: 3 / 3 + Qed: 3 +[wp] Report in: 'tests/wp_acsl/oracle_qualif/classify_float.3.report.json' +[wp] Report out: 'tests/wp_acsl/result_qualif/classify_float.3.report.json' +------------------------------------------------------------- +Axiomatics WP Alt-Ergo Total Success +Lemma 3 - 3 100% +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.0.res.oracle similarity index 100% rename from src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.res.oracle rename to src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.0.res.oracle diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d2cccc3d319aaf4d8f39e61cdaf04a28d717b99b --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.res.oracle @@ -0,0 +1,40 @@ +# frama-c -wp -wp-model 'Typed (Real)' [...] +[kernel] Parsing tests/wp_acsl/float_compare.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 19 goals scheduled +[wp] [Qed] Goal typed_real_lemma_finite_32_64 : Valid +[wp] [Qed] Goal typed_real_lemma_finite_32_64_real : Valid +[wp] [Alt-Ergo 2.0.0] Goal typed_real_lemma_test_double_compare : Valid +[wp] [Alt-Ergo 2.0.0] Goal typed_real_lemma_test_double_compare_greater : Valid +[wp] [Alt-Ergo 2.0.0] Goal typed_real_lemma_test_float_compare : Valid +[wp] [Alt-Ergo 2.0.0] Goal typed_real_lemma_test_float_compare_greater : Valid +[wp] [Qed] Goal typed_real_cmp_dd_ensures_DEF : Valid +[wp] [Qed] Goal typed_real_cmp_dd_ensures_REL1 : Valid +[wp] [Qed] Goal typed_real_cmp_dd_ensures_REL2 : Valid +[wp] [Qed] Goal typed_real_cmp_fd_ensures_DEF : Valid +[wp] [Qed] Goal typed_real_cmp_fd_ensures_REL1 : Valid +[wp] [Qed] Goal typed_real_cmp_fd_ensures_REL2 : Valid +[wp] [Qed] Goal typed_real_cmp_fd_assert : Valid +[wp] [Qed] Goal typed_real_cmp_fd_assert_2 : Valid +[wp] [Qed] Goal typed_real_cmp_ff_ensures_DEF : Valid +[wp] [Qed] Goal typed_real_cmp_ff_ensures_REL1 : Valid +[wp] [Qed] Goal typed_real_cmp_ff_ensures_REL2 : Valid +[wp] [Qed] Goal typed_real_cmp_fnan_ensures_POS : Valid +[wp] [Qed] Goal typed_real_cmp_fnan_ensures_NEG : Valid +[wp] Proved goals: 19 / 19 + Qed: 15 + Alt-Ergo 2.0.0: 4 +[wp] Report in: 'tests/wp_acsl/oracle_qualif/float_compare.1.report.json' +[wp] Report out: 'tests/wp_acsl/result_qualif/float_compare.1.report.json' +------------------------------------------------------------- +Axiomatics WP Alt-Ergo Total Success +Lemma 2 4 (1..12) 6 100% +------------------------------------------------------------- +Functions WP Alt-Ergo Total Success +cmp_ff 3 - 3 100% +cmp_dd 3 - 3 100% +cmp_fd 5 - 5 100% +cmp_fnan 2 - 2 100% +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/0229e4d03dbe5dab56c7710d10ede856.json b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/0229e4d03dbe5dab56c7710d10ede856.json new file mode 100644 index 0000000000000000000000000000000000000000..b875f72878672c071518369a3e24ffe8ff01f98b --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/0229e4d03dbe5dab56c7710d10ede856.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0057, + "steps": 4 } diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/5a2626cdfff12f90f4c43a8b11ff70fb.json b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/5a2626cdfff12f90f4c43a8b11ff70fb.json new file mode 100644 index 0000000000000000000000000000000000000000..cdba4fe113543f699c812db47d6cbe7d2fa2ba20 --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/5a2626cdfff12f90f4c43a8b11ff70fb.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0047, + "steps": 4 } diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/d189bb3b47019848c9af5b14c2febb1c.json b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/d189bb3b47019848c9af5b14c2febb1c.json new file mode 100644 index 0000000000000000000000000000000000000000..16eacff0af61e1b60c56f922f046783dfb7dc0ff --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/d189bb3b47019848c9af5b14c2febb1c.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0056, + "steps": 4 } diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/e2c00d7a3ff17960fa10dee8b619ee99.json b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/e2c00d7a3ff17960fa10dee8b619ee99.json new file mode 100644 index 0000000000000000000000000000000000000000..4d58671fa0e00cc8296590f2ad4014d8c431e7f9 --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/float_compare.1.session/cache/e2c00d7a3ff17960fa10dee8b619ee99.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.005, + "steps": 4 } diff --git a/src/plugins/wp/tests/wp_bts/bts_2471.i b/src/plugins/wp/tests/wp_bts/bts_2471.i new file mode 100644 index 0000000000000000000000000000000000000000..2419c0debd8c56f0daafc2f0bdae517aadb72fff --- /dev/null +++ b/src/plugins/wp/tests/wp_bts/bts_2471.i @@ -0,0 +1,22 @@ +/* run.config + DONTRUN: + */ + +/* run.config_qualif + OPT: -wp-timeout 1 + OPT: -wp-prover native:alt-ergo -wp-timeout 1 + OPT: -wp-prover native:coq + */ + +/*@ axiomatic maps { + type model_digit = octet | sextet; + logic integer foo(model_digit i); + } +*/ + +int foo() +{ + // Shall not fail (parse error in BTS issue) + //@assert ko: \forall int i; i == foo(octet); + return 0; +} diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.0.res.oracle b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..496e2f0690073f685362bcf86099d58a7ae46d38 --- /dev/null +++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.0.res.oracle @@ -0,0 +1,15 @@ +# frama-c -wp -wp-timeout 1 [...] +[kernel] Parsing tests/wp_bts/bts_2471.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 1 goal scheduled +[wp] [Alt-Ergo 2.0.0] Goal typed_foo_assert_ko : Unsuccess +[wp] Proved goals: 0 / 1 + Alt-Ergo 2.0.0: 0 (unsuccess: 1) +[wp] Report in: 'tests/wp_bts/oracle_qualif/bts_2471.0.report.json' +[wp] Report out: 'tests/wp_bts/result_qualif/bts_2471.0.report.json' +------------------------------------------------------------- +Functions WP Alt-Ergo Total Success +foo - - 1 0.0% +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.0.session/cache/73ea306163d25a228b4586b8b98472f6.json b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.0.session/cache/73ea306163d25a228b4586b8b98472f6.json new file mode 100644 index 0000000000000000000000000000000000000000..852d81aab273985772cb5b7d655f3f996ee7db5d --- /dev/null +++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.0.session/cache/73ea306163d25a228b4586b8b98472f6.json @@ -0,0 +1 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "timeout", "time": 1. } diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.1.res.oracle b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..68dc1319cde49b90405061a831cef2979123dab9 --- /dev/null +++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.1.res.oracle @@ -0,0 +1,15 @@ +# frama-c -wp -wp-timeout 1 [...] +[kernel] Parsing tests/wp_bts/bts_2471.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 1 goal scheduled +[wp] [Alt-Ergo (Native)] Goal typed_foo_assert_ko : Unsuccess +[wp] Proved goals: 0 / 1 + Alt-Ergo: 0 (unsuccess: 1) +[wp] Report in: 'tests/wp_bts/oracle_qualif/bts_2471.1.report.json' +[wp] Report out: 'tests/wp_bts/result_qualif/bts_2471.1.report.json' +------------------------------------------------------------- +Functions WP Alt-Ergo Total Success +foo - - 1 0.0% +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.2.res.oracle b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6c44b75068c14cfa5ea543478657ca61008ceeef --- /dev/null +++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts_2471.2.res.oracle @@ -0,0 +1,16 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_bts/bts_2471.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[wp] Warning: Missing RTE guards +[wp] 1 goal scheduled +[wp] [Coq] Goal typed_foo_assert_ko : Default tactic +[wp] [Coq (Native)] Goal typed_foo_assert_ko : Unsuccess +[wp] Proved goals: 0 / 1 + Coq: 0 (unsuccess: 1) +[wp] Report in: 'tests/wp_bts/oracle_qualif/bts_2471.2.report.json' +[wp] Report out: 'tests/wp_bts/result_qualif/bts_2471.2.report.json' +------------------------------------------------------------- +Functions WP Alt-Ergo Total Success +foo - - 1 0.0% +------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_plugin/stmt.c b/src/plugins/wp/tests/wp_plugin/stmt.c index 8af5d5b9b0e414ee0c10c80c1e8cf3c33ce485f3..62abcac4c5aa56351164c02fba1c2185ece058d4 100644 --- a/src/plugins/wp/tests/wp_plugin/stmt.c +++ b/src/plugins/wp/tests/wp_plugin/stmt.c @@ -4,7 +4,7 @@ /* run.config_qualif OPT: -load-module report -then -report - EXECNOW: LOG stmt.log LOG f.dot LOG f_default_for_stmt_2.dot LOG g.dot LOG g_default_for_stmt_11.dot @frama-c@ -no-autoload-plugins -load-module wp -wp-precond-weakening -wp -wp-model Dump -wp-out tests/wp_plugin/result_qualif @PTEST_FILE@ -wp-cache none 1> tests/wp_plugin/result_qualif/stmt.log + EXECNOW: LOG stmt.log LOG f.dot LOG f_default_for_stmt_2.dot LOG g.dot LOG g_default_for_stmt_11.dot @frama-c@ -no-autoload-plugins -load-module wp -wp-precond-weakening -wp -wp-model Dump -wp-out tests/wp_plugin/result_qualif -wp-cache none @PTEST_FILE@ 1> tests/wp_plugin/result_qualif/stmt.log */ /*@ ensures a > 0 ==> \result == a + b; diff --git a/src/plugins/wp/tests/wp_typed/mvar.i b/src/plugins/wp/tests/wp_typed/mvar.i new file mode 100644 index 0000000000000000000000000000000000000000..396b66373edf0915c76759110eedfd8ce1b64240 --- /dev/null +++ b/src/plugins/wp/tests/wp_typed/mvar.i @@ -0,0 +1,20 @@ +extern char A[20]; + +//@ predicate equal(integer x,integer y) = x==y ; + +/*@ + ensures \forall integer i ; 0 <= i < n ==> \at( A[i] == *(p + i) , Pre); + */ +extern void Write(char *p, int n); + + +/*@ + ensures equal(A[0],1) ; + */ +void Job(void) +{ + char DataWrite; + DataWrite = 1 ; + Write((& DataWrite),1); + return; +} diff --git a/src/plugins/wp/tests/wp_typed/oracle/mvar.0.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/mvar.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b290830da12f38bd7a0be3610f09ae4b77108df9 --- /dev/null +++ b/src/plugins/wp/tests/wp_typed/oracle/mvar.0.res.oracle @@ -0,0 +1,21 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_typed/mvar.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[kernel] tests/wp_typed/mvar.i:14: Warning: + No code nor implicit assigns clause for function Write, generating default assigns from the prototype +[wp] Warning: Missing RTE guards +------------------------------------------------------------ + Function Job +------------------------------------------------------------ + +Goal Post-condition (file tests/wp_typed/mvar.i, line 12) in 'Job': +Assume { + (* Heap *) + Have: linked(Malloc_0) /\ sconst(Mchar_0). + (* Call 'Write' *) + Have: A[0] = 1. +} +Prove: P_equal(1, 1). + +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_typed/oracle/mvar.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/mvar.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c5ee1a264cf0f1bb92bd2c8d9ea4c9ff09c56a40 --- /dev/null +++ b/src/plugins/wp/tests/wp_typed/oracle/mvar.1.res.oracle @@ -0,0 +1,21 @@ +# frama-c -wp -wp-model 'Typed (Ref)' [...] +[kernel] Parsing tests/wp_typed/mvar.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[kernel] tests/wp_typed/mvar.i:14: Warning: + No code nor implicit assigns clause for function Write, generating default assigns from the prototype +[wp] Warning: Missing RTE guards +------------------------------------------------------------ + Function Job +------------------------------------------------------------ + +Goal Post-condition (file tests/wp_typed/mvar.i, line 12) in 'Job': +Assume { + (* Heap *) + Have: linked(Malloc_0) /\ sconst(Mchar_0). + (* Call 'Write' *) + Have: A[0] = 1. +} +Prove: P_equal(1, 1). + +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.report.json b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.report.json new file mode 100644 index 0000000000000000000000000000000000000000..5d34a2aa148ec69a768c4de87205861440f6366d --- /dev/null +++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.report.json @@ -0,0 +1,14 @@ +{ "wp:global": { "why3:Alt-Ergo,2.0.0": { "total": 1, "valid": 1, "rank": 1 }, + "wp:main": { "total": 1, "valid": 1, "rank": 1 } }, + "wp:functions": { "Job": { "Job_ensures": { "why3:Alt-Ergo,2.0.0": + { "total": 1, "valid": 1, + "rank": 1 }, + "wp:main": { "total": 1, + "valid": 1, + "rank": 1 } }, + "wp:section": { "why3:Alt-Ergo,2.0.0": { "total": 1, + "valid": 1, + "rank": 1 }, + "wp:main": { "total": 1, + "valid": 1, + "rank": 1 } } } } } diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.session/cache/895ce5c124c30552810b4458d89f3885.json b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.session/cache/895ce5c124c30552810b4458d89f3885.json new file mode 100644 index 0000000000000000000000000000000000000000..5230d4cfc10fead23aa88fcd978ebb16058ac3bb --- /dev/null +++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.session/cache/895ce5c124c30552810b4458d89f3885.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0081, + "steps": 6 } diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.session/cache/e5ffef57a0640be83d7c30f0890f6022.json b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.session/cache/e5ffef57a0640be83d7c30f0890f6022.json new file mode 100644 index 0000000000000000000000000000000000000000..8722bffd2aab5ce648cc2e4e69a78617a55cc0c6 --- /dev/null +++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.0.session/cache/e5ffef57a0640be83d7c30f0890f6022.json @@ -0,0 +1,2 @@ +{ "prover": "why3:Alt-Ergo,2.0.0", "verdict": "valid", "time": 0.0089, + "steps": 5 } diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..48f19a88154aac3ef6ba18614891f4c87c71fdaa --- /dev/null +++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/mvar.res.oracle @@ -0,0 +1,18 @@ +# frama-c -wp [...] +[kernel] Parsing tests/wp_typed/mvar.i (no preprocessing) +[wp] Running WP plugin... +[wp] Loading driver 'share/wp.driver' +[kernel] tests/wp_typed/mvar.i:14: Warning: + No code nor implicit assigns clause for function Write, generating default assigns from the prototype +[wp] Warning: Missing RTE guards +[wp] 1 goal scheduled +[wp] [Alt-Ergo 2.0.0] Goal typed_Job_ensures : Valid +[wp] Proved goals: 1 / 1 + Qed: 0 + Alt-Ergo 2.0.0: 1 +[wp] Report in: 'tests/wp_typed/oracle_qualif/mvar.0.report.json' +[wp] Report out: 'tests/wp_typed/result_qualif/mvar.0.report.json' +------------------------------------------------------------- +Functions WP Alt-Ergo Total Success +Job - 1 (1..12) 1 100% +------------------------------------------------------------- diff --git a/tests/builtins/diff_octagons b/tests/builtins/diff_octagons new file mode 100644 index 0000000000000000000000000000000000000000..0054c1a3abad131720e7bd2fa952732a6567d75c --- /dev/null +++ b/tests/builtins/diff_octagons @@ -0,0 +1,335 @@ +diff tests/builtins/oracle/Longinit_sequencer.res.oracle tests/builtins/oracle_octagons/Longinit_sequencer.res.oracle +327c327 +< tests/builtins/result/Longinit_sequencer.sav +--- +> tests/builtins/result_octagons/Longinit_sequencer.sav +568c568 +< tests/builtins/result/Longinit_sequencer.sav +--- +> tests/builtins/result_octagons/Longinit_sequencer.sav +diff tests/builtins/oracle/allocated.0.res.oracle tests/builtins/oracle_octagons/allocated.0.res.oracle +273c273 +< j ∈ [1..2147483647] +--- +> j ∈ {10} +diff tests/builtins/oracle/allocated.1.res.oracle tests/builtins/oracle_octagons/allocated.1.res.oracle +191a192,194 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_7 +208a212,214 +> strong free on bases: {__malloc_main_l82_7} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +223a230,232 +> strong free on bases: {__malloc_main_l82_7} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +238a248,250 +> strong free on bases: {__malloc_main_l82_7} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +252,254c264,266 +< [eva] tests/builtins/allocated.c:82: +< Call to builtin Frama_C_malloc_fresh for function malloc +< [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_7 +--- +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_7} +323a336,356 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_31 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_32 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_33 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_34 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_35 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_36 +> [eva] tests/builtins/allocated.c:82: +> Call to builtin Frama_C_malloc_fresh for function malloc +> [eva] tests/builtins/allocated.c:82: allocating variable __malloc_main_l82_37 +329,330d361 +< Trace partitioning superposing up to 300 states +< [eva] tests/builtins/allocated.c:84: +333a365,385 +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +403c455,473 +< strong free on bases: {__malloc_main_l82_7} +--- +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +475c545,563 +< strong free on bases: {__malloc_main_l82_7} +--- +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +547c635,653 +< strong free on bases: {__malloc_main_l82_7} +--- +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +619c725,743 +< strong free on bases: {__malloc_main_l82_7} +--- +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +691c815,833 +< strong free on bases: {__malloc_main_l82_7} +--- +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +763c905,923 +< strong free on bases: {__malloc_main_l82_7} +--- +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +835c995,1013 +< strong free on bases: {__malloc_main_l82_7} +--- +> strong free on bases: {__malloc_main_l82_37} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_36} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_35} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_34} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_33} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_32} +> [eva] tests/builtins/allocated.c:87: Call to builtin free +> [eva:malloc] tests/builtins/allocated.c:87: +> strong free on bases: {__malloc_main_l82_31} +905,907c1083,1084 +< [eva] tests/builtins/allocated.c:87: Call to builtin free +< [eva:malloc] tests/builtins/allocated.c:87: +< strong free on bases: {__malloc_main_l82_7} +--- +> [eva] tests/builtins/allocated.c:81: +> Trace partitioning superposing up to 500 states +1069,1071c1246,1247 +< __malloc_main_l82_7[0] ∈ {21} or UNINITIALIZED +< [1] ∈ {24} or UNINITIALIZED +< [2] ∈ {27} or UNINITIALIZED +--- +> __malloc_main_l82_7[0] ∈ {14} or UNINITIALIZED +> [1] ∈ {17} or UNINITIALIZED +1140a1317,1337 +> __malloc_main_l82_31[0] ∈ {21} or UNINITIALIZED +> [1] ∈ {24} or UNINITIALIZED +> [2] ∈ {27} or UNINITIALIZED +> __malloc_main_l82_32[0] ∈ {21} or UNINITIALIZED +> [1] ∈ {24} or UNINITIALIZED +> [2] ∈ {27} or UNINITIALIZED +> __malloc_main_l82_33[0] ∈ {21} or UNINITIALIZED +> [1] ∈ {24} or UNINITIALIZED +> [2] ∈ {27} or UNINITIALIZED +> __malloc_main_l82_34[0] ∈ {21} or UNINITIALIZED +> [1] ∈ {24} or UNINITIALIZED +> [2] ∈ {27} or UNINITIALIZED +> __malloc_main_l82_35[0] ∈ {21} or UNINITIALIZED +> [1] ∈ {24} or UNINITIALIZED +> [2] ∈ {27} or UNINITIALIZED +> __malloc_main_l82_36[0] ∈ {21} or UNINITIALIZED +> [1] ∈ {24} or UNINITIALIZED +> [2] ∈ {27} or UNINITIALIZED +> __malloc_main_l82_37[0] ∈ {21} or UNINITIALIZED +> [1] ∈ {24} or UNINITIALIZED +> [2] ∈ {27} or UNINITIALIZED +1184c1381 +< __malloc_main_l82_7[0..2] FROM __fc_heap_status; nondet (and SELF) +--- +> __malloc_main_l82_7[0..1] FROM __fc_heap_status; nondet (and SELF) +1207a1405,1411 +> __malloc_main_l82_31[0..2] FROM __fc_heap_status; nondet (and SELF) +> __malloc_main_l82_32[0..2] FROM __fc_heap_status; nondet (and SELF) +> __malloc_main_l82_33[0..2] FROM __fc_heap_status; nondet (and SELF) +> __malloc_main_l82_34[0..2] FROM __fc_heap_status; nondet (and SELF) +> __malloc_main_l82_35[0..2] FROM __fc_heap_status; nondet (and SELF) +> __malloc_main_l82_36[0..2] FROM __fc_heap_status; nondet (and SELF) +> __malloc_main_l82_37[0..2] FROM __fc_heap_status; nondet (and SELF) +1231c1435 +< __malloc_main_l82_6[0..1]; __malloc_main_l82_7[0..2]; +--- +> __malloc_main_l82_6[0..1]; __malloc_main_l82_7[0..1]; +1243,1244c1447,1452 +< __malloc_main_l82_30[0..2]; __malloc_main_l97[0]; __malloc_main_l114[0..3]; +< __malloc_main_l127; __malloc_main_l127_0[0..1]; __malloc_main_l127_1[0..2]; +--- +> __malloc_main_l82_30[0..2]; __malloc_main_l82_31[0..2]; +> __malloc_main_l82_32[0..2]; __malloc_main_l82_33[0..2]; +> __malloc_main_l82_34[0..2]; __malloc_main_l82_35[0..2]; +> __malloc_main_l82_36[0..2]; __malloc_main_l82_37[0..2]; +> __malloc_main_l97[0]; __malloc_main_l114[0..3]; __malloc_main_l127; +> __malloc_main_l127_0[0..1]; __malloc_main_l127_1[0..2]; +diff tests/builtins/oracle/imprecise.res.oracle tests/builtins/oracle_octagons/imprecise.res.oracle +224a225,226 +> [kernel] tests/builtins/imprecise.c:111: +> more than 200(300) elements to enumerate. Approximating. +233a236,237 +> [kernel] tests/builtins/imprecise.c:114: +> more than 200(300) elements to enumerate. Approximating. +237,240d240 +< [kernel] tests/builtins/imprecise.c:111: +< more than 200(300) elements to enumerate. Approximating. +< [kernel] tests/builtins/imprecise.c:114: +< more than 200(300) elements to enumerate. Approximating. +diff tests/builtins/oracle/linked_list.1.res.oracle tests/builtins/oracle_octagons/linked_list.1.res.oracle +506a507,508 +> [kernel] tests/builtins/linked_list.c:43: +> more than 100(128) elements to enumerate. Approximating. +508a511,512 +> [kernel] tests/builtins/linked_list.c:44: +> more than 100(128) elements to enumerate. Approximating. +600,603d603 +< [kernel] tests/builtins/linked_list.c:43: +< more than 100(128) elements to enumerate. Approximating. +< [kernel] tests/builtins/linked_list.c:44: +< more than 100(128) elements to enumerate. Approximating. +diff tests/builtins/oracle/malloc-optimistic.res.oracle tests/builtins/oracle_octagons/malloc-optimistic.res.oracle +3520c3520 +< i ∈ [14..100] +--- +> i ∈ {98; 99; 100} +3524c3524 +< i ∈ [14..100] +--- +> i ∈ {98; 99; 100} diff --git a/tests/builtins/oracle/linked_list.0.res.oracle b/tests/builtins/oracle/linked_list.0.res.oracle index a720cea4364ad8be5ec34cc894fc4c0c6c6b63a0..7edb0dc61aa38f4ca9fa5dd58d0b5404bc3a30ec 100644 --- a/tests/builtins/oracle/linked_list.0.res.oracle +++ b/tests/builtins/oracle/linked_list.0.res.oracle @@ -15,6 +15,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -55,6 +57,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -91,6 +95,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -130,6 +136,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -168,6 +176,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -210,6 +220,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -250,6 +262,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -294,6 +308,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -336,6 +352,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -382,6 +400,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -426,6 +446,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -474,6 +496,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -765,6 +789,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} @@ -1058,6 +1084,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..2047] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {32767} diff --git a/tests/builtins/oracle/linked_list.1.res.oracle b/tests/builtins/oracle/linked_list.1.res.oracle index 67b3d10651f9e9d8f7d950db2f0cc401ee64c0bf..58a095a29ca9923f3349863a3f663a973737095e 100644 --- a/tests/builtins/oracle/linked_list.1.res.oracle +++ b/tests/builtins/oracle/linked_list.1.res.oracle @@ -15,6 +15,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -55,6 +57,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -91,6 +95,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -130,6 +136,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -168,6 +176,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -210,6 +220,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -250,6 +262,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -294,6 +308,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -336,6 +352,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -382,6 +400,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -427,6 +447,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -476,6 +498,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -519,6 +543,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -560,6 +586,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} diff --git a/tests/builtins/oracle/linked_list.2.res.oracle b/tests/builtins/oracle/linked_list.2.res.oracle index 4687366532f8f130442769db11f45930b3d4ec6e..b893ef1a658089db5f2be138b4391460dc1624ea 100644 --- a/tests/builtins/oracle/linked_list.2.res.oracle +++ b/tests/builtins/oracle/linked_list.2.res.oracle @@ -15,6 +15,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -55,6 +57,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -90,6 +94,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -129,6 +135,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -167,6 +175,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -209,6 +219,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -249,6 +261,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -293,6 +307,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -335,6 +351,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -381,6 +399,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -425,6 +445,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -473,6 +495,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -519,6 +543,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -569,6 +595,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -617,6 +645,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -669,6 +699,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -719,6 +751,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -773,6 +807,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -825,6 +861,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} @@ -881,6 +919,8 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} + __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] __fc_rand_max ∈ {0x7FFF} diff --git a/tests/builtins/oracle/memcpy.res.oracle b/tests/builtins/oracle/memcpy.res.oracle index 630d2219ba4794e3763ba8e70b88cedb13ad48b3..9deb0bc5e01c04aaea0bbf5178f55316e8f09166 100644 --- a/tests/builtins/oracle/memcpy.res.oracle +++ b/tests/builtins/oracle/memcpy.res.oracle @@ -1055,6 +1055,8 @@ Unverifiable but considered Valid. [ Extern ] Axiom 'wcsncmp_zero' Unverifiable but considered Valid. +[ Extern ] Axiom 'wmemchr_def' + Unverifiable but considered Valid. [ Valid ] Axiomatic 'MemChr' by Frama-C kernel. [ Valid ] Axiomatic 'MemCmp' @@ -1069,6 +1071,8 @@ by Frama-C kernel. [ Valid ] Axiomatic 'StrNCmp' by Frama-C kernel. +[ Valid ] Axiomatic 'WMemChr' + by Frama-C kernel. [ Valid ] Axiomatic 'WcsChr' by Frama-C kernel. [ Valid ] Axiomatic 'WcsCmp' @@ -2216,9 +2220,9 @@ -------------------------------------------------------------------------------- --- Status Report Summary -------------------------------------------------------------------------------- - 161 Completely validated - 238 Considered valid + 162 Completely validated + 239 Considered valid 29 To be validated 4 Alarms emitted - 432 Total + 434 Total -------------------------------------------------------------------------------- diff --git a/tests/builtins/oracle/wcslen.res.oracle b/tests/builtins/oracle/wcslen.res.oracle index 95f2548751afd2e5be3566ba103027f089417ec5..f5a97cc85744af051d76551bd0250596ac7f074f 100644 --- a/tests/builtins/oracle/wcslen.res.oracle +++ b/tests/builtins/oracle/wcslen.res.oracle @@ -618,7 +618,7 @@ [inout] Inputs for function misc: Frama_C_entropy_source; static_str; zero_str; tab_str[0..11]; unterminated_string[0..11]; nondet; L"Hello World\n"[bits 0 to 415]; - L"abc\000\000\000abc"[bits 0 to 319]; L""; L"a"[bits 0 to 63]; + L"abc\000\000\000abc"[bits 0 to 127]; L""; L"a"[bits 0 to 63]; L"aa"[bits 0 to 95]; L"aaa"[bits 0 to 127]; L"aaaa"[bits 0 to 159]; L"aaaaa"[bits 0 to 191]; L"aaaaaa"[bits 0 to 223]; L"aaaaaaaaa"[bits 0 to 319]; L"aaaaaaaaaa"[bits 0 to 351]; @@ -662,7 +662,7 @@ [inout] Inputs for function main: Frama_C_entropy_source; static_str; zero_str; tab_str[0..11]; unterminated_string[0..11]; nondet; L"Hello World\n"[bits 0 to 415]; - L"abc\000\000\000abc"[bits 0 to 319]; L""; L"a"[bits 0 to 63]; + L"abc\000\000\000abc"[bits 0 to 127]; L""; L"a"[bits 0 to 63]; L"aa"[bits 0 to 95]; L"aaa"[bits 0 to 127]; L"aaaa"[bits 0 to 159]; L"aaaaa"[bits 0 to 191]; L"aaaaaa"[bits 0 to 223]; L"aaaaaaaaa"[bits 0 to 319]; L"aaaaaaaaaa"[bits 0 to 351]; diff --git a/tests/builtins/test_config_octagons b/tests/builtins/test_config_octagons new file mode 100644 index 0000000000000000000000000000000000000000..848a1c5fa4142125e0dc80808d0a8027d9760a2a --- /dev/null +++ b/tests/builtins/test_config_octagons @@ -0,0 +1,3 @@ +MACRO: EVA_OPTIONS @EVA_OPTIONS@ -eva-msg-key malloc -eva-warn-key malloc:weak=feedback -eva-no-alloc-returns-null -eva-octagon-domain +MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic +OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/callgraph/oracle/issue_55_iter_over_unregistered_function.res.oracle b/tests/callgraph/oracle/issue_55_iter_over_unregistered_function.res.oracle index f2b3a6b73869d6056238fbd7bb1d8b664c3957b1..2efdf3909b39756e6eb8ab9986733941c1167363 100644 --- a/tests/callgraph/oracle/issue_55_iter_over_unregistered_function.res.oracle +++ b/tests/callgraph/oracle/issue_55_iter_over_unregistered_function.res.oracle @@ -11,7 +11,7 @@ assertion 'Eva,initialization' got final status invalid. [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 3): 33% coverage. + 1 function analyzed (out of 1): 100% coverage. In this function, 1 statements reached (out of 3): 33% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. 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/float/diff_octagons b/tests/float/diff_octagons new file mode 100644 index 0000000000000000000000000000000000000000..806b63f0fdd00d77aa58baea79238e5893426733 --- /dev/null +++ b/tests/float/diff_octagons @@ -0,0 +1,18 @@ +Only in tests/float/oracle: absorb.res.oracle +Only in tests/float/oracle: absorb_sav.err +Only in tests/float/oracle: absorb_sav.res +Only in tests/float/oracle: absorb_sav2.err +Only in tests/float/oracle: absorb_sav2.res +Only in tests/float/oracle: fval_test.res.oracle +diff tests/float/oracle/nonlin.1.res.oracle tests/float/oracle_octagons/nonlin.1.res.oracle +253a254,255 +> [eva:nonlin] tests/float/nonlin.c:101: non-linear 'f + f', lv 'f' +> [eva:nonlin] tests/float/nonlin.c:101: subdividing on f +257d258 +< [eva:nonlin] tests/float/nonlin.c:101: subdividing on f +diff tests/float/oracle/nonlin.3.res.oracle tests/float/oracle_octagons/nonlin.3.res.oracle +253a254,255 +> [eva:nonlin] tests/float/nonlin.c:101: non-linear 'f + f', lv 'f' +> [eva:nonlin] tests/float/nonlin.c:101: subdividing on f +257d258 +< [eva:nonlin] tests/float/nonlin.c:101: subdividing on f diff --git a/tests/float/oracle/special_floats.res.oracle b/tests/float/oracle/special_floats.res.oracle index ff41f51100d9dd7a7e66312a64e0e542dba4b6b8..653af4625c63f0bc09500f9a1a31b85f3d6c2fba 100644 --- a/tests/float/oracle/special_floats.res.oracle +++ b/tests/float/oracle/special_floats.res.oracle @@ -1,16 +1,87 @@ -[kernel] Parsing tests/float/special_floats.i (no preprocessing) +[kernel] Parsing tests/float/special_floats.c (with preprocessing) [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed [eva:initial-state] Values of globals at initialization rand ∈ [--..--] + any_double ∈ [--..--] + global_infinity ∈ {inf} + global_nan ∈ NaN [eva] computing for function nan_comparisons <- main. - Called from tests/float/special_floats.i:24. + Called from tests/float/special_floats.c:94. [eva] Recording results for nan_comparisons [eva] Done for function nan_comparisons +[eva] computing for function is_infinite <- main. + Called from tests/float/special_floats.c:95. +[eva] tests/float/special_floats.c:29: check 'true' got status valid. +[eva:alarm] tests/float/special_floats.c:30: Warning: + check 'false' got status invalid. +[eva:alarm] tests/float/special_floats.c:31: Warning: + check 'false' got status invalid. +[eva:alarm] tests/float/special_floats.c:32: Warning: + check 'false' got status invalid. +[eva:alarm] tests/float/special_floats.c:34: Warning: + check 'false' got status invalid. +[eva] tests/float/special_floats.c:35: check 'true' got status valid. +[eva] tests/float/special_floats.c:36: check 'true' got status valid. +[eva:alarm] tests/float/special_floats.c:37: Warning: + check 'false' got status invalid. +[eva:alarm] tests/float/special_floats.c:39: Warning: + check 'false' got status invalid. +[eva] tests/float/special_floats.c:40: check 'true' got status valid. +[eva:alarm] tests/float/special_floats.c:41: Warning: + check 'false' got status invalid. +[eva:alarm] tests/float/special_floats.c:42: Warning: + check 'false' got status invalid. +[eva:alarm] tests/float/special_floats.c:46: Warning: + assertion got status unknown. +[eva] tests/float/special_floats.c:47: Frama_C_show_each_pos_infinity: {inf} +[eva:alarm] tests/float/special_floats.c:50: Warning: + assertion got status unknown. +[eva] tests/float/special_floats.c:51: Frama_C_show_each_neg_infinity: {-inf} +[eva:alarm] tests/float/special_floats.c:54: Warning: + assertion got status unknown. +[eva:alarm] tests/float/special_floats.c:55: Warning: + assertion got status unknown. +[eva] tests/float/special_floats.c:56: + Frama_C_show_each_finite_nan: + [-1.79769313486e+308 .. 1.79769313486e+308] ∪ {NaN} +[eva:alarm] tests/float/special_floats.c:59: Warning: + assertion got status unknown. +[eva] tests/float/special_floats.c:60: + Frama_C_show_each_top: [-inf .. inf] ∪ {NaN} +[eva:alarm] tests/float/special_floats.c:63: Warning: + assertion got status unknown. +[eva] tests/float/special_floats.c:64: Frama_C_show_each_pos_infinity: {inf;NaN} +[eva] Recording results for is_infinite +[eva] Done for function is_infinite +[eva] computing for function macro_infinity <- main. + Called from tests/float/special_floats.c:96. +[eva] tests/float/special_floats.c:74: Frama_C_show_each_infinity: {inf} +[eva] tests/float/special_floats.c:75: assertion got status valid. +[eva] Recording results for macro_infinity +[eva] Done for function macro_infinity +[eva] computing for function macro_nan <- main. + Called from tests/float/special_floats.c:97. +[eva] tests/float/special_floats.c:84: Frama_C_show_each_nan: NaN +[eva] tests/float/special_floats.c:85: assertion got status valid. +[eva] tests/float/special_floats.c:86: assertion got status valid. +[eva] tests/float/special_floats.c:87: assertion got status valid. +[eva] Recording results for macro_nan +[eva] Done for function macro_nan [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function is_infinite: + zero ∈ {-0.} + inf ∈ {inf} + nan_0 ∈ NaN + d ∈ [-inf .. inf] ∪ {NaN} +[eva:final-states] Values at end of function macro_infinity: + infinity_f ∈ {inf} + infinity_d ∈ {inf} +[eva:final-states] Values at end of function macro_nan: + nan_f ∈ NaN [eva:final-states] Values at end of function nan_comparisons: n ∈ NaN d ∈ [-10. .. 10.] diff --git a/tests/float/special_floats.c b/tests/float/special_floats.c new file mode 100644 index 0000000000000000000000000000000000000000..1e07cd3a6ba385e0b3eec0bda2eb0aa1381200d3 --- /dev/null +++ b/tests/float/special_floats.c @@ -0,0 +1,98 @@ +/* run.config* + OPT: -eva @EVA_CONFIG@ -warn-special-float none +*/ + +/* Tests on special float values NaN and infinites. */ + +volatile int rand; +volatile double any_double; + +/* All comparisons involving NaN are false, except for inequalities that are + true. */ +void nan_comparisons () { + double n = 0.0 / 0.0; + double d = rand ? -10. : 10.; + int eq1 = (n == n) ? 1 : 0; + int comp1 = (n < n) ? 1 : 0; + int ne1 = (n != n) ? 1 : 0; + int eq2 = (n == d) ? 1 : 0; + int comp2 = (n < d) ? 1 : 0; + int ne2 = (n != d) ? 1 : 0; +} + +#include <math.h> + +/* Tests the logical predicates \is_plus_infinite & co. */ +void is_infinite () { + /* Tests the evaluation on singletons. */ + double zero = -0.; + /*@ check true: \is_finite(zero); */ + /*@ check false: !\is_finite(zero); */ + /*@ check false: \is_plus_infinity(zero); */ + /*@ check false: \is_minus_infinity(zero); */ + double inf = INFINITY; + /*@ check false: \is_finite(inf); */ + /*@ check true: !\is_finite(inf); */ + /*@ check true: \is_plus_infinity(inf); */ + /*@ check false: \is_minus_infinity(inf); */ + double nan = NAN; + /*@ check false: \is_finite(nan); */ + /*@ check true: !\is_finite(nan); */ + /*@ check false: \is_plus_infinity(nan); */ + /*@ check false: \is_minus_infinity(nan); */ + double d = any_double; + /* Tests the reduction by assertions. */ + if (rand) { + /*@ assert \is_plus_infinity(d); */ + Frama_C_show_each_pos_infinity(d); + } + if (rand) { + /*@ assert \is_minus_infinity(d); */ + Frama_C_show_each_neg_infinity(d); + } + if (rand) { + /*@ assert !\is_plus_infinity(d); */ + /*@ assert !\is_minus_infinity(d); */ + Frama_C_show_each_finite_nan(d); + } + if (rand) { + /*@ assert !\is_finite(d); */ + Frama_C_show_each_top(d); + } + if (d > 0.) { + /*@ assert !\is_finite(d); */ + Frama_C_show_each_pos_infinity(d); + } +} + +float global_infinity = INFINITY; +float global_nan = NAN; + +/* Tests the C and logic macros INFINITY and HUGE_VAL. */ +void macro_infinity () { + float infinity_f = INFINITY; + Frama_C_show_each_infinity(infinity_f); + /*@ assert \eq_float(infinity_f,INFINITY); @*/ + double infinity_d = HUGE_VAL; + if(INFINITY != infinity_d) + /*@ assert \false; @*/; +} + +/* Tests the C and logic macros NAN. */ +void macro_nan () { + float nan_f = NAN; + Frama_C_show_each_nan(nan_f); + /*@ assert \is_NaN(nan_f); @*/ + /*@ assert \ne_float(nan_f,NAN); @*/ + /*@ assert \subset({nan_f},{NAN}); @*/ + if(NAN == nan_f) + /*@ assert \false; @*/; +} + + +void main () { + nan_comparisons (); + is_infinite (); + macro_infinity (); + macro_nan (); +} diff --git a/tests/float/special_floats.i b/tests/float/special_floats.i deleted file mode 100644 index 191afecec7da2c637a90355d92a23dbab8bb23d0..0000000000000000000000000000000000000000 --- a/tests/float/special_floats.i +++ /dev/null @@ -1,25 +0,0 @@ -/* run.config* - OPT: -eva @EVA_CONFIG@ -warn-special-float none -*/ - -/* Tests on special float values NaN and infinites. */ - -volatile int rand; - - -/* All comparisons involving NaN are false, except for inequalities that are - true. */ -void nan_comparisons () { - double n = 0.0 / 0.0; - double d = rand ? -10. : 10.; - int eq1 = (n == n) ? 1 : 0; - int comp1 = (n < n) ? 1 : 0; - int ne1 = (n != n) ? 1 : 0; - int eq2 = (n == d) ? 1 : 0; - int comp2 = (n < d) ? 1 : 0; - int ne2 = (n != d) ? 1 : 0; -} - -void main () { - nan_comparisons (); -} diff --git a/tests/idct/diff_octagons b/tests/idct/diff_octagons new file mode 100644 index 0000000000000000000000000000000000000000..46e477e3f73c2fc3d4aa05888afdfc1d43d7b003 --- /dev/null +++ b/tests/idct/diff_octagons @@ -0,0 +1,78 @@ +diff tests/idct/oracle/ieee_1180_1990.res.oracle tests/idct/oracle_octagons/ieee_1180_1990.res.oracle +424a425,432 +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +498a507,514 +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +571a588,595 +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +> [eva] tests/idct/ieee_1180_1990.c:85: +> Reusing old results for call to IEEE_1180_1990_rand +579a604,617 +> [eva] tests/idct/ieee_1180_1990.c:100: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:101: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:100: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:101: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:100: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:101: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:100: +> Call to builtin Frama_C_sqrt for function sqrt +581a620,621 +> [eva] tests/idct/ieee_1180_1990.c:100: +> Call to builtin Frama_C_sqrt for function sqrt +583a624,629 +> [eva] tests/idct/ieee_1180_1990.c:100: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:101: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:100: +> Call to builtin Frama_C_sqrt for function sqrt +605a652,661 +> [eva] tests/idct/ieee_1180_1990.c:140: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:141: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:140: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:141: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:140: +> Call to builtin Frama_C_sqrt for function sqrt +607a664,665 +> [eva] tests/idct/ieee_1180_1990.c:140: +> Call to builtin Frama_C_sqrt for function sqrt +609a668,677 +> [eva] tests/idct/ieee_1180_1990.c:140: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:141: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:140: +> Call to builtin Frama_C_sqrt for function sqrt +> [eva] tests/idct/ieee_1180_1990.c:141: +> Call to builtin Frama_C_cos for function cos +> [eva] tests/idct/ieee_1180_1990.c:140: +> Call to builtin Frama_C_sqrt for function sqrt diff --git a/tests/idct/oracle/ieee_1180_1990.res.oracle b/tests/idct/oracle/ieee_1180_1990.res.oracle index 0f3499f8f38e8e1815a6b7f9bb68d54d3019a961..1b12533c9f8de027acbe4871855f4d283b89627f 100644 --- a/tests/idct/oracle/ieee_1180_1990.res.oracle +++ b/tests/idct/oracle/ieee_1180_1990.res.oracle @@ -973,7 +973,7 @@ S___fc_stdout[0..1] ∈ [--..--] [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 6 functions analyzed (out of 44): 13% coverage. + 6 functions analyzed (out of 6): 100% coverage. In these functions, 588 statements reached (out of 626): 93% coverage. ---------------------------------------------------------------------------- Some errors and warnings have been raised during the analysis: @@ -1223,6 +1223,12 @@ [ Extern ] Axiom 'wcsncmp_zero' axiom wcsncmp_zero Unverifiable but considered Valid. +[ Extern ] Axiom 'wmemchr_def' + axiom wmemchr_def + Unverifiable but considered Valid. +[ Valid ] Axiomatic 'GetsLength' + axiomatic GetsLength + by Frama-C kernel. [ Valid ] Axiomatic 'MemChr' axiomatic MemChr by Frama-C kernel. @@ -1244,6 +1250,9 @@ [ Valid ] Axiomatic 'StrNCmp' axiomatic StrNCmp by Frama-C kernel. +[ Valid ] Axiomatic 'WMemChr' + axiomatic WMemChr + by Frama-C kernel. [ Valid ] Axiomatic 'WcsChr' axiomatic WcsChr by Frama-C kernel. @@ -1267,9 +1276,16 @@ --- Properties of Function 'remove' -------------------------------------------------------------------------------- +[ Extern ] Post-condition 'result_ok_or_error' + ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1 + Unverifiable but considered Valid. [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 76) + assigns \result + \from (indirect: *(filename + (0 .. strlen{Old}(filename)))); + Unverifiable but considered Valid. [ Valid ] Default behavior default behavior by Frama-C kernel. @@ -1278,9 +1294,17 @@ --- Properties of Function 'rename' -------------------------------------------------------------------------------- +[ Extern ] Post-condition 'result_ok_or_error' + ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1 + Unverifiable but considered Valid. [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 85) + assigns \result + \from (indirect: *(old_name + (0 .. strlen{Old}(old_name)))), + (indirect: *(new_name + (0 .. strlen{Old}(new_name)))); + Unverifiable but considered Valid. [ Valid ] Default behavior default behavior by Frama-C kernel. @@ -1298,7 +1322,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 80) +[ Extern ] Froms (file share/libc/stdio.h, line 95) assigns \result \from __fc_p_fopen; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1309,14 +1333,26 @@ --- Properties of Function 'tmpnam' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 87) - assigns \result, *(s + (..)); +[ Extern ] Post-condition 'result_string_or_null' + ensures + result_string_or_null: + \result ≡ \null ∨ \result ≡ \old(s) ∨ + \result ≡ __fc_p_tmpnam + Unverifiable but considered Valid. +[ Extern ] Assigns (file share/libc/stdio.h, line 109) + assigns *(__fc_p_tmpnam + (0 .. 2048)), *(s + (0 .. 2048)), + \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 87) - assigns \result \from *(s + (..)); +[ Extern ] Froms (file share/libc/stdio.h, line 109) + assigns *(__fc_p_tmpnam + (0 .. 2048)) + \from *(__fc_p_tmpnam + (0 .. 2048)), (indirect: s); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 88) - assigns *(s + (..)) \from \nothing; +[ Extern ] Froms (file share/libc/stdio.h, line 111) + assigns *(s + (0 .. 2048)) + \from (indirect: s), *(__fc_p_tmpnam + (0 .. 2048)); + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 112) + assigns \result \from s, __fc_p_tmpnam; Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1332,8 +1368,8 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 95) - assigns \result \from stream, stream->__fc_FILE_id; +[ Extern ] Froms (file share/libc/stdio.h, line 121) + assigns \result \from (indirect: stream), (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1346,15 +1382,48 @@ [ Extern ] Post-condition 'result_zero_or_EOF' ensures result_zero_or_EOF: \result ≡ 0 ∨ \result ≡ -1 Unverifiable but considered Valid. -[ Extern ] Assigns nothing - assigns \nothing; +[ Extern ] Assigns (file share/libc/stdio.h, line 130) + assigns \result, *stream, __fc_fopen[0 .. 16 - 1]; + Unverifiable but considered Valid. +[ Extern ] Assigns for 'flush_all' (file share/libc/stdio.h, line 137) + assigns __fc_fopen[0 .. 16 - 1], \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 103) - assigns \result \from stream, stream->__fc_FILE_id; +[ Extern ] Assigns for 'flush_stream' (file share/libc/stdio.h, line 142) + assigns *stream, \result; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 130) + assigns \result + \from (indirect: *stream), (indirect: __fc_fopen[0 .. 16 - 1]); + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 132) + assigns *stream + \from (indirect: stream), *stream, __fc_fopen[0 .. 16 - 1]; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 132) + assigns __fc_fopen[0 .. 16 - 1] + \from (indirect: stream), *stream, __fc_fopen[0 .. 16 - 1]; + Unverifiable but considered Valid. +[ Extern ] Froms for 'flush_all' (file share/libc/stdio.h, line 137) + assigns __fc_fopen[0 .. 16 - 1] \from __fc_fopen[0 .. 16 - 1]; + Unverifiable but considered Valid. +[ Extern ] Froms for 'flush_all' (file share/libc/stdio.h, line 139) + assigns \result \from (indirect: __fc_fopen[0 .. 16 - 1]); + Unverifiable but considered Valid. +[ Extern ] Froms for 'flush_stream' (file share/libc/stdio.h, line 142) + assigns *stream \from *stream; + Unverifiable but considered Valid. +[ Extern ] Froms for 'flush_stream' (file share/libc/stdio.h, line 143) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior by Frama-C kernel. +[ Valid ] Behavior 'flush_all' + behavior flush_all + by Frama-C kernel. +[ Valid ] Behavior 'flush_stream' + behavior flush_stream + by Frama-C kernel. -------------------------------------------------------------------------------- --- Properties of Function 'fopen' @@ -1369,10 +1438,11 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 112) +[ Extern ] Froms (file share/libc/stdio.h, line 152) assigns \result - \from (indirect: *(filename + (..))), - (indirect: *(mode + (..))), __fc_p_fopen; + \from (indirect: *(filename + (0 .. strlen{Old}(filename)))), + (indirect: *(mode + (0 .. strlen{Old}(mode)))), + __fc_p_fopen; Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1388,17 +1458,19 @@ \result ≡ \null ∨ \subset(\result, &__fc_fopen[0 .. 16 - 1]) Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 121) +[ Extern ] Assigns (file share/libc/stdio.h, line 162) assigns \result, __fc_fopen[fd]; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 121) +[ Extern ] Froms (file share/libc/stdio.h, line 162) assigns \result - \from (indirect: fd), (indirect: *(mode + (0 ..))), + \from (indirect: fd), + (indirect: *(mode + (0 .. strlen{Old}(mode)))), (indirect: __fc_fopen[fd]), __fc_p_fopen; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 121) +[ Extern ] Froms (file share/libc/stdio.h, line 162) assigns __fc_fopen[fd] - \from (indirect: fd), (indirect: *(mode + (0 ..))), + \from (indirect: fd), + (indirect: *(mode + (0 .. strlen{Old}(mode)))), (indirect: __fc_fopen[fd]), __fc_p_fopen; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1417,16 +1489,16 @@ [ Extern ] Post-condition 'stream_opened' ensures stream_opened: *\old(stream) ∈ __fc_fopen[0 .. 16 - 1] Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 132) +[ Extern ] Assigns (file share/libc/stdio.h, line 174) assigns \result, *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 132) +[ Extern ] Froms (file share/libc/stdio.h, line 174) assigns \result \from (indirect: *(filename + (..))), (indirect: *(mode + (..))), __fc_p_fopen, (indirect: stream); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 134) +[ Extern ] Froms (file share/libc/stdio.h, line 176) assigns *stream \from (indirect: *(filename + (..))), (indirect: *(mode + (..))), __fc_p_fopen, @@ -1440,10 +1512,10 @@ --- Properties of Function 'setbuf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 145) +[ Extern ] Assigns (file share/libc/stdio.h, line 187) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 145) +[ Extern ] Froms (file share/libc/stdio.h, line 187) assigns *stream \from buf; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1454,10 +1526,10 @@ --- Properties of Function 'setvbuf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 149) +[ Extern ] Assigns (file share/libc/stdio.h, line 191) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 149) +[ Extern ] Froms (file share/libc/stdio.h, line 191) assigns *stream \from buf, mode, size; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1468,10 +1540,10 @@ --- Properties of Function 'vfprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 178) +[ Extern ] Assigns (file share/libc/stdio.h, line 220) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 178) +[ Extern ] Froms (file share/libc/stdio.h, line 220) assigns *stream \from *(format + (..)), arg; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1482,10 +1554,10 @@ --- Properties of Function 'vfscanf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 183) +[ Extern ] Assigns (file share/libc/stdio.h, line 225) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 183) +[ Extern ] Froms (file share/libc/stdio.h, line 225) assigns *stream \from *(format + (..)), *stream; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1496,10 +1568,10 @@ --- Properties of Function 'vprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 189) +[ Extern ] Assigns (file share/libc/stdio.h, line 231) assigns *__fc_stdout; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 189) +[ Extern ] Froms (file share/libc/stdio.h, line 231) assigns *__fc_stdout \from arg; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1510,10 +1582,10 @@ --- Properties of Function 'vscanf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 193) +[ Extern ] Assigns (file share/libc/stdio.h, line 235) assigns *__fc_stdin; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 193) +[ Extern ] Froms (file share/libc/stdio.h, line 235) assigns *__fc_stdin \from *(format + (..)); Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1524,10 +1596,10 @@ --- Properties of Function 'vsnprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 198) +[ Extern ] Assigns (file share/libc/stdio.h, line 240) assigns *(s + (0 .. n - 1)); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 198) +[ Extern ] Froms (file share/libc/stdio.h, line 240) assigns *(s + (0 .. n - 1)) \from *(format + (..)), arg; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1538,10 +1610,10 @@ --- Properties of Function 'vsprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 204) +[ Extern ] Assigns (file share/libc/stdio.h, line 246) assigns *(s + (0 ..)); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 204) +[ Extern ] Froms (file share/libc/stdio.h, line 246) assigns *(s + (0 ..)) \from *(format + (..)), arg; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1556,13 +1628,13 @@ ensures result_uchar_or_eof: (0 ≤ \result ≤ 255) ∨ \result ≡ -1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 217) +[ Extern ] Assigns (file share/libc/stdio.h, line 259) assigns *stream, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 217) +[ Extern ] Froms (file share/libc/stdio.h, line 259) assigns *stream \from *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 218) +[ Extern ] Froms (file share/libc/stdio.h, line 260) assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1577,19 +1649,24 @@ ensures result_null_or_same: \result ≡ \null ∨ \result ≡ \old(s) Unverifiable but considered Valid. +[ Extern ] Post-condition 'initialization,at_least_one' + ensures + initialization: at_least_one: + \result ≢ \null ⇒ \initialized(\old(s) + 0) + Unverifiable but considered Valid. [ Extern ] Post-condition 'terminated_string_on_success' ensures terminated_string_on_success: \result ≢ \null ⇒ valid_string(\old(s)) Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 225) - assigns *(s + (0 .. size)), \result; +[ Extern ] Assigns (file share/libc/stdio.h, line 268) + assigns *(s + (0 .. size - 1)), \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 225) - assigns *(s + (0 .. size)) +[ Extern ] Froms (file share/libc/stdio.h, line 268) + assigns *(s + (0 .. size - 1)) \from (indirect: size), (indirect: *stream); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 226) +[ Extern ] Froms (file share/libc/stdio.h, line 269) assigns \result \from s, (indirect: size), (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1600,8 +1677,14 @@ --- Properties of Function 'fputc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 234) - assigns *stream; +[ Extern ] Assigns (file share/libc/stdio.h, line 282) + assigns *stream, \result; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 282) + assigns *stream \from c, *stream; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 283) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1611,11 +1694,16 @@ --- Properties of Function 'fputs' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 237) - assigns *stream; +[ Extern ] Assigns (file share/libc/stdio.h, line 289) + assigns *stream, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 237) - assigns *stream \from *(s + (..)); +[ Extern ] Froms (file share/libc/stdio.h, line 289) + assigns *stream \from *(s + (0 .. strlen{Old}(s))), *stream; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 290) + assigns \result + \from (indirect: *(s + (0 .. strlen{Old}(s)))), + (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1625,13 +1713,13 @@ --- Properties of Function 'getc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 241) +[ Extern ] Assigns (file share/libc/stdio.h, line 297) assigns \result, *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 241) +[ Extern ] Froms (file share/libc/stdio.h, line 297) assigns \result \from *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 241) +[ Extern ] Froms (file share/libc/stdio.h, line 297) assigns *stream \from *stream; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1642,12 +1730,15 @@ --- Properties of Function 'getchar' -------------------------------------------------------------------------------- -[ Extern ] Assigns nothing - assigns \nothing; +[ Extern ] Assigns (file share/libc/stdio.h, line 302) + assigns \result, *__fc_stdin; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 244) +[ Extern ] Froms (file share/libc/stdio.h, line 302) assigns \result \from *__fc_stdin; Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 302) + assigns *__fc_stdin \from *__fc_stdin; + Unverifiable but considered Valid. [ Valid ] Default behavior default behavior by Frama-C kernel. @@ -1660,14 +1751,17 @@ ensures result_null_or_same: \result ≡ \old(s) ∨ \result ≡ \null Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 248) - assigns *(s + (..)), \result; +[ Extern ] Assigns (file share/libc/stdio.h, line 315) + assigns *(s + (0 .. gets_length{Old})), \result, *__fc_stdin; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 248) - assigns *(s + (..)) \from *__fc_stdin; +[ Extern ] Froms (file share/libc/stdio.h, line 315) + assigns *(s + (0 .. gets_length{Old})) \from *__fc_stdin; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 249) - assigns \result \from s, __fc_stdin; +[ Extern ] Froms (file share/libc/stdio.h, line 316) + assigns \result \from s, *__fc_stdin; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 317) + assigns *__fc_stdin \from *__fc_stdin; Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1677,11 +1771,14 @@ --- Properties of Function 'putc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 254) - assigns *stream; +[ Extern ] Assigns (file share/libc/stdio.h, line 324) + assigns *stream, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 254) - assigns *stream \from c; +[ Extern ] Froms (file share/libc/stdio.h, line 324) + assigns *stream \from c, *stream; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 325) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1691,11 +1788,14 @@ --- Properties of Function 'putchar' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 257) - assigns *__fc_stdout; +[ Extern ] Assigns (file share/libc/stdio.h, line 330) + assigns *__fc_stdout, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 257) - assigns *__fc_stdout \from c; +[ Extern ] Froms (file share/libc/stdio.h, line 330) + assigns *__fc_stdout \from c, *__fc_stdout; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 331) + assigns \result \from (indirect: *__fc_stdout); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1705,11 +1805,17 @@ --- Properties of Function 'puts' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 260) - assigns *__fc_stdout; +[ Extern ] Assigns (file share/libc/stdio.h, line 337) + assigns *__fc_stdout, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 260) - assigns *__fc_stdout \from *(s + (..)); +[ Extern ] Froms (file share/libc/stdio.h, line 337) + assigns *__fc_stdout + \from *(s + (0 .. strlen{Old}(s))), *__fc_stdout; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 338) + assigns \result + \from (indirect: *(s + (0 .. strlen{Old}(s)))), + (indirect: *__fc_stdout); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1719,11 +1825,18 @@ --- Properties of Function 'ungetc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 263) - assigns *stream; +[ Extern ] Post-condition 'result_ok_or_error' + ensures + result_ok_or_error: \result ≡ \old(c) ∨ \result ≡ -1 Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 263) - assigns *stream \from c; +[ Extern ] Assigns (file share/libc/stdio.h, line 344) + assigns *stream, \result; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 344) + assigns *stream \from (indirect: c); + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 345) + assigns \result \from (indirect: c), (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1742,15 +1855,20 @@ \initialized((char *)\old(ptr) + (0 .. \result * \old(size) - 1)) Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 269) - assigns *((char *)ptr + (0 .. nmemb * size - 1)), \result; +[ Extern ] Assigns (file share/libc/stdio.h, line 353) + assigns *((char *)ptr + (0 .. nmemb * size - 1)), *stream, + \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 269) +[ Extern ] Froms (file share/libc/stdio.h, line 353) assigns *((char *)ptr + (0 .. nmemb * size - 1)) - \from size, nmemb, *stream; + \from (indirect: size), (indirect: nmemb), (indirect: *stream); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 270) - assigns \result \from size, *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 353) + assigns *stream + \from (indirect: size), (indirect: nmemb), (indirect: *stream); + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 355) + assigns \result \from size, (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1763,14 +1881,16 @@ [ Extern ] Post-condition 'size_written' ensures size_written: \result ≤ \old(nmemb) Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 282) +[ Extern ] Assigns (file share/libc/stdio.h, line 366) assigns *stream, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 282) - assigns *stream \from *((char *)ptr + (0 .. nmemb * size - 1)); +[ Extern ] Froms (file share/libc/stdio.h, line 366) + assigns *stream + \from (indirect: *((char *)ptr + (0 .. nmemb * size - 1))); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 282) - assigns \result \from *((char *)ptr + (0 .. nmemb * size - 1)); +[ Extern ] Froms (file share/libc/stdio.h, line 366) + assigns \result + \from (indirect: *((char *)ptr + (0 .. nmemb * size - 1))); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1780,11 +1900,14 @@ --- Properties of Function 'fgetpos' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 290) - assigns *pos; +[ Extern ] Assigns (file share/libc/stdio.h, line 377) + assigns *pos, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 290) - assigns *pos \from *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 377) + assigns *pos \from (indirect: *stream); + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 378) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1794,19 +1917,19 @@ --- Properties of Function 'fseek' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 297) +[ Extern ] Assigns (file share/libc/stdio.h, line 386) assigns *stream, \result, __fc_errno; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 297) +[ Extern ] Froms (file share/libc/stdio.h, line 386) assigns *stream \from *stream, (indirect: offset), (indirect: whence); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 298) +[ Extern ] Froms (file share/libc/stdio.h, line 387) assigns \result \from (indirect: *stream), (indirect: offset), (indirect: whence); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 298) +[ Extern ] Froms (file share/libc/stdio.h, line 387) assigns __fc_errno \from (indirect: *stream), (indirect: offset), (indirect: whence); @@ -1819,10 +1942,10 @@ --- Properties of Function 'fsetpos' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 303) +[ Extern ] Assigns (file share/libc/stdio.h, line 396) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 303) +[ Extern ] Froms (file share/libc/stdio.h, line 396) assigns *stream \from *pos; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1839,13 +1962,13 @@ \result ≡ -1 ∨ (\result ≥ 0 ∧ __fc_errno ≡ \old(__fc_errno)) Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 308) +[ Extern ] Assigns (file share/libc/stdio.h, line 402) assigns \result, __fc_errno; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 308) +[ Extern ] Froms (file share/libc/stdio.h, line 402) assigns \result \from (indirect: *stream); Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 308) +[ Extern ] Froms (file share/libc/stdio.h, line 402) assigns __fc_errno \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1856,10 +1979,10 @@ --- Properties of Function 'rewind' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 314) +[ Extern ] Assigns (file share/libc/stdio.h, line 410) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 314) +[ Extern ] Froms (file share/libc/stdio.h, line 410) assigns *stream \from \nothing; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1870,10 +1993,10 @@ --- Properties of Function 'clearerr' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 317) +[ Extern ] Assigns (file share/libc/stdio.h, line 416) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 317) +[ Extern ] Froms (file share/libc/stdio.h, line 416) assigns *stream \from \nothing; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1887,8 +2010,8 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 320) - assigns \result \from *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 422) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1901,8 +2024,8 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 323) - assigns \result \from *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 428) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1912,10 +2035,10 @@ --- Properties of Function 'flockfile' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 326) +[ Extern ] Assigns (file share/libc/stdio.h, line 434) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 326) +[ Extern ] Froms (file share/libc/stdio.h, line 434) assigns *stream \from \nothing; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1926,10 +2049,10 @@ --- Properties of Function 'funlockfile' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 329) +[ Extern ] Assigns (file share/libc/stdio.h, line 440) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 329) +[ Extern ] Froms (file share/libc/stdio.h, line 440) assigns *stream \from \nothing; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1940,13 +2063,13 @@ --- Properties of Function 'ftrylockfile' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 332) +[ Extern ] Assigns (file share/libc/stdio.h, line 446) assigns \result, *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 332) +[ Extern ] Froms (file share/libc/stdio.h, line 446) assigns \result \from \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 332) +[ Extern ] Froms (file share/libc/stdio.h, line 446) assigns *stream \from \nothing; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -1960,8 +2083,8 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 335) - assigns \result \from *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 452) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1971,11 +2094,12 @@ --- Properties of Function 'perror' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 338) +[ Extern ] Assigns (file share/libc/stdio.h, line 458) assigns __fc_stdout; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 338) - assigns __fc_stdout \from __fc_errno, *(s + (..)); +[ Extern ] Froms (file share/libc/stdio.h, line 458) + assigns __fc_stdout + \from __fc_errno, *(s + (0 .. strlen{Old}(s))); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -1985,13 +2109,13 @@ --- Properties of Function 'getc_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 341) +[ Extern ] Assigns (file share/libc/stdio.h, line 464) assigns \result, *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 341) +[ Extern ] Froms (file share/libc/stdio.h, line 464) assigns \result \from *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 341) +[ Extern ] Froms (file share/libc/stdio.h, line 464) assigns *stream \from *stream; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2005,7 +2129,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 343) +[ Extern ] Froms (file share/libc/stdio.h, line 469) assigns \result \from *__fc_stdin; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2016,12 +2140,15 @@ --- Properties of Function 'putc_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 345) - assigns *stream; +[ Extern ] Assigns (file share/libc/stdio.h, line 475) + assigns *stream, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 345) +[ Extern ] Froms (file share/libc/stdio.h, line 475) assigns *stream \from c; Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 476) + assigns \result \from (indirect: *stream); + Unverifiable but considered Valid. [ Valid ] Default behavior default behavior by Frama-C kernel. @@ -2030,12 +2157,15 @@ --- Properties of Function 'putchar_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 347) - assigns *__fc_stdout; +[ Extern ] Assigns (file share/libc/stdio.h, line 481) + assigns *__fc_stdout, \result; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 347) +[ Extern ] Froms (file share/libc/stdio.h, line 481) assigns *__fc_stdout \from c; Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 482) + assigns \result \from (indirect: *__fc_stdout); + Unverifiable but considered Valid. [ Valid ] Default behavior default behavior by Frama-C kernel. @@ -2044,10 +2174,10 @@ --- Properties of Function 'clearerr_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 350) +[ Extern ] Assigns (file share/libc/stdio.h, line 488) assigns *stream; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 350) +[ Extern ] Froms (file share/libc/stdio.h, line 488) assigns *stream \from \nothing; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2061,8 +2191,8 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 352) - assigns \result \from *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 494) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -2075,8 +2205,8 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 354) - assigns \result \from *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 500) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -2089,8 +2219,8 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 356) - assigns \result \from *stream; +[ Extern ] Froms (file share/libc/stdio.h, line 506) + assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior @@ -2107,14 +2237,14 @@ (\subset(\result, &__fc_fopen[0 .. 16 - 1]) ∧ is_open_pipe(\result)) Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 381) +[ Extern ] Assigns (file share/libc/stdio.h, line 533) assigns \result, __fc_fopen[0 ..]; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 381) +[ Extern ] Froms (file share/libc/stdio.h, line 533) assigns \result \from (indirect: *command), (indirect: *type), __fc_p_fopen; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 383) +[ Extern ] Froms (file share/libc/stdio.h, line 535) assigns __fc_fopen[0 ..] \from (indirect: *command), (indirect: *type), __fc_fopen[0 ..]; Unverifiable but considered Valid. @@ -2132,7 +2262,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 395) +[ Extern ] Froms (file share/libc/stdio.h, line 547) assigns \result \from (indirect: *stream); Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2161,7 +2291,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 71) +[ Extern ] Froms (file share/libc/math.h, line 67) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2205,7 +2335,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 95) +[ Extern ] Froms (file share/libc/math.h, line 91) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2237,28 +2367,28 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 132) +[ Extern ] Assigns (file share/libc/math.h, line 128) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 139) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 135) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 132) +[ Extern ] Froms (file share/libc/math.h, line 128) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 132) +[ Extern ] Froms (file share/libc/math.h, line 128) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 139) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 135) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 139) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 135) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 135) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 131) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2281,28 +2411,28 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 146) +[ Extern ] Assigns (file share/libc/math.h, line 142) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 153) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 149) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 146) +[ Extern ] Froms (file share/libc/math.h, line 142) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 146) +[ Extern ] Froms (file share/libc/math.h, line 142) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 153) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 149) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 153) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 149) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 149) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 145) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2325,28 +2455,28 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 160) +[ Extern ] Assigns (file share/libc/math.h, line 156) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 167) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 163) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 160) +[ Extern ] Froms (file share/libc/math.h, line 156) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 160) +[ Extern ] Froms (file share/libc/math.h, line 156) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 167) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 163) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 167) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 163) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 163) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 159) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2369,28 +2499,28 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 174) +[ Extern ] Assigns (file share/libc/math.h, line 170) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 181) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 177) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 174) +[ Extern ] Froms (file share/libc/math.h, line 170) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 174) +[ Extern ] Froms (file share/libc/math.h, line 170) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 181) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 177) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 181) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 177) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 177) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 173) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2413,28 +2543,28 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 188) +[ Extern ] Assigns (file share/libc/math.h, line 184) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 195) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 191) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 188) +[ Extern ] Froms (file share/libc/math.h, line 184) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 188) +[ Extern ] Froms (file share/libc/math.h, line 184) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 195) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 191) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 195) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 191) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 191) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 187) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2457,28 +2587,28 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 202) +[ Extern ] Assigns (file share/libc/math.h, line 198) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 209) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 205) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 202) +[ Extern ] Froms (file share/libc/math.h, line 198) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 202) +[ Extern ] Froms (file share/libc/math.h, line 198) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 209) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 205) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 209) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 205) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 205) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 201) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2504,7 +2634,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 216) +[ Extern ] Froms (file share/libc/math.h, line 212) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2524,7 +2654,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 223) +[ Extern ] Froms (file share/libc/math.h, line 219) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2544,7 +2674,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 230) +[ Extern ] Froms (file share/libc/math.h, line 226) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2561,7 +2691,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 238) +[ Extern ] Froms (file share/libc/math.h, line 234) assigns \result \from x, y; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2578,7 +2708,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 245) +[ Extern ] Froms (file share/libc/math.h, line 241) assigns \result \from x, y; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2601,7 +2731,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 253) +[ Extern ] Froms (file share/libc/math.h, line 249) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2621,7 +2751,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 260) +[ Extern ] Froms (file share/libc/math.h, line 256) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2641,7 +2771,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 267) +[ Extern ] Froms (file share/libc/math.h, line 263) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2661,7 +2791,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 274) +[ Extern ] Froms (file share/libc/math.h, line 270) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2681,7 +2811,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 281) +[ Extern ] Froms (file share/libc/math.h, line 277) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2701,7 +2831,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 288) +[ Extern ] Froms (file share/libc/math.h, line 284) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2721,10 +2851,10 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 299) +[ Extern ] Assigns (file share/libc/math.h, line 295) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 310) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 306) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'infinite' nothing @@ -2733,22 +2863,22 @@ [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 299) +[ Extern ] Froms (file share/libc/math.h, line 295) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 299) +[ Extern ] Froms (file share/libc/math.h, line 295) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 310) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 306) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 310) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 306) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'infinite' (file share/libc/math.h, line 306) +[ Extern ] Froms for 'infinite' (file share/libc/math.h, line 302) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 302) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 298) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2777,10 +2907,10 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 317) +[ Extern ] Assigns (file share/libc/math.h, line 313) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 328) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 324) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'infinite' nothing @@ -2789,22 +2919,22 @@ [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 317) +[ Extern ] Froms (file share/libc/math.h, line 313) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 317) +[ Extern ] Froms (file share/libc/math.h, line 313) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 328) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 324) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 328) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 324) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'infinite' (file share/libc/math.h, line 324) +[ Extern ] Froms for 'infinite' (file share/libc/math.h, line 320) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 320) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 316) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2833,10 +2963,10 @@ [ Extern ] Post-condition for 'domain_error' 'errno_set' ensures errno_set: __fc_errno ≡ 1 Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/math.h, line 335) +[ Extern ] Assigns (file share/libc/math.h, line 331) assigns __fc_errno, \result; Unverifiable but considered Valid. -[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 346) +[ Extern ] Assigns for 'domain_error' (file share/libc/math.h, line 342) assigns __fc_errno, \result; Unverifiable but considered Valid. [ Extern ] Assigns for 'infinite' nothing @@ -2845,22 +2975,22 @@ [ Extern ] Assigns for 'normal' nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 335) +[ Extern ] Froms (file share/libc/math.h, line 331) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 335) +[ Extern ] Froms (file share/libc/math.h, line 331) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 346) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 342) assigns __fc_errno \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 346) +[ Extern ] Froms for 'domain_error' (file share/libc/math.h, line 342) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'infinite' (file share/libc/math.h, line 342) +[ Extern ] Froms for 'infinite' (file share/libc/math.h, line 338) assigns \result \from x; Unverifiable but considered Valid. -[ Extern ] Froms for 'normal' (file share/libc/math.h, line 338) +[ Extern ] Froms for 'normal' (file share/libc/math.h, line 334) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2889,7 +3019,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 374) +[ Extern ] Froms (file share/libc/math.h, line 370) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2909,7 +3039,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 382) +[ Extern ] Froms (file share/libc/math.h, line 378) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2926,7 +3056,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 412) +[ Extern ] Froms (file share/libc/math.h, line 408) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2943,7 +3073,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 419) +[ Extern ] Froms (file share/libc/math.h, line 415) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2960,7 +3090,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 426) +[ Extern ] Froms (file share/libc/math.h, line 422) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2977,7 +3107,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 433) +[ Extern ] Froms (file share/libc/math.h, line 429) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -2994,7 +3124,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 440) +[ Extern ] Froms (file share/libc/math.h, line 436) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3011,7 +3141,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 447) +[ Extern ] Froms (file share/libc/math.h, line 443) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3028,7 +3158,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 458) +[ Extern ] Froms (file share/libc/math.h, line 454) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3045,7 +3175,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 465) +[ Extern ] Froms (file share/libc/math.h, line 461) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3062,7 +3192,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 472) +[ Extern ] Froms (file share/libc/math.h, line 468) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3087,7 +3217,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 498) +[ Extern ] Froms (file share/libc/math.h, line 494) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3112,7 +3242,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 506) +[ Extern ] Froms (file share/libc/math.h, line 502) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3137,7 +3267,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 514) +[ Extern ] Froms (file share/libc/math.h, line 510) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3154,7 +3284,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 527) +[ Extern ] Froms (file share/libc/math.h, line 523) assigns \result \from x, y; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3171,7 +3301,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 534) +[ Extern ] Froms (file share/libc/math.h, line 530) assigns \result \from x, y; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3197,7 +3327,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 543) +[ Extern ] Froms (file share/libc/math.h, line 539) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3217,7 +3347,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 551) +[ Extern ] Froms (file share/libc/math.h, line 547) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3237,7 +3367,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 559) +[ Extern ] Froms (file share/libc/math.h, line 555) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3254,7 +3384,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 582) +[ Extern ] Froms (file share/libc/math.h, line 578) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3271,7 +3401,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 588) +[ Extern ] Froms (file share/libc/math.h, line 584) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3288,7 +3418,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 595) +[ Extern ] Froms (file share/libc/math.h, line 591) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3305,7 +3435,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 601) +[ Extern ] Froms (file share/libc/math.h, line 597) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3322,7 +3452,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 607) +[ Extern ] Froms (file share/libc/math.h, line 603) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3339,7 +3469,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 613) +[ Extern ] Froms (file share/libc/math.h, line 609) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3356,7 +3486,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 635) +[ Extern ] Froms (file share/libc/math.h, line 631) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3373,7 +3503,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 641) +[ Extern ] Froms (file share/libc/math.h, line 637) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3390,7 +3520,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 647) +[ Extern ] Froms (file share/libc/math.h, line 643) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3407,7 +3537,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 661) +[ Extern ] Froms (file share/libc/math.h, line 657) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3424,7 +3554,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 667) +[ Extern ] Froms (file share/libc/math.h, line 663) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3441,7 +3571,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 673) +[ Extern ] Froms (file share/libc/math.h, line 669) assigns \result \from x; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3458,7 +3588,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 680) +[ Extern ] Froms (file share/libc/math.h, line 676) assigns \result \from x, y; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3475,7 +3605,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 687) +[ Extern ] Froms (file share/libc/math.h, line 683) assigns \result \from x, y; Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3492,7 +3622,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 708) +[ Extern ] Froms (file share/libc/math.h, line 704) assigns \result \from (indirect: *(tagp + (0 ..))); Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3509,7 +3639,7 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 715) +[ Extern ] Froms (file share/libc/math.h, line 711) assigns \result \from (indirect: *(tagp + (0 ..))); Unverifiable but considered Valid. [ Valid ] Default behavior @@ -3526,13 +3656,47 @@ [ Extern ] Assigns nothing assigns \nothing; Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/math.h, line 722) +[ Extern ] Froms (file share/libc/math.h, line 718) assigns \result \from (indirect: *(tagp + (0 ..))); Unverifiable but considered Valid. [ Valid ] Default behavior default behavior by Frama-C kernel. +-------------------------------------------------------------------------------- +--- Properties of Function '__fc_infinity' +-------------------------------------------------------------------------------- + +[ Extern ] Post-condition 'result_is_infinity' + ensures result_is_infinity: \is_plus_infinity(\result) + Unverifiable but considered Valid. +[ Extern ] Assigns nothing + assigns \nothing; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/math.h, line 766) + assigns \result \from \nothing; + Unverifiable but considered Valid. +[ Valid ] Default behavior + default behavior + by Frama-C kernel. + +-------------------------------------------------------------------------------- +--- Properties of Function '__fc_nan' +-------------------------------------------------------------------------------- + +[ Extern ] Post-condition 'result_is_nan' + ensures result_is_nan: \is_NaN(\result) + Unverifiable but considered Valid. +[ Extern ] Assigns nothing + assigns \nothing; + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/math.h, line 772) + assigns \result \from \nothing; + Unverifiable but considered Valid. +[ Valid ] Default behavior + default behavior + by Frama-C kernel. + -------------------------------------------------------------------------------- --- Properties of Function 'idct' -------------------------------------------------------------------------------- @@ -3888,9 +4052,9 @@ -------------------------------------------------------------------------------- --- Status Report Summary -------------------------------------------------------------------------------- - 173 Completely validated + 179 Completely validated 16 Locally validated - 448 Considered valid + 484 Considered valid 56 To be validated - 693 Total + 735 Total -------------------------------------------------------------------------------- diff --git a/tests/impact/depend5.i b/tests/impact/depend5.i index fcae6034c68e975b5cd0c0712356523269a25e33..52b560fbce0feb000e1bab6d409c7d022216c822 100644 --- a/tests/impact/depend5.i +++ b/tests/impact/depend5.i @@ -1,5 +1,5 @@ /* run.config - STDOPT: #"-calldeps -then -impact-pragma g" + STDOPT: #"@EVA_OPTIONS@ -calldeps -then -impact-pragma g" */ int a, b, c, d, e; diff --git a/tests/impact/oracle/depend5.res.oracle b/tests/impact/oracle/depend5.res.oracle index 415d327aa48e2ce9f2a753cf94e0667a2ea0b345..f75abc0f8070015f2b9e02de9243b93be8905853 100644 --- a/tests/impact/oracle/depend5.res.oracle +++ b/tests/impact/oracle/depend5.res.oracle @@ -8,26 +8,28 @@ c ∈ {0} d ∈ {0} e ∈ {0} +[eva] computing for function f <- main. + Called from tests/impact/depend5.i:23. +[eva] Recording results for f [from] Computing for function f [from] Done for function f +[eva] Done for function f +[eva] computing for function g <- main. + Called from tests/impact/depend5.i:25. +[eva] computing for function f <- g <- main. + Called from tests/impact/depend5.i:18. +[eva] Recording results for f [from] Computing for function f [from] Done for function f +[eva] Done for function f +[eva] Recording results for g [from] Computing for function g [from] Done for function g +[eva] Done for function g +[eva] Recording results for main [from] Computing for function main [from] Done for function main [eva] done for function main -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 3 functions analyzed (out of 3): 100% coverage. - In these functions, 13 statements reached (out of 13): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 0 alarms generated by the analysis. - ---------------------------------------------------------------------------- - No logical properties have been reached by the analysis. - ---------------------------------------------------------------------------- [from] ====== DISPLAYING CALLWISE DEPENDENCIES ====== [from] call to f at tests/impact/depend5.i:18 (by g): b FROM a; e diff --git a/tests/journal/oracle/control.0.res.oracle b/tests/journal/oracle/control.0.res.oracle index 2ee981ccf351c5624f462d99bd30b24696a4e799..efd77d2456cfca6a462c6f6af540db2334a34f5b 100644 --- a/tests/journal/oracle/control.0.res.oracle +++ b/tests/journal/oracle/control.0.res.oracle @@ -18,7 +18,7 @@ i ∈ {4} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 4): 25% coverage. + 1 function analyzed (out of 1): 100% coverage. In this function, 9 statements reached (out of 12): 75% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/journal/oracle/control.1.res.oracle b/tests/journal/oracle/control.1.res.oracle index 55c6fcda9b26c40ee167dcf8563665b5dd72ab26..663abd350fa5fdc998e8857a64b6cdc201d4e121 100644 --- a/tests/journal/oracle/control.1.res.oracle +++ b/tests/journal/oracle/control.1.res.oracle @@ -18,7 +18,7 @@ i ∈ {4} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 4): 25% coverage. + 1 function analyzed (out of 1): 100% coverage. In this function, 9 statements reached (out of 12): 75% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. @@ -56,7 +56,7 @@ i ∈ {4} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 4): 25% coverage. + 1 function analyzed (out of 1): 100% coverage. In this function, 9 statements reached (out of 12): 75% coverage. ---------------------------------------------------------------------------- Some errors and warnings have been raised during the analysis: diff --git a/tests/journal/oracle/control2.res.oracle b/tests/journal/oracle/control2.res.oracle index f73d56171f0db23c4055406812a7c19107de9100..04f5cc28cae629f77dab9116a4785e1910491f0e 100644 --- a/tests/journal/oracle/control2.res.oracle +++ b/tests/journal/oracle/control2.res.oracle @@ -17,7 +17,7 @@ i ∈ {4} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 4): 25% coverage. + 1 function analyzed (out of 1): 100% coverage. In this function, 9 statements reached (out of 12): 75% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/journal/oracle/control2_sav.res b/tests/journal/oracle/control2_sav.res index cfefb7770292c8cb107c3032b830803c8191e095..234e16239cc482d48773b401746dffd334303ca7 100644 --- a/tests/journal/oracle/control2_sav.res +++ b/tests/journal/oracle/control2_sav.res @@ -17,7 +17,7 @@ i ∈ {4} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 4): 25% coverage. + 1 function analyzed (out of 1): 100% coverage. In this function, 9 statements reached (out of 12): 75% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/journal/oracle/intra.res.oracle b/tests/journal/oracle/intra.res.oracle index 5e39a5c278bb9da6f9f575e1bfa755291fb626d9..9032dd6f7aef8be7a8e414890d3e99b037adf17d 100644 --- a/tests/journal/oracle/intra.res.oracle +++ b/tests/journal/oracle/intra.res.oracle @@ -58,7 +58,7 @@ [eva] done for function main [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 8 functions analyzed (out of 9): 88% coverage. + 8 functions analyzed (out of 10): 80% coverage. In these functions, 58 statements reached (out of 59): 98% coverage. ---------------------------------------------------------------------------- Some errors and warnings have been raised during the analysis: diff --git a/tests/libc/oracle/fc_libc.0.res.oracle b/tests/libc/oracle/fc_libc.0.res.oracle index d64ea807afda96b59b16bcca76633b124b9864dc..8554a5a2d796a49cecbaea8e86f5ded905a0e92f 100644 --- a/tests/libc/oracle/fc_libc.0.res.oracle +++ b/tests/libc/oracle/fc_libc.0.res.oracle @@ -40,7 +40,7 @@ unsetenv (0 call); wcscat (0 call); wcscpy (0 call); wcslen (2 calls); wcsncat (0 call); wcsncpy (0 call); wmemcpy (0 call); wmemset (0 call); - Undefined functions (382) + Undefined functions (384) ========================= FD_CLR (0 call); FD_ISSET (0 call); FD_SET (0 call); FD_ZERO (0 call); Frama_C_int_interval (0 call); Frama_C_long_interval (0 call); @@ -61,64 +61,64 @@ __builtin_umull_overflow (0 call); __builtin_umulll_overflow (0 call); __builtin_usub_overflow (0 call); __builtin_usubl_overflow (0 call); __builtin_usubll_overflow (0 call); __fc_fpclassify (0 call); - __fc_fpclassifyf (0 call); __va_fcntl_flock (0 call); - __va_fcntl_int (0 call); __va_fcntl_void (0 call); __va_ioctl_int (0 call); - __va_ioctl_ptr (0 call); __va_ioctl_void (0 call); - __va_open_mode_t (0 call); __va_open_void (0 call); - __va_openat_mode_t (0 call); __va_openat_void (0 call); _exit (0 call); - abort (0 call); accept (0 call); access (0 call); acos (0 call); - acosf (0 call); acosh (0 call); acoshf (0 call); acoshl (0 call); - acosl (0 call); alloca (0 call); asin (0 call); asinf (0 call); - asinl (0 call); at_quick_exit (0 call); atan (0 call); atan2 (0 call); - atan2f (0 call); atanf (0 call); atanl (0 call); atexit (0 call); - atof (0 call); atol (0 call); atoll (0 call); basename (0 call); - bind (0 call); bsearch (0 call); bzero (0 call); ceil (0 call); - ceilf (0 call); ceill (0 call); chdir (0 call); chown (0 call); - chroot (0 call); clearerr (0 call); clearerr_unlocked (0 call); - clock (0 call); clock_gettime (0 call); clock_nanosleep (0 call); - close (0 call); closedir (0 call); closelog (0 call); connect (0 call); - cos (0 call); cosf (0 call); cosl (0 call); creat (0 call); ctime (0 call); - difftime (0 call); dirname (0 call); div (0 call); drand48 (0 call); - dup (0 call); dup2 (0 call); erand48 (0 call); execl (0 call); - execle (0 call); execlp (0 call); execv (0 call); execve (0 call); - execvp (0 call); exit (0 call); exp (0 call); expf (0 call); fabsl (0 call); - fclose (0 call); fcntl (0 call); fdopen (0 call); feof (2 calls); - feof_unlocked (0 call); ferror (2 calls); ferror_unlocked (0 call); - fflush (0 call); fgetc (1 call); fgetpos (0 call); fgets (0 call); - fgetws (0 call); fileno (0 call); fileno_unlocked (0 call); flock (0 call); - flockfile (0 call); floor (0 call); floorf (0 call); floorl (0 call); - fmod (0 call); fmodf (0 call); fopen (0 call); fork (0 call); - fputc (0 call); fputs (0 call); fread (0 call); free (1 call); - freeaddrinfo (0 call); freopen (0 call); fseek (0 call); fsetpos (0 call); - ftell (0 call); ftrylockfile (0 call); funlockfile (0 call); - fwrite (0 call); gai_strerror (0 call); getc (0 call); - getc_unlocked (0 call); getchar (0 call); getchar_unlocked (0 call); - getcwd (0 call); getegid (0 call); geteuid (0 call); getgid (0 call); - gethostname (0 call); getitimer (0 call); getopt (0 call); - getopt_long (0 call); getopt_long_only (0 call); getpgid (0 call); - getpgrp (0 call); getpid (0 call); getppid (0 call); getpriority (0 call); - getpwnam (0 call); getpwuid (0 call); getresgid (0 call); - getresuid (0 call); getrlimit (0 call); getrusage (0 call); gets (0 call); - getsid (0 call); getsockopt (0 call); gettimeofday (0 call); - getuid (0 call); gmtime (0 call); htonl (0 call); htons (0 call); - iconv (0 call); iconv_close (0 call); iconv_open (0 call); - inet_addr (2 calls); inet_ntoa (0 call); inet_ntop (0 call); - inet_pton (0 call); isascii (0 call); isatty (0 call); jrand48 (0 call); - kill (0 call); killpg (0 call); labs (0 call); lcong48 (0 call); - ldiv (0 call); listen (0 call); llabs (0 call); lldiv (0 call); - localtime (0 call); log (0 call); log10 (0 call); log10f (0 call); - log10l (0 call); log2 (0 call); log2f (0 call); log2l (0 call); - logf (0 call); logl (0 call); longjmp (0 call); lrand48 (0 call); - lseek (0 call); malloc (7 calls); mblen (0 call); mbstowcs (0 call); - mbtowc (0 call); mkdir (0 call); mkstemp (0 call); mktime (0 call); - mrand48 (0 call); nan (0 call); nanf (0 call); nanl (0 call); - nanosleep (0 call); nrand48 (0 call); ntohl (0 call); ntohs (0 call); - open (0 call); openat (0 call); opendir (0 call); openlog (0 call); - pathconf (0 call); pclose (0 call); perror (0 call); pipe (0 call); - poll (0 call); popen (0 call); pow (0 call); powf (0 call); - pthread_cond_broadcast (0 call); pthread_cond_destroy (0 call); - pthread_cond_init (0 call); pthread_cond_wait (0 call); - pthread_create (0 call); pthread_join (0 call); + __fc_fpclassifyf (0 call); __fc_infinity (0 call); __fc_nan (0 call); + __va_fcntl_flock (0 call); __va_fcntl_int (0 call); + __va_fcntl_void (0 call); __va_ioctl_int (0 call); __va_ioctl_ptr (0 call); + __va_ioctl_void (0 call); __va_open_mode_t (0 call); + __va_open_void (0 call); __va_openat_mode_t (0 call); + __va_openat_void (0 call); _exit (0 call); abort (0 call); accept (0 call); + access (0 call); acos (0 call); acosf (0 call); acosh (0 call); + acoshf (0 call); acoshl (0 call); acosl (0 call); alloca (0 call); + asin (0 call); asinf (0 call); asinl (0 call); at_quick_exit (0 call); + atan (0 call); atan2 (0 call); atan2f (0 call); atanf (0 call); + atanl (0 call); atexit (0 call); atof (0 call); atol (0 call); + atoll (0 call); basename (0 call); bind (0 call); bsearch (0 call); + bzero (0 call); ceil (0 call); ceilf (0 call); ceill (0 call); + chdir (0 call); chown (0 call); chroot (0 call); clearerr (0 call); + clearerr_unlocked (0 call); clock (0 call); clock_gettime (0 call); + clock_nanosleep (0 call); close (0 call); closedir (0 call); + closelog (0 call); connect (0 call); cos (0 call); cosf (0 call); + cosl (0 call); creat (0 call); ctime (0 call); difftime (0 call); + dirname (0 call); div (0 call); drand48 (0 call); dup (0 call); + dup2 (0 call); erand48 (0 call); execl (0 call); execle (0 call); + execlp (0 call); execv (0 call); execve (0 call); execvp (0 call); + exit (0 call); exp (0 call); expf (0 call); fabsl (0 call); fclose (0 call); + fcntl (0 call); fdopen (0 call); feof (2 calls); feof_unlocked (0 call); + ferror (2 calls); ferror_unlocked (0 call); fflush (0 call); fgetc (1 call); + fgetpos (0 call); fgets (0 call); fgetws (0 call); fileno (0 call); + fileno_unlocked (0 call); flock (0 call); flockfile (0 call); + floor (0 call); floorf (0 call); floorl (0 call); fmod (0 call); + fmodf (0 call); fopen (0 call); fork (0 call); fputc (0 call); + fputs (0 call); fread (0 call); free (1 call); freeaddrinfo (0 call); + freopen (0 call); fseek (0 call); fsetpos (0 call); ftell (0 call); + ftrylockfile (0 call); funlockfile (0 call); fwrite (0 call); + gai_strerror (0 call); getc (0 call); getc_unlocked (0 call); + getchar (0 call); getchar_unlocked (0 call); getcwd (0 call); + getegid (0 call); geteuid (0 call); getgid (0 call); gethostname (0 call); + getitimer (0 call); getopt (0 call); getopt_long (0 call); + getopt_long_only (0 call); getpgid (0 call); getpgrp (0 call); + getpid (0 call); getppid (0 call); getpriority (0 call); getpwnam (0 call); + getpwuid (0 call); getresgid (0 call); getresuid (0 call); + getrlimit (0 call); getrusage (0 call); gets (0 call); getsid (0 call); + getsockopt (0 call); gettimeofday (0 call); getuid (0 call); + gmtime (0 call); htonl (0 call); htons (0 call); iconv (0 call); + iconv_close (0 call); iconv_open (0 call); inet_addr (2 calls); + inet_ntoa (0 call); inet_ntop (0 call); inet_pton (0 call); + isascii (0 call); isatty (0 call); jrand48 (0 call); kill (0 call); + killpg (0 call); labs (0 call); lcong48 (0 call); ldiv (0 call); + listen (0 call); llabs (0 call); lldiv (0 call); localtime (0 call); + log (0 call); log10 (0 call); log10f (0 call); log10l (0 call); + log2 (0 call); log2f (0 call); log2l (0 call); logf (0 call); logl (0 call); + longjmp (0 call); lrand48 (0 call); lseek (0 call); malloc (7 calls); + mblen (0 call); mbstowcs (0 call); mbtowc (0 call); mkdir (0 call); + mkstemp (0 call); mktime (0 call); mrand48 (0 call); nan (0 call); + nanf (0 call); nanl (0 call); nanosleep (0 call); nrand48 (0 call); + ntohl (0 call); ntohs (0 call); open (0 call); openat (0 call); + opendir (0 call); openlog (0 call); pathconf (0 call); pclose (0 call); + perror (0 call); pipe (0 call); poll (0 call); popen (0 call); pow (0 call); + powf (0 call); pthread_cond_broadcast (0 call); + pthread_cond_destroy (0 call); pthread_cond_init (0 call); + pthread_cond_wait (0 call); pthread_create (0 call); pthread_join (0 call); pthread_mutex_destroy (0 call); pthread_mutex_init (0 call); pthread_mutex_lock (0 call); pthread_mutex_unlock (0 call); putc (0 call); putc_unlocked (0 call); putchar (0 call); putchar_unlocked (0 call); @@ -172,13 +172,13 @@ ============== Sloc = 1083 Decision point = 204 - Global variables = 68 + Global variables = 70 If = 195 Loop = 43 Goto = 89 Assignment = 438 Exit point = 82 - Function = 464 + Function = 466 Function call = 89 Pointer dereferencing = 158 Cyclomatic complexity = 286 diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle index f1bb1d42421189f8e087c94215e6f4d70d1cf335..ed172048f4c391e586f81f1d78820d16d0d48d97 100644 --- a/tests/libc/oracle/fc_libc.1.res.oracle +++ b/tests/libc/oracle/fc_libc.1.res.oracle @@ -1308,6 +1308,23 @@ axiomatic StrChr { } */ /*@ +axiomatic WMemChr { + logic 𔹠wmemchr{L}(wchar_t *s, wchar_t c, ℤ n) + reads *(s + (0 .. n - 1)); + + logic ℤ wmemchr_off{L}(wchar_t *s, wchar_t c, ℤ n) + reads *(s + (0 .. n - 1)); + + axiom wmemchr_def{L}: + ∀ wchar_t *s; + ∀ int c; + ∀ ℤ n; + wmemchr(s, c, n) ≡ \true ⇔ + (∃ int i; 0 ≤ i < n ∧ *(s + i) ≡ c); + + } + */ +/*@ axiomatic WcsLen { logic ℤ wcslen{L}(wchar_t *s) reads *(s + (0 ..)); @@ -1643,7 +1660,8 @@ extern off_t lseek(int fd, off_t offset, int whence); */ extern long pathconf(char const *path, int name); -/*@ ensures initialization: pipefd: \initialized(\old(pipefd) + (0 .. 1)); +/*@ requires valid_pipefd: \valid(pipefd + (0 .. 1)); + ensures initialization: pipefd: \initialized(\old(pipefd) + (0 .. 1)); ensures valid_fd0: 0 ≤ *(\old(pipefd) + 0) < 1024; ensures valid_fd1: 0 ≤ *(\old(pipefd) + 1) < 1024; ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1; @@ -1727,7 +1745,8 @@ extern long sysconf(int name); extern char volatile __fc_ttyname[32]; char volatile *__fc_p_ttyname = __fc_ttyname; -/*@ ensures +/*@ requires valid_fildes: 0 ≤ fildes < 1024; + ensures result_name_or_null: \result ≡ __fc_p_ttyname ∨ \result ≡ \null; assigns \result; assigns \result \from __fc_p_ttyname, (indirect: fildes); @@ -3385,6 +3404,23 @@ int __finitef(float f); int __finite(double d); +/*@ logic float __fc_infinity(ℤ x) = \plus_infinity; + */ +/*@ logic float __fc_nan(ℤ x) = \NaN; + +*/ +/*@ ensures result_is_infinity: \is_plus_infinity(\result); + assigns \result; + assigns \result \from \nothing; + */ +extern float __fc_infinity(int x); + +/*@ ensures result_is_nan: \is_NaN(\result); + assigns \result; + assigns \result \from \nothing; + */ +extern float __fc_nan(int x); + /*@ requires finite_arg: \is_finite(x); ensures res_finite: \is_finite(\result); ensures positive_result: \result ≥ 0.; @@ -4431,10 +4467,22 @@ FILE *__fc_stdin; FILE *__fc_stdout; -/*@ assigns \nothing; */ +/*@ requires valid_filename: valid_read_string(filename); + ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1; + assigns \result; + assigns \result + \from (indirect: *(filename + (0 .. strlen{Old}(filename)))); + */ extern int remove(char const *filename); -/*@ assigns \nothing; */ +/*@ requires valid_old_name: valid_read_string(old_name); + requires valid_new_name: valid_read_string(new_name); + ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1; + assigns \result; + assigns \result + \from (indirect: *(old_name + (0 .. strlen{Old}(old_name)))), + (indirect: *(new_name + (0 .. strlen{Old}(new_name)))); + */ extern int rename(char const *old_name, char const *new_name); FILE __fc_fopen[16]; @@ -4447,23 +4495,53 @@ FILE * const __fc_p_fopen = __fc_fopen; */ extern FILE *tmpfile(void); -/*@ assigns \result, *(s + (..)); - assigns \result \from *(s + (..)); - assigns *(s + (..)) \from \nothing; +char __fc_tmpnam[2048]; +char * const __fc_p_tmpnam = __fc_tmpnam; +/*@ requires valid_s_or_null: s ≡ \null ∨ \valid(s + (0 .. 2048)); + ensures + result_string_or_null: + \result ≡ \null ∨ \result ≡ \old(s) ∨ + \result ≡ __fc_p_tmpnam; + assigns *(__fc_p_tmpnam + (0 .. 2048)), *(s + (0 .. 2048)), \result; + assigns *(__fc_p_tmpnam + (0 .. 2048)) + \from *(__fc_p_tmpnam + (0 .. 2048)), (indirect: s); + assigns *(s + (0 .. 2048)) + \from (indirect: s), *(__fc_p_tmpnam + (0 .. 2048)); + assigns \result \from s, __fc_p_tmpnam; */ extern char *tmpnam(char *s); /*@ requires valid_stream: \valid(stream); ensures result_zero_or_EOF: \result ≡ 0 ∨ \result ≡ -1; assigns \result; - assigns \result \from stream, stream->__fc_FILE_id; + assigns \result \from (indirect: stream), (indirect: *stream); */ extern int fclose(FILE *stream); /*@ requires null_or_valid_stream: stream ≡ \null ∨ \valid_read(stream); ensures result_zero_or_EOF: \result ≡ 0 ∨ \result ≡ -1; - assigns \result; - assigns \result \from stream, stream->__fc_FILE_id; + assigns \result, *stream, __fc_fopen[0 .. 16 - 1]; + assigns \result + \from (indirect: *stream), (indirect: __fc_fopen[0 .. 16 - 1]); + assigns *stream + \from (indirect: stream), *stream, __fc_fopen[0 .. 16 - 1]; + assigns __fc_fopen[0 .. 16 - 1] + \from (indirect: stream), *stream, __fc_fopen[0 .. 16 - 1]; + + behavior flush_all: + assumes all_streams: stream ≡ \null; + assigns __fc_fopen[0 .. 16 - 1], \result; + assigns __fc_fopen[0 .. 16 - 1] \from __fc_fopen[0 .. 16 - 1]; + assigns \result \from (indirect: __fc_fopen[0 .. 16 - 1]); + + behavior flush_stream: + assumes single_stream: stream ≢ \null; + assigns *stream, \result; + assigns *stream \from *stream; + assigns \result \from (indirect: *stream); + + complete behaviors flush_stream, flush_all; + disjoint behaviors flush_stream, flush_all; */ extern int fflush(FILE *stream); @@ -4474,8 +4552,8 @@ extern int fflush(FILE *stream); \result ≡ \null ∨ \subset(\result, &__fc_fopen[0 .. 16 - 1]); assigns \result; assigns \result - \from (indirect: *(filename + (..))), (indirect: *(mode + (..))), - __fc_p_fopen; + \from (indirect: *(filename + (0 .. strlen{Old}(filename)))), + (indirect: *(mode + (0 .. strlen{Old}(mode)))), __fc_p_fopen; */ extern FILE *fopen(char const * __restrict filename, char const * __restrict mode); @@ -4486,10 +4564,10 @@ extern FILE *fopen(char const * __restrict filename, \result ≡ \null ∨ \subset(\result, &__fc_fopen[0 .. 16 - 1]); assigns \result, __fc_fopen[fd]; assigns \result - \from (indirect: fd), (indirect: *(mode + (0 ..))), + \from (indirect: fd), (indirect: *(mode + (0 .. strlen{Old}(mode)))), (indirect: __fc_fopen[fd]), __fc_p_fopen; assigns __fc_fopen[fd] - \from (indirect: fd), (indirect: *(mode + (0 ..))), + \from (indirect: fd), (indirect: *(mode + (0 .. strlen{Old}(mode)))), (indirect: __fc_fopen[fd]), __fc_p_fopen; */ extern FILE *fdopen(int fd, char const *mode); @@ -4566,54 +4644,93 @@ extern int vsprintf(char * __restrict s, char const * __restrict format, extern int fgetc(FILE *stream); /*@ requires valid_stream: \valid(stream); + requires room_s: \valid(s + (0 .. size - 1)); ensures result_null_or_same: \result ≡ \null ∨ \result ≡ \old(s); + ensures + initialization: at_least_one: + \result ≢ \null ⇒ \initialized(\old(s) + 0); ensures terminated_string_on_success: \result ≢ \null ⇒ valid_string(\old(s)); - assigns *(s + (0 .. size)), \result; - assigns *(s + (0 .. size)) \from (indirect: size), (indirect: *stream); + assigns *(s + (0 .. size - 1)), \result; + assigns *(s + (0 .. size - 1)) + \from (indirect: size), (indirect: *stream); assigns \result \from s, (indirect: size), (indirect: *stream); */ extern char *fgets(char * __restrict s, int size, FILE * __restrict stream); -/*@ assigns *stream; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream, \result; + assigns *stream \from c, *stream; + assigns \result \from (indirect: *stream); + */ extern int fputc(int c, FILE *stream); -/*@ assigns *stream; - assigns *stream \from *(s + (..)); */ +/*@ requires valid_string_s: valid_read_string(s); + assigns *stream, \result; + assigns *stream \from *(s + (0 .. strlen{Old}(s))), *stream; + assigns \result + \from (indirect: *(s + (0 .. strlen{Old}(s)))), (indirect: *stream); + */ extern int fputs(char const * __restrict s, FILE * __restrict stream); -/*@ assigns \result, *stream; +/*@ requires valid_stream: \valid(stream); + assigns \result, *stream; assigns \result \from *stream; assigns *stream \from *stream; */ extern int getc(FILE *stream); -/*@ assigns \result; - assigns \result \from *__fc_stdin; */ +/*@ assigns \result, *__fc_stdin; + assigns \result \from *__fc_stdin; + assigns *__fc_stdin \from *__fc_stdin; + */ extern int getchar(void); -/*@ ensures result_null_or_same: \result ≡ \old(s) ∨ \result ≡ \null; - assigns *(s + (..)), \result; - assigns *(s + (..)) \from *__fc_stdin; - assigns \result \from s, __fc_stdin; +/*@ axiomatic GetsLength { + logic size_t gets_length{L} + reads *__fc_stdin; + + } + +*/ +/*@ requires room_s: \valid(s + (0 .. gets_length)); + ensures result_null_or_same: \result ≡ \old(s) ∨ \result ≡ \null; + assigns *(s + (0 .. gets_length{Old})), \result, *__fc_stdin; + assigns *(s + (0 .. gets_length{Old})) \from *__fc_stdin; + assigns \result \from s, *__fc_stdin; + assigns *__fc_stdin \from *__fc_stdin; */ extern char *gets(char *s); -/*@ assigns *stream; - assigns *stream \from c; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream, \result; + assigns *stream \from c, *stream; + assigns \result \from (indirect: *stream); + */ extern int putc(int c, FILE *stream); -/*@ assigns *__fc_stdout; - assigns *__fc_stdout \from c; */ +/*@ assigns *__fc_stdout, \result; + assigns *__fc_stdout \from c, *__fc_stdout; + assigns \result \from (indirect: *__fc_stdout); + */ extern int putchar(int c); -/*@ assigns *__fc_stdout; - assigns *__fc_stdout \from *(s + (..)); */ +/*@ requires valid_string_s: valid_read_string(s); + assigns *__fc_stdout, \result; + assigns *__fc_stdout \from *(s + (0 .. strlen{Old}(s))), *__fc_stdout; + assigns \result + \from (indirect: *(s + (0 .. strlen{Old}(s)))), + (indirect: *__fc_stdout); + */ extern int puts(char const *s); -/*@ assigns *stream; - assigns *stream \from c; */ +/*@ requires valid_stream: \valid(stream); + ensures result_ok_or_error: \result ≡ \old(c) ∨ \result ≡ -1; + assigns *stream, \result; + assigns *stream \from (indirect: c); + assigns \result \from (indirect: c), (indirect: *stream); + */ extern int ungetc(int c, FILE *stream); /*@ requires valid_ptr_block: \valid((char *)ptr + (0 .. nmemb * size - 1)); @@ -4622,10 +4739,12 @@ extern int ungetc(int c, FILE *stream); ensures initialization: \initialized((char *)\old(ptr) + (0 .. \result * \old(size) - 1)); - assigns *((char *)ptr + (0 .. nmemb * size - 1)), \result; + assigns *((char *)ptr + (0 .. nmemb * size - 1)), *stream, \result; assigns *((char *)ptr + (0 .. nmemb * size - 1)) - \from size, nmemb, *stream; - assigns \result \from size, *stream; + \from (indirect: size), (indirect: nmemb), (indirect: *stream); + assigns *stream + \from (indirect: size), (indirect: nmemb), (indirect: *stream); + assigns \result \from size, (indirect: *stream); */ extern size_t fread(void * __restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream); @@ -4635,14 +4754,21 @@ extern size_t fread(void * __restrict ptr, size_t size, size_t nmemb, requires valid_stream: \valid(stream); ensures size_written: \result ≤ \old(nmemb); assigns *stream, \result; - assigns *stream \from *((char *)ptr + (0 .. nmemb * size - 1)); - assigns \result \from *((char *)ptr + (0 .. nmemb * size - 1)); + assigns *stream + \from (indirect: *((char *)ptr + (0 .. nmemb * size - 1))); + assigns \result + \from (indirect: *((char *)ptr + (0 .. nmemb * size - 1))); */ extern size_t fwrite(void const * __restrict ptr, size_t size, size_t nmemb, FILE * __restrict stream); -/*@ assigns *pos; - assigns *pos \from *stream; */ +/*@ requires valid_stream: \valid(stream); + requires valid_pos: \valid(pos); + requires initialization: pos: \initialized(pos); + assigns *pos, \result; + assigns *pos \from (indirect: *stream); + assigns \result \from (indirect: *stream); + */ extern int fgetpos(FILE * __restrict stream, fpos_t * __restrict pos); /*@ requires valid_stream: \valid(stream); @@ -4656,8 +4782,12 @@ extern int fgetpos(FILE * __restrict stream, fpos_t * __restrict pos); */ extern int fseek(FILE *stream, long offset, int whence); -/*@ assigns *stream; - assigns *stream \from *pos; */ +/*@ requires valid_stream: \valid(stream); + requires valid_pos: \valid_read(pos); + requires initialization: pos: \initialized(pos); + assigns *stream; + assigns *stream \from *pos; + */ extern int fsetpos(FILE *stream, fpos_t const *pos); /*@ requires valid_stream: \valid(stream); @@ -4671,46 +4801,63 @@ extern int fsetpos(FILE *stream, fpos_t const *pos); */ extern long ftell(FILE *stream); -/*@ assigns *stream; - assigns *stream \from \nothing; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream; + assigns *stream \from \nothing; + */ extern void rewind(FILE *stream); -/*@ assigns *stream; - assigns *stream \from \nothing; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream; + assigns *stream \from \nothing; + */ extern void clearerr(FILE *stream); -/*@ assigns \result; - assigns \result \from *stream; */ +/*@ requires valid_stream: \valid(stream); + assigns \result; + assigns \result \from (indirect: *stream); + */ extern int feof(FILE *stream); -/*@ assigns \result; - assigns \result \from *stream; */ +/*@ requires valid_stream: \valid(stream); + assigns \result; + assigns \result \from (indirect: *stream); + */ extern int fileno(FILE *stream); -/*@ assigns *stream; - assigns *stream \from \nothing; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream; + assigns *stream \from \nothing; + */ extern void flockfile(FILE *stream); -/*@ assigns *stream; - assigns *stream \from \nothing; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream; + assigns *stream \from \nothing; + */ extern void funlockfile(FILE *stream); -/*@ assigns \result, *stream; +/*@ requires valid_stream: \valid(stream); + assigns \result, *stream; assigns \result \from \nothing; assigns *stream \from \nothing; */ extern int ftrylockfile(FILE *stream); -/*@ assigns \result; - assigns \result \from *stream; */ +/*@ requires valid_stream: \valid(stream); + assigns \result; + assigns \result \from (indirect: *stream); + */ extern int ferror(FILE *stream); -/*@ assigns __fc_stdout; - assigns __fc_stdout \from __fc_errno, *(s + (..)); +/*@ requires valid_string_s: valid_read_string(s); + assigns __fc_stdout; + assigns __fc_stdout \from __fc_errno, *(s + (0 .. strlen{Old}(s))); */ extern void perror(char const *s); -/*@ assigns \result, *stream; +/*@ requires valid_stream: \valid(stream); + assigns \result, *stream; assigns \result \from *stream; assigns *stream \from *stream; */ @@ -4720,28 +4867,41 @@ extern int getc_unlocked(FILE *stream); assigns \result \from *__fc_stdin; */ extern int getchar_unlocked(void); -/*@ assigns *stream; - assigns *stream \from c; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream, \result; + assigns *stream \from c; + assigns \result \from (indirect: *stream); + */ extern int putc_unlocked(int c, FILE *stream); -/*@ assigns *__fc_stdout; - assigns *__fc_stdout \from c; */ +/*@ assigns *__fc_stdout, \result; + assigns *__fc_stdout \from c; + assigns \result \from (indirect: *__fc_stdout); + */ extern int putchar_unlocked(int c); -/*@ assigns *stream; - assigns *stream \from \nothing; */ +/*@ requires valid_stream: \valid(stream); + assigns *stream; + assigns *stream \from \nothing; + */ extern void clearerr_unlocked(FILE *stream); -/*@ assigns \result; - assigns \result \from *stream; */ +/*@ requires valid_stream: \valid(stream); + assigns \result; + assigns \result \from (indirect: *stream); + */ extern int feof_unlocked(FILE *stream); -/*@ assigns \result; - assigns \result \from *stream; */ +/*@ requires valid_stream: \valid(stream); + assigns \result; + assigns \result \from (indirect: *stream); + */ extern int ferror_unlocked(FILE *stream); -/*@ assigns \result; - assigns \result \from *stream; */ +/*@ requires valid_stream: \valid(stream); + assigns \result; + assigns \result \from (indirect: *stream); + */ extern int fileno_unlocked(FILE *stream); /*@ axiomatic pipe_streams { @@ -6065,9 +6225,10 @@ extern clock_t clock(void); assigns \result \from time1, time0; */ extern double difftime(time_t time1, time_t time0); -/*@ assigns *timeptr, \result; +/*@ requires valid_timeptr: \valid(timeptr); + assigns *timeptr, \result; assigns *timeptr \from *timeptr; - assigns \result \from *timeptr; + assigns \result \from (indirect: *timeptr); */ extern time_t mktime(struct tm *timeptr); @@ -6109,7 +6270,8 @@ extern char *ctime(time_t const *timer); struct tm __fc_time_tm; struct tm * const __fc_p_time_tm = & __fc_time_tm; -/*@ ensures +/*@ requires valid_timer: \valid_read(timer); + ensures result_null_or_internal_tm: \result ≡ &__fc_time_tm ∨ \result ≡ \null; assigns \result, __fc_time_tm; @@ -6118,7 +6280,8 @@ struct tm * const __fc_p_time_tm = & __fc_time_tm; */ extern struct tm *gmtime(time_t const *timer); -/*@ ensures +/*@ requires valid_timer: \valid_read(timer); + ensures result_null_or_internal_tm: \result ≡ &__fc_time_tm ∨ \result ≡ \null; assigns \result, __fc_time_tm; @@ -6295,8 +6458,6 @@ extern int clock_nanosleep(clockid_t clock_id, int flags, */ extern int nanosleep(struct timespec const *rqtp, struct timespec *rmtp); -extern void tzset(void); - extern char *tzname[2]; /*@ assigns *(tzname[0 .. 1] + (0 ..)); @@ -6304,7 +6465,21 @@ extern char *tzname[2]; */ extern void tzset(void); -/*@ ensures +/*@ requires + valid: + valid_read_or_empty((void *)s, (unsigned int)(sizeof(wchar_t) * n)) ∨ + \valid_read((unsigned char *)s + (0 .. wmemchr_off(s, c, n))); + requires + initialization: + \initialized(s + (0 .. n - 1)) ∨ + \initialized(s + (0 .. wmemchr_off(s, c, n))); + requires + danglingness: + non_escaping((void *)s, (unsigned int)(sizeof(wchar_t) * n)) ∨ + non_escaping((void *)s, + (unsigned int)(sizeof(wchar_t) * + (wmemchr_off(s, c, n) + 1))); + ensures result_null_or_inside_s: \result ≡ \null ∨ \subset(\result, \old(s) + (0 .. \old(n) - 1)); assigns \result; @@ -6313,7 +6488,21 @@ extern void tzset(void); */ extern wchar_t *wmemchr(wchar_t const *s, wchar_t c, size_t n); -/*@ assigns \result; +/*@ requires + valid_s1: + valid_read_or_empty((void *)s1, (unsigned int)(sizeof(wchar_t) * n)); + requires + valid_s2: + valid_read_or_empty((void *)s2, (unsigned int)(sizeof(wchar_t) * n)); + requires initialization: s1: \initialized(s1 + (0 .. n - 1)); + requires initialization: s2: \initialized(s2 + (0 .. n - 1)); + requires + danglingness: s1: + non_escaping((void *)s1, (unsigned int)(sizeof(wchar_t) * n)); + requires + danglingness: s2: + non_escaping((void *)s2, (unsigned int)(sizeof(wchar_t) * n)); + assigns \result; assigns \result \from (indirect: *(s1 + (0 .. n - 1))), (indirect: *(s2 + (0 .. n - 1))), (indirect: n); @@ -6322,7 +6511,9 @@ extern int wmemcmp(wchar_t const *s1, wchar_t const *s2, size_t n); wchar_t *wmemcpy(wchar_t *dest, wchar_t const *src, size_t n); -/*@ ensures result_ptr: \result ≡ \old(dest); +/*@ requires valid_src: \valid_read(src + (0 .. n - 1)); + requires valid_dest: \valid(dest + (0 .. n - 1)); + ensures result_ptr: \result ≡ \old(dest); assigns *(dest + (0 .. n - 1)), \result; assigns *(dest + (0 .. n - 1)) \from *(src + (0 .. n - 1)), (indirect: src), (indirect: n); @@ -6343,7 +6534,9 @@ wchar_t *wcscat(wchar_t *dest, wchar_t const *src); */ extern wchar_t *wcschr(wchar_t const *wcs, wchar_t wc); -/*@ assigns \result; +/*@ requires valid_wstring_s1: valid_read_wstring(s1); + requires valid_wstring_s2: valid_read_wstring(s2); + assigns \result; assigns \result \from (indirect: *(s1 + (0 ..))), (indirect: *(s2 + (0 ..))); */ @@ -6351,13 +6544,25 @@ extern int wcscmp(wchar_t const *s1, wchar_t const *s2); wchar_t *wcscpy(wchar_t *dest, wchar_t const *src); -/*@ assigns \result; +/*@ requires valid_wstring_wcs: valid_read_wstring(wcs); + requires valid_wstring_accept: valid_read_wstring(accept); + assigns \result; assigns \result \from (indirect: *(wcs + (0 ..))), (indirect: *(accept + (0 ..))); */ extern size_t wcscspn(wchar_t const *wcs, wchar_t const *accept); -/*@ assigns *(dest + (0 ..)), \result; +/*@ requires valid_nwstring_src: valid_read_nwstring(src, n); + requires valid_wstring_dest: valid_wstring(dest); + requires + room_for_concatenation: + \valid(dest + (wcslen(dest) .. wcslen(dest) + \min(wcslen(src), n))); + requires + separation: + \separated( + dest + (0 .. wcslen(dest) + wcslen(src)), src + (0 .. wcslen(src)) + ); + assigns *(dest + (0 ..)), \result; assigns *(dest + (0 ..)) \from *(dest + (0 ..)), (indirect: dest), *(src + (0 .. n - 1)), (indirect: src), (indirect: n); @@ -6368,7 +6573,9 @@ extern size_t wcscspn(wchar_t const *wcs, wchar_t const *accept); extern size_t wcslcat(wchar_t * __restrict dest, wchar_t const * __restrict src, size_t n); -/*@ requires +/*@ requires valid_wstring_src: valid_read_wstring(src); + requires room_nwstring: \valid(dest + (0 .. n)); + requires separation: dest: src: \separated(dest + (0 .. n - 1), src + (0 .. n - 1)); assigns *(dest + (0 .. n - 1)), \result; @@ -6384,7 +6591,9 @@ size_t wcslen(wchar_t const *str); wchar_t *wcsncat(wchar_t *dest, wchar_t const *src, size_t n); -/*@ assigns \result; +/*@ requires valid_wstring_s1: valid_read_wstring(s1); + requires valid_wstring_s2: valid_read_wstring(s2); + assigns \result; assigns \result \from (indirect: *(s1 + (0 .. n - 1))), (indirect: *(s2 + (0 .. n - 1))), (indirect: n); @@ -6393,7 +6602,9 @@ extern int wcsncmp(wchar_t const *s1, wchar_t const *s2, size_t n); wchar_t *wcsncpy(wchar_t *dest, wchar_t const *src, size_t n); -/*@ ensures +/*@ requires valid_wstring_wcs: valid_read_wstring(wcs); + requires valid_wstring_accept: valid_read_wstring(accept); + ensures result_null_or_inside_wcs: \result ≡ \null ∨ \subset(\result, \old(wcs) + (0 ..)); assigns \result; @@ -6402,21 +6613,28 @@ wchar_t *wcsncpy(wchar_t *dest, wchar_t const *src, size_t n); */ extern wchar_t *wcspbrk(wchar_t const *wcs, wchar_t const *accept); -/*@ ensures +/*@ requires valid_wstring_wcs: valid_read_wstring(wcs); + ensures result_null_or_inside_wcs: \result ≡ \null ∨ \subset(\result, \old(wcs) + (0 ..)); assigns \result; - assigns \result \from wcs, (indirect: *(wcs + (0 ..))), (indirect: wc); + assigns \result + \from wcs, (indirect: *(wcs + (0 .. wcslen{Old}(wcs)))), (indirect: wc); */ extern wchar_t *wcsrchr(wchar_t const *wcs, wchar_t wc); -/*@ assigns \result; +/*@ requires valid_wstring_wcs: valid_read_wstring(wcs); + requires valid_wstring_accept: valid_read_wstring(accept); + assigns \result; assigns \result - \from (indirect: *(wcs + (0 ..))), (indirect: *(accept + (0 ..))); + \from (indirect: *(wcs + (0 .. wcslen{Old}(wcs)))), + (indirect: *(accept + (0 .. wcslen{Old}(accept)))); */ extern size_t wcsspn(wchar_t const *wcs, wchar_t const *accept); -/*@ ensures +/*@ requires valid_wstring_haystack: valid_read_wstring(haystack); + requires valid_wstring_needle: valid_read_wstring(needle); + ensures result_null_or_inside_haystack: \result ≡ \null ∨ \subset(\result, \old(haystack) + (0 ..)); assigns \result; @@ -6426,13 +6644,14 @@ extern size_t wcsspn(wchar_t const *wcs, wchar_t const *accept); */ extern wchar_t *wcsstr(wchar_t const *haystack, wchar_t const *needle); -/*@ requires valid_stream: \valid(stream); +/*@ requires room_nwstring: \valid(ws + (0 .. n - 1)); + requires valid_stream: \valid(stream); ensures result_null_or_same: \result ≡ \null ∨ \result ≡ \old(ws); ensures terminated_string_on_success: \result ≢ \null ⇒ valid_wstring(\old(ws)); - assigns *(ws + (0 .. n)), \result; - assigns *(ws + (0 .. n)) \from (indirect: n), (indirect: *stream); + assigns *(ws + (0 .. n - 1)), \result; + assigns *(ws + (0 .. n - 1)) \from (indirect: n), (indirect: *stream); assigns \result \from ws, (indirect: n), (indirect: *stream); */ extern wchar_t *fgetws(wchar_t * __restrict ws, int n, @@ -6445,6 +6664,12 @@ extern wchar_t *fgetws(wchar_t * __restrict ws, int n, */ /*@ requires + valid_dest: + valid_or_empty((void *)dest, (unsigned int)(sizeof(wchar_t) * n)); + requires + valid_src: + valid_read_or_empty((void *)src, (unsigned int)(sizeof(wchar_t) * n)); + requires separation: dest: src: \separated(dest + (0 .. n - 1), src + (0 .. n - 1)); ensures result_ptr: \result ≡ \old(dest); @@ -6465,7 +6690,8 @@ wchar_t *wmemcpy(wchar_t *dest, wchar_t const *src, size_t n) return dest; } -/*@ ensures result_ptr: \result ≡ \old(dest); +/*@ requires valid_wcs: \valid(dest + (0 .. len - 1)); + ensures result_ptr: \result ≡ \old(dest); ensures initialization: wcs: \initialized(\old(dest) + (0 .. \old(len) - 1)); ensures @@ -6487,11 +6713,15 @@ wchar_t *wmemset(wchar_t *dest, wchar_t val, size_t len) return dest; } -/*@ ensures result_ptr: \result ≡ \old(dest); - assigns *(dest + (0 ..)), \result; - assigns *(dest + (0 ..)) - \from *(src + (0 ..)), (indirect: src), *(dest + (0 ..)), - (indirect: dest); +/*@ requires valid_wstring_src: valid_read_wstring(src); + requires room_wstring: \valid(dest + (0 .. wcslen(src))); + requires + separation: + \separated(dest + (0 .. wcslen(src)), src + (0 .. wcslen(src))); + ensures result_ptr: \result ≡ \old(dest); + assigns *(dest + (0 .. wcslen{Old}(src))), \result; + assigns *(dest + (0 .. wcslen{Old}(src))) + \from *(src + (0 .. wcslen{Old}(src))), (indirect: src); assigns \result \from dest; */ wchar_t *wcscpy(wchar_t *dest, wchar_t const *src) @@ -6507,8 +6737,9 @@ wchar_t *wcscpy(wchar_t *dest, wchar_t const *src) } /*@ requires valid_string_s: valid_read_wstring(str); + ensures result_is_length: \result ≡ wcslen(\old(str)); assigns \result; - assigns \result \from (indirect: *(str + (0 ..))); + assigns \result \from (indirect: *(str + (0 .. wcslen{Old}(str)))); */ size_t wcslen(wchar_t const *str) { @@ -6518,10 +6749,13 @@ size_t wcslen(wchar_t const *str) return i; } -/*@ requires +/*@ requires valid_wstring_src: valid_read_wstring(src); + requires room_nwstring: \valid(dest + (0 .. n - 1)); + requires separation: dest: src: \separated(dest + (0 .. n - 1), src + (0 .. n - 1)); ensures result_ptr: \result ≡ \old(dest); + ensures initialization: \initialized(\old(dest) + (0 .. \old(n) - 1)); assigns *(dest + (0 .. n - 1)), \result; assigns *(dest + (0 .. n - 1)) \from *(src + (0 .. n - 1)), (indirect: src), (indirect: n); @@ -6543,7 +6777,17 @@ wchar_t *wcsncpy(wchar_t *dest, wchar_t const *src, size_t n) return dest; } -/*@ ensures result_ptr: \result ≡ \old(dest); +/*@ requires valid_wstring_src: valid_read_wstring(src); + requires valid_wstring_dest: valid_wstring(dest); + requires + room_for_concatenation: + \valid(dest + (wcslen(dest) .. wcslen(dest) + wcslen(src))); + requires + separation: + \separated( + dest + (0 .. wcslen(dest) + wcslen(src)), src + (0 .. wcslen(src)) + ); + ensures result_ptr: \result ≡ \old(dest); assigns *(dest + (0 ..)), \result; assigns *(dest + (0 ..)) \from *(dest + (0 ..)), (indirect: dest), *(src + (0 ..)), @@ -6563,7 +6807,17 @@ wchar_t *wcscat(wchar_t *dest, wchar_t const *src) return dest; } -/*@ ensures result_ptr: \result ≡ \old(dest); +/*@ requires valid_nwstring_src: valid_read_nwstring(src, n); + requires valid_wstring_dest: valid_wstring(dest); + requires + room_for_concatenation: + \valid(dest + (wcslen(dest) .. wcslen(dest) + \min(wcslen(src), n))); + requires + separation: + \separated( + dest + (0 .. wcslen(dest) + wcslen(src)), src + (0 .. wcslen(src)) + ); + ensures result_ptr: \result ≡ \old(dest); assigns *(dest + (0 ..)), \result; assigns *(dest + (0 ..)) \from *(dest + (0 ..)), (indirect: dest), *(src + (0 .. n - 1)), @@ -7011,8 +7265,13 @@ extern int __va_openat_mode_t(int dirfd, char const *filename, int flags, /*@ ghost extern int __fc_tz __attribute__((__FRAMA_C_MODEL__)); */ -/*@ assigns \result; - assigns \result \from *(path + (0 ..)), *(times + (0 .. 1)); +/*@ requires valid_path: valid_read_string(path); + requires + valid_times_or_null: \valid_read(times + (0 .. 1)) ∨ times ≡ \null; + assigns \result; + assigns \result + \from (indirect: *(path + (0 .. strlen{Old}(path)))), + (indirect: times), (indirect: *(times + (0 .. 1))); */ extern int utimes(char const *path, struct timeval const * /*[2]*/ times); @@ -7076,13 +7335,15 @@ extern int utimes(char const *path, struct timeval const * /*[2]*/ times); */ extern int gettimeofday(struct timeval * __restrict tv, void * __restrict tz); -/*@ assigns \result, __fc_time, __fc_tz; - assigns \result - \from tv->tv_sec, tv->tv_usec, tz->tz_dsttime, tz->tz_minuteswest; +/*@ requires valid_tv_or_null: \valid_read(tv) ∨ tv ≡ \null; + requires valid_tz_or_null: \valid_read(tz) ∨ tz ≡ \null; + ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1; + assigns __fc_time, __fc_tz, \result; assigns __fc_time \from tv->tv_sec, tv->tv_usec, tz->tz_dsttime, tz->tz_minuteswest; assigns __fc_tz \from tv->tv_sec, tv->tv_usec, tz->tz_dsttime, tz->tz_minuteswest; + assigns \result \from (indirect: *tv), (indirect: *tz); */ extern int settimeofday(struct timeval const *tv, struct timezone const *tz); @@ -7586,23 +7847,28 @@ extern int getpriority(int which, id_t who); assigns \result \from which, who, prio; */ extern int setpriority(int which, id_t who, int prio); -/*@ assigns \result, rl->rlim_cur, rl->rlim_max; - assigns \result \from r; - assigns rl->rlim_cur \from r; - assigns rl->rlim_max \from r; +/*@ requires valid_rlp: \valid(rlp); + assigns \result, *rlp; + assigns \result \from resource; + assigns *rlp \from resource; */ -extern int getrlimit(int r, struct rlimit *rl); +extern int getrlimit(int resource, struct rlimit *rlp); -/*@ assigns \result, ru->ru_utime, ru->ru_stime; - assigns \result \from r; - assigns ru->ru_utime \from r; - assigns ru->ru_stime \from r; +/*@ requires valid_r_usage: \valid(r_usage); + ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1; + assigns *r_usage, \result; + assigns *r_usage \from who; + assigns \result \from (indirect: who); */ -extern int getrusage(int r, struct rusage *ru); +extern int getrusage(int who, struct rusage *r_usage); -/*@ assigns \result; - assigns \result \from r, rl->rlim_cur, rl->rlim_max; */ -extern int setrlimit(int r, struct rlimit const *rl); +/*@ requires valid_rlp: \valid_read(rlp); + ensures result_ok_or_error: \result ≡ 0 ∨ \result ≡ -1; + assigns *rlp, \result; + assigns *rlp \from resource; + assigns \result \from (indirect: resource), (indirect: *rlp); + */ +extern int setrlimit(int resource, struct rlimit const *rlp); /*@ requires valid_buffer: \valid(buffer); assigns \result, *buffer; diff --git a/tests/libc/oracle/poll.res.oracle b/tests/libc/oracle/poll.res.oracle index 11b20253b1a0df727f0356e029ddf671fa985eb0..311b9eca83445d6938754f8aefda746f0ba0efbb 100644 --- a/tests/libc/oracle/poll.res.oracle +++ b/tests/libc/oracle/poll.res.oracle @@ -13,6 +13,8 @@ [eva] computing for function perror <- main. Called from tests/libc/poll.c:12. [eva] using specification for function perror +[eva] tests/libc/poll.c:12: + function perror: precondition 'valid_string_s' got status valid. [eva] Done for function perror [eva] Recording results for main [eva] done for function main diff --git a/tests/libc/oracle/stdio_c.res.oracle b/tests/libc/oracle/stdio_c.res.oracle index 40428842717797ef2180c0447d600f308ff4e75b..06ba2405258b9311bfeb5ca4f73196a063806ca0 100644 --- a/tests/libc/oracle/stdio_c.res.oracle +++ b/tests/libc/oracle/stdio_c.res.oracle @@ -17,18 +17,26 @@ [eva] computing for function ferror <- getline <- main. Called from share/libc/stdio.c:46. [eva] using specification for function ferror +[eva] share/libc/stdio.c:46: + function ferror: precondition 'valid_stream' got status valid. [eva] Done for function ferror [eva] computing for function feof <- getline <- main. Called from share/libc/stdio.c:46. [eva] using specification for function feof +[eva] share/libc/stdio.c:46: + function feof: precondition 'valid_stream' got status valid. [eva] Done for function feof [eva] share/libc/stdio.c:51: Call to builtin malloc [eva] share/libc/stdio.c:51: allocating variable __malloc_getline_l51 [eva] computing for function ferror <- getline <- main. Called from share/libc/stdio.c:60. +[eva] share/libc/stdio.c:60: + function ferror: precondition 'valid_stream' got status valid. [eva] Done for function ferror [eva] computing for function feof <- getline <- main. Called from share/libc/stdio.c:60. +[eva] share/libc/stdio.c:60: + function feof: precondition 'valid_stream' got status valid. [eva] Done for function feof [eva] computing for function fgetc <- getline <- main. Called from share/libc/stdio.c:62. diff --git a/tests/libc/oracle/stdio_h.res.oracle b/tests/libc/oracle/stdio_h.res.oracle index 267bfa3fb5cd00eb5c67fec3ee3113d8729ae044..8262aa6c408e46edf0fd8bb728cb16edf61af046 100644 --- a/tests/libc/oracle/stdio_h.res.oracle +++ b/tests/libc/oracle/stdio_h.res.oracle @@ -78,6 +78,22 @@ [eva] tests/libc/stdio_h.c:31: function fclose: precondition 'valid_stream' got status valid. [eva] Done for function fclose +[eva] computing for function fgets <- main. + Called from tests/libc/stdio_h.c:34. +[eva] using specification for function fgets +[eva] tests/libc/stdio_h.c:34: + function fgets: precondition 'valid_stream' got status valid. +[eva] tests/libc/stdio_h.c:34: + function fgets: precondition 'room_s' got status valid. +[eva] Done for function fgets +[eva:alarm] tests/libc/stdio_h.c:36: Warning: check got status unknown. +[eva] computing for function fgets <- main. + Called from tests/libc/stdio_h.c:38. +[eva] tests/libc/stdio_h.c:38: + function fgets: precondition 'valid_stream' got status valid. +[eva:alarm] tests/libc/stdio_h.c:38: Warning: + function fgets: precondition 'room_s' got status invalid. +[eva] Done for function fgets [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== @@ -89,5 +105,7 @@ r ∈ [--..--] tmp_2 ∈ {{ NULL ; &__fc_fopen + [0..120],0%8 }} redirected ∈ {{ NULL ; &__fc_fopen + [0..120],0%8 }} + fgets_buf0[0] ∈ [--..--] or UNINITIALIZED + fgets_res ∈ {{ NULL ; &fgets_buf0[0] }} __retres ∈ {0; 1; 2; 3} S___fc_stdout[0..1] ∈ [--..--] diff --git a/tests/libc/oracle/sys_time.res.oracle b/tests/libc/oracle/sys_time.res.oracle deleted file mode 100644 index 18c18fa9f8cf4ac0e2cd2252f3a3baf3d7dcd62c..0000000000000000000000000000000000000000 --- a/tests/libc/oracle/sys_time.res.oracle +++ /dev/null @@ -1,62 +0,0 @@ -[kernel] Parsing tests/libc/sys_time.c (with preprocessing) -[eva] Analyzing a complete application starting at main -[eva] Computing initial state -[eva] Initial state computed -[eva:initial-state] Values of globals at initialization - -[eva] computing for function setitimer <- main. - Called from tests/libc/sys_time.c:6. -[eva] using specification for function setitimer -[eva] tests/libc/sys_time.c:6: - function setitimer: precondition 'valid_new_value' got status valid. -[eva] tests/libc/sys_time.c:6: - function setitimer: precondition 'old_value_null_or_valid' got status valid. -[eva:invalid-assigns] tests/libc/sys_time.c:6: - Completely invalid destination for assigns clause *old_value. Ignoring. -[eva] Done for function setitimer -[eva] tests/libc/sys_time.c:7: assertion got status valid. -[eva] computing for function setitimer <- main. - Called from tests/libc/sys_time.c:9. -[eva] tests/libc/sys_time.c:9: - function setitimer: precondition 'valid_new_value' got status valid. -[eva] tests/libc/sys_time.c:9: - function setitimer: precondition 'old_value_null_or_valid' got status valid. -[eva] Done for function setitimer -[eva] tests/libc/sys_time.c:10: assertion got status valid. -[eva] tests/libc/sys_time.c:11: assertion got status valid. -[eva] computing for function getitimer <- main. - Called from tests/libc/sys_time.c:12. -[eva] using specification for function getitimer -[eva] tests/libc/sys_time.c:12: - function getitimer: precondition 'valid_curr_value' got status valid. -[eva] Done for function getitimer -[eva] tests/libc/sys_time.c:13: assertion got status valid. -[eva] tests/libc/sys_time.c:14: assertion got status valid. -[eva] computing for function getitimer <- main. - Called from tests/libc/sys_time.c:16. -[eva] tests/libc/sys_time.c:16: - function getitimer: precondition 'valid_curr_value' got status valid. -[eva] Done for function getitimer -[eva] tests/libc/sys_time.c:17: assertion got status valid. -[eva] computing for function setitimer <- main. - Called from tests/libc/sys_time.c:19. -[eva] tests/libc/sys_time.c:19: - function setitimer: precondition 'valid_new_value' got status valid. -[eva] tests/libc/sys_time.c:19: - function setitimer: precondition 'old_value_null_or_valid' got status valid. -[eva] Done for function setitimer -[eva] tests/libc/sys_time.c:20: assertion got status valid. -[eva] Recording results for main -[eva] done for function main -[eva] ====== VALUES COMPUTED ====== -[eva:final-states] Values at end of function main: - i1.it_interval.tv_sec ∈ {1} - .it_interval.tv_usec ∈ {100} - .it_value.tv_sec ∈ {2} - .it_value.tv_usec ∈ {200} - res ∈ {-1} - i2.it_interval.tv_sec ∈ [--..--] - .it_interval.tv_usec ∈ {1000000} - .it_value ∈ [--..--] - INVALID_ITIMER ∈ {-1} - __retres ∈ {0} diff --git a/tests/libc/oracle/sys_time_h.res.oracle b/tests/libc/oracle/sys_time_h.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..56221db7dec29a071d214607e6c178e1ccc12f1e --- /dev/null +++ b/tests/libc/oracle/sys_time_h.res.oracle @@ -0,0 +1,83 @@ +[kernel] Parsing tests/libc/sys_time_h.c (with preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + +[eva] computing for function setitimer <- main. + Called from tests/libc/sys_time_h.c:6. +[eva] using specification for function setitimer +[eva] tests/libc/sys_time_h.c:6: + function setitimer: precondition 'valid_new_value' got status valid. +[eva] tests/libc/sys_time_h.c:6: + function setitimer: precondition 'old_value_null_or_valid' got status valid. +[eva:invalid-assigns] tests/libc/sys_time_h.c:6: + Completely invalid destination for assigns clause *old_value. Ignoring. +[eva] Done for function setitimer +[eva] tests/libc/sys_time_h.c:7: assertion got status valid. +[eva] computing for function setitimer <- main. + Called from tests/libc/sys_time_h.c:9. +[eva] tests/libc/sys_time_h.c:9: + function setitimer: precondition 'valid_new_value' got status valid. +[eva] tests/libc/sys_time_h.c:9: + function setitimer: precondition 'old_value_null_or_valid' got status valid. +[eva] Done for function setitimer +[eva] tests/libc/sys_time_h.c:10: assertion got status valid. +[eva] tests/libc/sys_time_h.c:11: assertion got status valid. +[eva] computing for function getitimer <- main. + Called from tests/libc/sys_time_h.c:12. +[eva] using specification for function getitimer +[eva] tests/libc/sys_time_h.c:12: + function getitimer: precondition 'valid_curr_value' got status valid. +[eva] Done for function getitimer +[eva] tests/libc/sys_time_h.c:13: assertion got status valid. +[eva] tests/libc/sys_time_h.c:14: assertion got status valid. +[eva] computing for function getitimer <- main. + Called from tests/libc/sys_time_h.c:16. +[eva] tests/libc/sys_time_h.c:16: + function getitimer: precondition 'valid_curr_value' got status valid. +[eva] Done for function getitimer +[eva] tests/libc/sys_time_h.c:17: assertion got status valid. +[eva] computing for function setitimer <- main. + Called from tests/libc/sys_time_h.c:19. +[eva] tests/libc/sys_time_h.c:19: + function setitimer: precondition 'valid_new_value' got status valid. +[eva] tests/libc/sys_time_h.c:19: + function setitimer: precondition 'old_value_null_or_valid' got status valid. +[eva] Done for function setitimer +[eva] tests/libc/sys_time_h.c:20: assertion got status valid. +[eva] computing for function utimes <- main. + Called from tests/libc/sys_time_h.c:22. +[eva] using specification for function utimes +[eva] tests/libc/sys_time_h.c:22: + function utimes: precondition 'valid_path' got status valid. +[eva] tests/libc/sys_time_h.c:22: + function utimes: precondition 'valid_times_or_null' got status valid. +[eva] Done for function utimes +[eva] computing for function utimes <- main. + Called from tests/libc/sys_time_h.c:28. +[eva] tests/libc/sys_time_h.c:28: + function utimes: precondition 'valid_path' got status valid. +[eva] tests/libc/sys_time_h.c:28: + function utimes: precondition 'valid_times_or_null' got status valid. +[eva] Done for function utimes +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + i1.it_interval.tv_sec ∈ {1} + .it_interval.tv_usec ∈ {100} + .it_value.tv_sec ∈ {2} + .it_value.tv_usec ∈ {200} + res ∈ {-1} + i2.it_interval.tv_sec ∈ [--..--] + .it_interval.tv_usec ∈ {1000000} + .it_value ∈ [--..--] + INVALID_ITIMER ∈ {-1} + r1 ∈ [--..--] + tv[0].tv_sec ∈ {10000000} + [0].tv_usec ∈ {999999} + [1].tv_sec ∈ {-9000000} + [1].tv_usec ∈ {1} + r2 ∈ [--..--] + __retres ∈ {0} diff --git a/tests/libc/oracle/time_misc.res.oracle b/tests/libc/oracle/time_misc.res.oracle index 11b3437a14bb4490511094ca437543e11a7ed99e..b869818342bf421d884def68508d5e0d39319b14 100644 --- a/tests/libc/oracle/time_misc.res.oracle +++ b/tests/libc/oracle/time_misc.res.oracle @@ -23,6 +23,8 @@ [eva] computing for function localtime <- test_strftime <- main. Called from tests/libc/time_misc.c:19. [eva] using specification for function localtime +[eva] tests/libc/time_misc.c:19: + function localtime: precondition 'valid_timer' got status valid. [eva] Done for function localtime [eva] computing for function strftime <- test_strftime <- main. Called from tests/libc/time_misc.c:21. diff --git a/tests/libc/oracle/unistd_h.0.res.oracle b/tests/libc/oracle/unistd_h.0.res.oracle index 5b653c8e60e1ae17db8af7beee6cf8ab0a0e9195..23bd3f50c5392a7f5ff4ec33796919b99c80672b 100644 --- a/tests/libc/oracle/unistd_h.0.res.oracle +++ b/tests/libc/oracle/unistd_h.0.res.oracle @@ -9,6 +9,7 @@ \return(gethostname) == 0 (auto) \return(getpgrp) == 0 (auto) \return(isatty) == 0 (auto) + \return(pipe) == 0 (auto) \return(setegid) == 0 (auto) \return(seteuid) == 0 (auto) \return(setgid) == 0 (auto) @@ -477,6 +478,8 @@ [eva] computing for function ttyname <- main. Called from tests/libc/unistd_h.c:86. [eva] using specification for function ttyname +[eva] tests/libc/unistd_h.c:86: + function ttyname: precondition 'valid_fildes' got status valid. [eva] Done for function ttyname [eva] computing for function ttyname <- main. Called from tests/libc/unistd_h.c:86. @@ -529,6 +532,32 @@ [eva] computing for function chroot <- main. Called from tests/libc/unistd_h.c:92. [eva] Done for function chroot +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:95. +[eva] using specification for function pipe +[eva:alarm] tests/libc/unistd_h.c:95: Warning: + function pipe: precondition 'valid_pipefd' got status invalid. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:95. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:100. +[eva:alarm] tests/libc/unistd_h.c:100: Warning: + function pipe: precondition 'valid_pipefd' got status invalid. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:100. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:104. +[eva] tests/libc/unistd_h.c:104: + function pipe: precondition 'valid_pipefd' got status valid. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:104. +[eva] Done for function pipe +[eva] tests/libc/unistd_h.c:105: check 'ok' got status valid. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== @@ -554,4 +583,6 @@ sgid ∈ [--..--] or UNINITIALIZED p ∈ [--..--] tty ∈ {{ NULL ; &__fc_ttyname[0] }} + halfpipe ∈ UNINITIALIZED + pipefd[0..1] ∈ [0..1023] or UNINITIALIZED __retres ∈ {0; 1} diff --git a/tests/libc/oracle/unistd_h.1.res.oracle b/tests/libc/oracle/unistd_h.1.res.oracle index 5cd1bf50f5d48d55f8b70a02c7b37f8b1385336f..32c8e8164076a62e38d24dc837301d2d539dd3d8 100644 --- a/tests/libc/oracle/unistd_h.1.res.oracle +++ b/tests/libc/oracle/unistd_h.1.res.oracle @@ -9,6 +9,7 @@ \return(gethostname) == 0 (auto) \return(getpgrp) == 0 (auto) \return(isatty) == 0 (auto) + \return(pipe) == 0 (auto) \return(setegid) == 0 (auto) \return(seteuid) == 0 (auto) \return(setgid) == 0 (auto) @@ -477,6 +478,8 @@ [eva] computing for function ttyname <- main. Called from tests/libc/unistd_h.c:86. [eva] using specification for function ttyname +[eva] tests/libc/unistd_h.c:86: + function ttyname: precondition 'valid_fildes' got status valid. [eva] Done for function ttyname [eva] computing for function ttyname <- main. Called from tests/libc/unistd_h.c:86. @@ -529,6 +532,32 @@ [eva] computing for function chroot <- main. Called from tests/libc/unistd_h.c:92. [eva] Done for function chroot +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:95. +[eva] using specification for function pipe +[eva:alarm] tests/libc/unistd_h.c:95: Warning: + function pipe: precondition 'valid_pipefd' got status invalid. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:95. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:100. +[eva:alarm] tests/libc/unistd_h.c:100: Warning: + function pipe: precondition 'valid_pipefd' got status invalid. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:100. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:104. +[eva] tests/libc/unistd_h.c:104: + function pipe: precondition 'valid_pipefd' got status valid. +[eva] Done for function pipe +[eva] computing for function pipe <- main. + Called from tests/libc/unistd_h.c:104. +[eva] Done for function pipe +[eva] tests/libc/unistd_h.c:105: check 'ok' got status valid. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== @@ -554,4 +583,6 @@ sgid ∈ [--..--] or UNINITIALIZED p ∈ [--..--] tty ∈ {{ NULL ; &__fc_ttyname[0] }} + halfpipe ∈ UNINITIALIZED + pipefd[0..1] ∈ [0..1023] or UNINITIALIZED __retres ∈ {0; 1} diff --git a/tests/libc/oracle/wchar_c_h.0.res.oracle b/tests/libc/oracle/wchar_c_h.0.res.oracle index 67067c92b5680061e15983d06f22d8dd457234f0..8e6c444ee9de224d23eb1b8e1040a87196b79489 100644 --- a/tests/libc/oracle/wchar_c_h.0.res.oracle +++ b/tests/libc/oracle/wchar_c_h.0.res.oracle @@ -8,9 +8,30 @@ t ∈ {0} nondet ∈ [--..--] [eva] tests/libc/wchar_c_h.c:31: Call to builtin wmemchr +[eva] tests/libc/wchar_c_h.c:31: + function wmemchr: precondition 'valid' got status valid. +[eva] share/libc/wchar.h:58: + Cannot evaluate range bound wmemchr_off(s, c, n) + (unsupported ACSL construct: logic function wmemchr_off). Approximating +[eva] tests/libc/wchar_c_h.c:31: + function wmemchr: precondition 'initialization' got status valid. +[eva] tests/libc/wchar_c_h.c:31: + function wmemchr: precondition 'danglingness' got status valid. [eva] computing for function wmemcmp <- main. Called from tests/libc/wchar_c_h.c:32. [eva] using specification for function wmemcmp +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'valid_s1' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'valid_s2' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'initialization,s1' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'initialization,s2' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'danglingness,s1' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'danglingness,s2' got status valid. [eva] Done for function wmemcmp [eva] computing for function wmemcpy <- main. Called from tests/libc/wchar_c_h.c:33. @@ -19,6 +40,10 @@ [eva] computing for function wmemmove <- main. Called from tests/libc/wchar_c_h.c:34. [eva] using specification for function wmemmove +[eva] tests/libc/wchar_c_h.c:34: + function wmemmove: precondition 'valid_src' got status valid. +[eva] tests/libc/wchar_c_h.c:34: + function wmemmove: precondition 'valid_dest' got status valid. [eva] Done for function wmemmove [eva] computing for function wmemset <- main. Called from tests/libc/wchar_c_h.c:35. @@ -30,6 +55,10 @@ [eva] computing for function wcscmp <- main. Called from tests/libc/wchar_c_h.c:37. [eva] using specification for function wcscmp +[eva] tests/libc/wchar_c_h.c:37: + function wcscmp: precondition 'valid_wstring_s1' got status valid. +[eva] tests/libc/wchar_c_h.c:37: + function wcscmp: precondition 'valid_wstring_s2' got status valid. [eva] Done for function wcscmp [eva] computing for function wcscpy <- main. Called from tests/libc/wchar_c_h.c:38. @@ -38,14 +67,30 @@ [eva] computing for function wcscspn <- main. Called from tests/libc/wchar_c_h.c:39. [eva] using specification for function wcscspn +[eva] tests/libc/wchar_c_h.c:39: + function wcscspn: precondition 'valid_wstring_wcs' got status valid. +[eva] tests/libc/wchar_c_h.c:39: + function wcscspn: precondition 'valid_wstring_accept' got status valid. [eva] Done for function wcscspn [eva] computing for function wcslcat <- main. Called from tests/libc/wchar_c_h.c:40. [eva] using specification for function wcslcat +[eva] tests/libc/wchar_c_h.c:40: + function wcslcat: precondition 'valid_nwstring_src' got status valid. +[eva:alarm] tests/libc/wchar_c_h.c:40: Warning: + function wcslcat: precondition 'valid_wstring_dest' got status invalid. +[eva] tests/libc/wchar_c_h.c:40: + function wcslcat: no state left, precondition 'room_for_concatenation' got status valid. +[eva] tests/libc/wchar_c_h.c:40: + function wcslcat: no state left, precondition 'separation' got status valid. [eva] Done for function wcslcat [eva] computing for function wcslcpy <- main. Called from tests/libc/wchar_c_h.c:41. [eva] using specification for function wcslcpy +[eva] tests/libc/wchar_c_h.c:41: + function wcslcpy: precondition 'valid_wstring_src' got status valid. +[eva] tests/libc/wchar_c_h.c:41: + function wcslcpy: precondition 'room_nwstring' got status valid. [eva] tests/libc/wchar_c_h.c:41: function wcslcpy: precondition 'separation,dest,src' got status valid. [eva] Done for function wcslcpy @@ -55,6 +100,10 @@ [eva] computing for function wcsncmp <- main. Called from tests/libc/wchar_c_h.c:43. [eva] using specification for function wcsncmp +[eva] tests/libc/wchar_c_h.c:43: + function wcsncmp: precondition 'valid_wstring_s1' got status valid. +[eva] tests/libc/wchar_c_h.c:43: + function wcsncmp: precondition 'valid_wstring_s2' got status valid. [eva] Done for function wcsncmp [eva] computing for function wcsncpy <- main. Called from tests/libc/wchar_c_h.c:44. @@ -63,18 +112,32 @@ [eva] computing for function wcspbrk <- main. Called from tests/libc/wchar_c_h.c:45. [eva] using specification for function wcspbrk +[eva] tests/libc/wchar_c_h.c:45: + function wcspbrk: precondition 'valid_wstring_wcs' got status valid. +[eva] tests/libc/wchar_c_h.c:45: + function wcspbrk: precondition 'valid_wstring_accept' got status valid. [eva] Done for function wcspbrk [eva] computing for function wcsrchr <- main. Called from tests/libc/wchar_c_h.c:46. [eva] using specification for function wcsrchr +[eva] tests/libc/wchar_c_h.c:46: + function wcsrchr: precondition 'valid_wstring_wcs' got status valid. [eva] Done for function wcsrchr [eva] computing for function wcsspn <- main. Called from tests/libc/wchar_c_h.c:47. [eva] using specification for function wcsspn +[eva] tests/libc/wchar_c_h.c:47: + function wcsspn: precondition 'valid_wstring_wcs' got status valid. +[eva] tests/libc/wchar_c_h.c:47: + function wcsspn: precondition 'valid_wstring_accept' got status valid. [eva] Done for function wcsspn [eva] computing for function wcsstr <- main. Called from tests/libc/wchar_c_h.c:48. [eva] using specification for function wcsstr +[eva] tests/libc/wchar_c_h.c:48: + function wcsstr: precondition 'valid_wstring_haystack' got status valid. +[eva] tests/libc/wchar_c_h.c:48: + function wcsstr: precondition 'valid_wstring_needle' got status valid. [eva] Done for function wcsstr [eva] computing for function wcscat <- main. Called from tests/libc/wchar_c_h.c:52. @@ -112,7 +175,19 @@ [eva] tests/libc/wchar_c_h.c:68: function wcschr: precondition 'valid_wstring_src' got status valid. [eva] tests/libc/wchar_c_h.c:69: Call to builtin wmemchr +[eva] tests/libc/wchar_c_h.c:69: + function wmemchr: precondition 'valid' got status valid. +[eva] tests/libc/wchar_c_h.c:69: + function wmemchr: precondition 'initialization' got status valid. +[eva] tests/libc/wchar_c_h.c:69: + function wmemchr: precondition 'danglingness' got status valid. [eva] tests/libc/wchar_c_h.c:70: Call to builtin wmemchr +[eva] tests/libc/wchar_c_h.c:70: + function wmemchr: precondition 'valid' got status valid. +[eva] tests/libc/wchar_c_h.c:70: + function wmemchr: precondition 'initialization' got status valid. +[eva] tests/libc/wchar_c_h.c:70: + function wmemchr: precondition 'danglingness' got status valid. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== @@ -174,7 +249,17 @@ [eva:final-states] Values at end of function main: sc1 ∈ {{ L"Needle" }} sc2 ∈ {{ L"Haystack" }} - buf[0..19] ∈ [--..--] or UNINITIALIZED + buf[0..4] ∈ [--..--] or UNINITIALIZED + [5] ∈ {0; 72; 97; 115; 116; 121} or UNINITIALIZED + [6] ∈ {0; 97; 99; 115; 116; 121} or UNINITIALIZED + [7] ∈ {0; 97; 99; 107; 115; 116; 121} or UNINITIALIZED + [8] ∈ {0; 97; 99; 107; 115; 116} or UNINITIALIZED + [9] ∈ {0; 97; 99; 107; 116} or UNINITIALIZED + [10] ∈ {0; 97; 99; 107} or UNINITIALIZED + [11] ∈ {0; 99; 107} or UNINITIALIZED + [12] ∈ {0; 107} or UNINITIALIZED + [13] ∈ {0} or UNINITIALIZED + [14..19] ∈ UNINITIALIZED c ∈ [--..--] n ∈ {5} r ∈ [--..--] or UNINITIALIZED diff --git a/tests/libc/oracle/wchar_c_h.1.res.oracle b/tests/libc/oracle/wchar_c_h.1.res.oracle index d90fa422c1726b48744c12ed9f5c4b199b9edb7b..8a8b446879fbfa8b923ba6416bbab050564219f2 100644 --- a/tests/libc/oracle/wchar_c_h.1.res.oracle +++ b/tests/libc/oracle/wchar_c_h.1.res.oracle @@ -8,23 +8,54 @@ t ∈ {0} nondet ∈ [--..--] [eva] tests/libc/wchar_c_h.c:31: Call to builtin wmemchr +[eva] tests/libc/wchar_c_h.c:31: + function wmemchr: precondition 'valid' got status valid. +[eva] share/libc/wchar.h:58: + Cannot evaluate range bound wmemchr_off(s, c, n) + (unsupported ACSL construct: logic function wmemchr_off). Approximating +[eva] tests/libc/wchar_c_h.c:31: + function wmemchr: precondition 'initialization' got status valid. +[eva] tests/libc/wchar_c_h.c:31: + function wmemchr: precondition 'danglingness' got status valid. [eva] computing for function wmemcmp <- main. Called from tests/libc/wchar_c_h.c:32. [eva] using specification for function wmemcmp +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'valid_s1' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'valid_s2' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'initialization,s1' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'initialization,s2' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'danglingness,s1' got status valid. +[eva] tests/libc/wchar_c_h.c:32: + function wmemcmp: precondition 'danglingness,s2' got status valid. [eva] Done for function wmemcmp [eva] computing for function wmemcpy <- main. Called from tests/libc/wchar_c_h.c:33. [eva] using specification for function wmemcpy +[eva] tests/libc/wchar_c_h.c:33: + function wmemcpy: precondition 'valid_dest' got status valid. +[eva] tests/libc/wchar_c_h.c:33: + function wmemcpy: precondition 'valid_src' got status valid. [eva] tests/libc/wchar_c_h.c:33: function wmemcpy: precondition 'separation,dest,src' got status valid. [eva] Done for function wmemcpy [eva] computing for function wmemmove <- main. Called from tests/libc/wchar_c_h.c:34. [eva] using specification for function wmemmove +[eva] tests/libc/wchar_c_h.c:34: + function wmemmove: precondition 'valid_src' got status valid. +[eva] tests/libc/wchar_c_h.c:34: + function wmemmove: precondition 'valid_dest' got status valid. [eva] Done for function wmemmove [eva] computing for function wmemset <- main. Called from tests/libc/wchar_c_h.c:35. [eva] using specification for function wmemset +[eva] tests/libc/wchar_c_h.c:35: + function wmemset: precondition 'valid_wcs' got status valid. [eva] Done for function wmemset [eva] tests/libc/wchar_c_h.c:36: Call to builtin wcschr [eva] tests/libc/wchar_c_h.c:36: @@ -32,22 +63,48 @@ [eva] computing for function wcscmp <- main. Called from tests/libc/wchar_c_h.c:37. [eva] using specification for function wcscmp +[eva] tests/libc/wchar_c_h.c:37: + function wcscmp: precondition 'valid_wstring_s1' got status valid. +[eva] tests/libc/wchar_c_h.c:37: + function wcscmp: precondition 'valid_wstring_s2' got status valid. [eva] Done for function wcscmp [eva] computing for function wcscpy <- main. Called from tests/libc/wchar_c_h.c:38. [eva] using specification for function wcscpy +[eva] tests/libc/wchar_c_h.c:38: + function wcscpy: precondition 'valid_wstring_src' got status valid. +[eva] tests/libc/wchar_c_h.c:38: + function wcscpy: precondition 'room_wstring' got status valid. +[eva] tests/libc/wchar_c_h.c:38: + function wcscpy: precondition 'separation' got status valid. [eva] Done for function wcscpy [eva] computing for function wcscspn <- main. Called from tests/libc/wchar_c_h.c:39. [eva] using specification for function wcscspn +[eva] tests/libc/wchar_c_h.c:39: + function wcscspn: precondition 'valid_wstring_wcs' got status valid. +[eva] tests/libc/wchar_c_h.c:39: + function wcscspn: precondition 'valid_wstring_accept' got status valid. [eva] Done for function wcscspn [eva] computing for function wcslcat <- main. Called from tests/libc/wchar_c_h.c:40. [eva] using specification for function wcslcat +[eva] tests/libc/wchar_c_h.c:40: + function wcslcat: precondition 'valid_nwstring_src' got status valid. +[eva:alarm] tests/libc/wchar_c_h.c:40: Warning: + function wcslcat: precondition 'valid_wstring_dest' got status invalid. +[eva] tests/libc/wchar_c_h.c:40: + function wcslcat: no state left, precondition 'room_for_concatenation' got status valid. +[eva] tests/libc/wchar_c_h.c:40: + function wcslcat: no state left, precondition 'separation' got status valid. [eva] Done for function wcslcat [eva] computing for function wcslcpy <- main. Called from tests/libc/wchar_c_h.c:41. [eva] using specification for function wcslcpy +[eva] tests/libc/wchar_c_h.c:41: + function wcslcpy: precondition 'valid_wstring_src' got status valid. +[eva] tests/libc/wchar_c_h.c:41: + function wcslcpy: precondition 'room_nwstring' got status valid. [eva] tests/libc/wchar_c_h.c:41: function wcslcpy: precondition 'separation,dest,src' got status valid. [eva] Done for function wcslcpy @@ -57,36 +114,74 @@ [eva] computing for function wcsncmp <- main. Called from tests/libc/wchar_c_h.c:43. [eva] using specification for function wcsncmp +[eva] tests/libc/wchar_c_h.c:43: + function wcsncmp: precondition 'valid_wstring_s1' got status valid. +[eva] tests/libc/wchar_c_h.c:43: + function wcsncmp: precondition 'valid_wstring_s2' got status valid. [eva] Done for function wcsncmp [eva] computing for function wcsncpy <- main. Called from tests/libc/wchar_c_h.c:44. [eva] using specification for function wcsncpy +[eva] tests/libc/wchar_c_h.c:44: + function wcsncpy: precondition 'valid_wstring_src' got status valid. +[eva] tests/libc/wchar_c_h.c:44: + function wcsncpy: precondition 'room_nwstring' got status valid. [eva] tests/libc/wchar_c_h.c:44: function wcsncpy: precondition 'separation,dest,src' got status valid. [eva] Done for function wcsncpy [eva] computing for function wcspbrk <- main. Called from tests/libc/wchar_c_h.c:45. [eva] using specification for function wcspbrk +[eva] tests/libc/wchar_c_h.c:45: + function wcspbrk: precondition 'valid_wstring_wcs' got status valid. +[eva] tests/libc/wchar_c_h.c:45: + function wcspbrk: precondition 'valid_wstring_accept' got status valid. [eva] Done for function wcspbrk [eva] computing for function wcsrchr <- main. Called from tests/libc/wchar_c_h.c:46. [eva] using specification for function wcsrchr +[eva] tests/libc/wchar_c_h.c:46: + function wcsrchr: precondition 'valid_wstring_wcs' got status valid. [eva] Done for function wcsrchr [eva] computing for function wcsspn <- main. Called from tests/libc/wchar_c_h.c:47. [eva] using specification for function wcsspn +[eva] tests/libc/wchar_c_h.c:47: + function wcsspn: precondition 'valid_wstring_wcs' got status valid. +[eva] tests/libc/wchar_c_h.c:47: + function wcsspn: precondition 'valid_wstring_accept' got status valid. [eva] Done for function wcsspn [eva] computing for function wcsstr <- main. Called from tests/libc/wchar_c_h.c:48. [eva] using specification for function wcsstr +[eva] tests/libc/wchar_c_h.c:48: + function wcsstr: precondition 'valid_wstring_haystack' got status valid. +[eva] tests/libc/wchar_c_h.c:48: + function wcsstr: precondition 'valid_wstring_needle' got status valid. [eva] Done for function wcsstr [eva] computing for function wcscat <- main. Called from tests/libc/wchar_c_h.c:52. [eva] using specification for function wcscat +[eva] tests/libc/wchar_c_h.c:52: + function wcscat: precondition 'valid_wstring_src' got status valid. +[eva] tests/libc/wchar_c_h.c:52: + function wcscat: precondition 'valid_wstring_dest' got status valid. +[eva] tests/libc/wchar_c_h.c:52: + function wcscat: precondition 'room_for_concatenation' got status valid. +[eva] tests/libc/wchar_c_h.c:52: + function wcscat: precondition 'separation' got status valid. [eva] Done for function wcscat [eva] computing for function wcsncat <- main. Called from tests/libc/wchar_c_h.c:54. [eva] using specification for function wcsncat +[eva] tests/libc/wchar_c_h.c:54: + function wcsncat: precondition 'valid_nwstring_src' got status valid. +[eva] tests/libc/wchar_c_h.c:54: + function wcsncat: precondition 'valid_wstring_dest' got status valid. +[eva] tests/libc/wchar_c_h.c:54: + function wcsncat: precondition 'room_for_concatenation' got status valid. +[eva] tests/libc/wchar_c_h.c:54: + function wcsncat: precondition 'separation' got status valid. [eva] Done for function wcsncat [eva] tests/libc/wchar_c_h.c:57: Call to builtin wcslen [eva:alarm] tests/libc/wchar_c_h.c:57: Warning: @@ -110,7 +205,19 @@ [eva] tests/libc/wchar_c_h.c:68: function wcschr: precondition 'valid_wstring_src' got status valid. [eva] tests/libc/wchar_c_h.c:69: Call to builtin wmemchr +[eva] tests/libc/wchar_c_h.c:69: + function wmemchr: precondition 'valid' got status valid. +[eva] tests/libc/wchar_c_h.c:69: + function wmemchr: precondition 'initialization' got status valid. +[eva] tests/libc/wchar_c_h.c:69: + function wmemchr: precondition 'danglingness' got status valid. [eva] tests/libc/wchar_c_h.c:70: Call to builtin wmemchr +[eva] tests/libc/wchar_c_h.c:70: + function wmemchr: precondition 'valid' got status valid. +[eva] tests/libc/wchar_c_h.c:70: + function wmemchr: precondition 'initialization' got status valid. +[eva] tests/libc/wchar_c_h.c:70: + function wmemchr: precondition 'danglingness' got status valid. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== diff --git a/tests/libc/oracle/wchar_h.res.oracle b/tests/libc/oracle/wchar_h.res.oracle index e1161566c7fd14a4c7f27edfa0bad2ff7818e2b3..2ffbd071fc836e2895f3dcf5ae60d6a8f06b29ec 100644 --- a/tests/libc/oracle/wchar_h.res.oracle +++ b/tests/libc/oracle/wchar_h.res.oracle @@ -3,7 +3,7 @@ [eva] Computing initial state [eva] Initial state computed [eva:initial-state] Values of globals at initialization - + v ∈ [--..--] [eva] computing for function fopen <- main. Called from tests/libc/wchar_h.c:5. [eva] using specification for function fopen @@ -15,15 +15,196 @@ [eva] computing for function fgetws <- main. Called from tests/libc/wchar_h.c:8. [eva] using specification for function fgetws +[eva] tests/libc/wchar_h.c:8: + function fgetws: precondition 'room_nwstring' got status valid. [eva] tests/libc/wchar_h.c:8: function fgetws: precondition 'valid_stream' got status valid. [eva] Done for function fgetws [eva] tests/libc/wchar_h.c:10: assertion got status valid. +[eva] tests/libc/wchar_h.c:13: Call to builtin wmemchr +[eva] tests/libc/wchar_h.c:13: + function wmemchr: precondition 'valid' got status valid. +[eva] share/libc/wchar.h:58: + Cannot evaluate range bound wmemchr_off(s, c, n) + (unsupported ACSL construct: logic function wmemchr_off). Approximating +[eva:alarm] tests/libc/wchar_h.c:13: Warning: + function wmemchr: precondition 'initialization' got status unknown. +[eva] tests/libc/wchar_h.c:13: + function wmemchr: precondition 'danglingness' got status valid. +[eva] tests/libc/wchar_h.c:14: check 'ok' got status valid. +[eva] tests/libc/wchar_h.c:15: Call to builtin wmemchr +[eva] share/libc/wchar.h:55: + Cannot evaluate range bound wmemchr_off(s, c, n) + (unsupported ACSL construct: logic function wmemchr_off). Approximating +[eva:alarm] tests/libc/wchar_h.c:15: Warning: + function wmemchr: precondition 'valid' got status unknown. +[eva] tests/libc/wchar_h.c:15: + function wmemchr: precondition 'initialization' got status valid. +[eva] tests/libc/wchar_h.c:15: + function wmemchr: precondition 'danglingness' got status valid. +[eva] tests/libc/wchar_h.c:16: check 'ok' got status valid. +[eva] tests/libc/wchar_h.c:18: Call to builtin wmemchr +[eva] tests/libc/wchar_h.c:18: + function wmemchr: precondition 'valid' got status valid. +[eva:alarm] tests/libc/wchar_h.c:18: Warning: + function wmemchr: precondition 'initialization' got status unknown. +[eva] tests/libc/wchar_h.c:18: + function wmemchr: precondition 'danglingness' got status valid. +[eva] tests/libc/wchar_h.c:21: Call to builtin wmemchr +[eva:alarm] tests/libc/wchar_h.c:21: Warning: + function wmemchr: precondition 'valid' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:21: Warning: + function wmemchr: precondition 'initialization' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:21: Warning: + function wmemchr: precondition 'danglingness' got status unknown. +[eva] tests/libc/wchar_h.c:22: check 'ok' got status valid. +[eva] tests/libc/wchar_h.c:24: Call to builtin wmemchr +[eva:alarm] tests/libc/wchar_h.c:24: Warning: + function wmemchr: precondition 'valid' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:24: Warning: + function wmemchr: precondition 'initialization' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:24: Warning: + function wmemchr: precondition 'danglingness' got status unknown. +[eva] tests/libc/wchar_h.c:25: check 'ok' got status valid. +[eva] tests/libc/wchar_h.c:26: Call to builtin wmemchr +[eva:alarm] tests/libc/wchar_h.c:26: Warning: + function wmemchr: precondition 'valid' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:26: Warning: + function wmemchr: precondition 'initialization' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:26: Warning: + function wmemchr: precondition 'danglingness' got status unknown. +[eva] tests/libc/wchar_h.c:27: check 'ok' got status valid. +[eva] tests/libc/wchar_h.c:29: Call to builtin wmemchr +[eva:alarm] tests/libc/wchar_h.c:29: Warning: + function wmemchr: precondition 'valid' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:29: Warning: + function wmemchr: precondition 'initialization' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:29: Warning: + function wmemchr: precondition 'danglingness' got status unknown. +[eva] tests/libc/wchar_h.c:30: check 'ok' got status valid. +[eva] computing for function wcsncpy <- main. + Called from tests/libc/wchar_h.c:33. +[eva] using specification for function wcsncpy +[eva] tests/libc/wchar_h.c:33: + function wcsncpy: precondition 'valid_wstring_src' got status valid. +[eva] tests/libc/wchar_h.c:33: + function wcsncpy: precondition 'room_nwstring' got status valid. +[eva] tests/libc/wchar_h.c:33: + function wcsncpy: precondition 'separation,dest,src' got status valid. +[eva] Done for function wcsncpy +[eva] tests/libc/wchar_h.c:34: check 'ok' got status valid. +[eva] tests/libc/wchar_h.c:35: check 'ok' got status valid. +[eva] tests/libc/wchar_h.c:37: Call to builtin wcslen +[eva] tests/libc/wchar_h.c:37: + function wcslen: precondition 'valid_string_s' got status valid. +[eva] computing for function wcsncpy <- main. + Called from tests/libc/wchar_h.c:37. +[eva] tests/libc/wchar_h.c:37: + function wcsncpy: precondition 'valid_wstring_src' got status valid. +[eva:alarm] tests/libc/wchar_h.c:37: Warning: + function wcsncpy: precondition 'room_nwstring' got status invalid. +[eva] tests/libc/wchar_h.c:37: + function wcsncpy: no state left, precondition 'separation,dest,src' got status valid. +[eva] Done for function wcsncpy +[eva] computing for function wcsncpy <- main. + Called from tests/libc/wchar_h.c:41. +[eva:alarm] tests/libc/wchar_h.c:41: Warning: + function wcsncpy: precondition 'valid_wstring_src' got status unknown. +[eva] tests/libc/wchar_h.c:41: + function wcsncpy: precondition 'room_nwstring' got status valid. +[eva:alarm] tests/libc/wchar_h.c:41: Warning: + function wcsncpy: precondition 'separation,dest,src' got status invalid. +[eva] Done for function wcsncpy +[eva] computing for function wcsncpy <- main. + Called from tests/libc/wchar_h.c:45. +[eva] tests/libc/wchar_h.c:45: + function wcsncpy: precondition 'valid_wstring_src' got status valid. +[eva:alarm] tests/libc/wchar_h.c:45: Warning: + function wcsncpy: precondition 'room_nwstring' got status invalid. +[eva] tests/libc/wchar_h.c:45: + function wcsncpy: no state left, precondition 'separation,dest,src' got status valid. +[eva] Done for function wcsncpy +[eva] computing for function wcsncpy <- main. + Called from tests/libc/wchar_h.c:49. +[eva:alarm] tests/libc/wchar_h.c:49: Warning: + function wcsncpy: precondition 'valid_wstring_src' got status invalid. +[eva] tests/libc/wchar_h.c:49: + function wcsncpy: no state left, precondition 'room_nwstring' got status valid. +[eva] tests/libc/wchar_h.c:49: + function wcsncpy: no state left, precondition 'separation,dest,src' got status valid. +[eva] Done for function wcsncpy +[eva] computing for function wcsncpy <- main. + Called from tests/libc/wchar_h.c:53. +[eva:alarm] tests/libc/wchar_h.c:53: Warning: + function wcsncpy: precondition 'valid_wstring_src' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:53: Warning: + function wcsncpy: precondition 'room_nwstring' got status invalid. +[eva] tests/libc/wchar_h.c:53: + function wcsncpy: no state left, precondition 'separation,dest,src' got status valid. +[eva] Done for function wcsncpy +[eva] computing for function wcsncmp <- main. + Called from tests/libc/wchar_h.c:56. +[eva] using specification for function wcsncmp +[eva] tests/libc/wchar_h.c:56: + function wcsncmp: precondition 'valid_wstring_s1' got status valid. +[eva] tests/libc/wchar_h.c:56: + function wcsncmp: precondition 'valid_wstring_s2' got status valid. +[eva] Done for function wcsncmp +[eva] computing for function wcsncmp <- main. + Called from tests/libc/wchar_h.c:57. +[eva] tests/libc/wchar_h.c:57: + function wcsncmp: precondition 'valid_wstring_s1' got status valid. +[eva:alarm] tests/libc/wchar_h.c:57: Warning: + function wcsncmp: precondition 'valid_wstring_s2' got status unknown. +[eva] Done for function wcsncmp +[eva] computing for function wcsncat <- main. + Called from tests/libc/wchar_h.c:59. +[eva] using specification for function wcsncat +[eva] tests/libc/wchar_h.c:59: + function wcsncat: precondition 'valid_nwstring_src' got status valid. +[eva] tests/libc/wchar_h.c:59: + function wcsncat: precondition 'valid_wstring_dest' got status valid. +[eva] tests/libc/wchar_h.c:59: + function wcsncat: precondition 'room_for_concatenation' got status valid. +[eva] tests/libc/wchar_h.c:59: + function wcsncat: precondition 'separation' got status valid. +[eva] Done for function wcsncat +[eva] computing for function wcsncat <- main. + Called from tests/libc/wchar_h.c:60. +[eva] tests/libc/wchar_h.c:60: + function wcsncat: precondition 'valid_nwstring_src' got status valid. +[eva:alarm] tests/libc/wchar_h.c:60: Warning: + function wcsncat: precondition 'valid_wstring_dest' got status unknown. +[eva:alarm] tests/libc/wchar_h.c:60: Warning: + function wcsncat: precondition 'room_for_concatenation' got status unknown. +[eva] tests/libc/wchar_h.c:60: + function wcsncat: precondition 'separation' got status valid. +[eva] Done for function wcsncat +[eva] computing for function wcsncat <- main. + Called from tests/libc/wchar_h.c:66. +[eva] tests/libc/wchar_h.c:66: + function wcsncat: precondition 'valid_nwstring_src' got status valid. +[eva] tests/libc/wchar_h.c:66: + function wcsncat: precondition 'valid_wstring_dest' got status valid. +[eva:alarm] tests/libc/wchar_h.c:66: Warning: + function wcsncat: precondition 'room_for_concatenation' got status invalid. +[eva] tests/libc/wchar_h.c:66: + function wcsncat: no state left, precondition 'separation' got status valid. +[eva] Done for function wcsncat [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: fd ∈ {{ NULL ; &__fc_fopen + [0..120],0%8 }} - buf[0..29] ∈ [--..--] or UNINITIALIZED + buf[0..28] ∈ [--..--] or UNINITIALIZED + [29] ∈ UNINITIALIZED res ∈ {{ NULL ; &buf[0] }} + buf2[0] ∈ {97} or UNINITIALIZED + [1] ∈ {98} or UNINITIALIZED + r ∈ {{ &wdst[0] }} + wsrc ∈ {{ L"wide thing" }} + wdst[0..9] ∈ [--..--] or UNINITIALIZED + wdst2[0..9] ∈ {65} + [10] ∈ {0} + [11..19] ∈ [--..--] __retres ∈ {0; 1} diff --git a/tests/libc/stdio_h.c b/tests/libc/stdio_h.c index 9e9ac6ba242de5f7bb922d965b18eed6b3393c80..a1d6f3fa161b6d6edc7ac04fd41056285eea2f00 100644 --- a/tests/libc/stdio_h.c +++ b/tests/libc/stdio_h.c @@ -29,5 +29,15 @@ int main() { if (!redirected) return 3; printf("redirected to file"); fclose(redirected); + + char fgets_buf0[1]; + char *fgets_res = fgets(fgets_buf0, 1, f); // ok + if (!fgets_res) return 1; + //@ check \initialized(&fgets_buf0[0]); + if (nondet) { + fgets(fgets_buf0, 2, f); // error: buf too small + //@ assert unreachable: \false; + } + return 0; } diff --git a/tests/libc/sys_time.c b/tests/libc/sys_time_h.c similarity index 74% rename from tests/libc/sys_time.c rename to tests/libc/sys_time_h.c index 51808be30647c078a6b23b1813df9e5a1b4b9346..2ec5bcf485a068132a17e9885092ab322067fcfe 100644 --- a/tests/libc/sys_time.c +++ b/tests/libc/sys_time_h.c @@ -18,5 +18,14 @@ int main() { i2.it_interval.tv_usec = 1000000; // invalid tv_usec res = setitimer(ITIMER_VIRTUAL, &i2, &i1); //@ assert res == -1; + + int r1 = utimes("/tmp/utimes", 0); + struct timeval tv[2] = + { + { .tv_sec = 10000000, .tv_usec = 999999 }, + { .tv_sec = -9000000, .tv_usec = 1 }, + }; + int r2 = utimes("/tmp/utimes", tv); + return 0; } diff --git a/tests/libc/unistd_h.c b/tests/libc/unistd_h.c index b625b3b83d2d10e57806e83a9bf73d7521d08134..8c3104215bf71005b84e6d834a103ebe75056110 100644 --- a/tests/libc/unistd_h.c +++ b/tests/libc/unistd_h.c @@ -91,5 +91,18 @@ int main() { r = chroot("/tmp"); + if (nondet) { + pipe(0); // invalid fildes + //@ assert unreachable:\false; + } + int halfpipe; + if (nondet) { + pipe(&halfpipe); // invalid fildes + //@ assert unreachable:\false; + } + int pipefd[2]; + r = pipe(pipefd); + //@ check ok: r == 0 || r == -1; + return 0; } diff --git a/tests/libc/wchar_h.c b/tests/libc/wchar_h.c index c10e733da9168c3ffb7537e5c97faf20d8727105..e7cb493fa75d8adf0b06af406ebdf64c38dd3463 100644 --- a/tests/libc/wchar_h.c +++ b/tests/libc/wchar_h.c @@ -1,6 +1,6 @@ #include <stdio.h> #include <wchar.h> - +volatile int v; int main() { FILE *fd = fopen("bla", "r"); if (!fd) return 1; @@ -8,5 +8,63 @@ int main() { wchar_t *res = fgetws(buf, 29, fd); if (!res) return 1; //@ assert res == buf; + wchar_t buf2[2]; + buf2[0] = L'a'; + wchar_t *r = wmemchr(buf2, L'a', 2); // no warning + //@ check ok: r != \null; + r = wmemchr(0, 0, 0); // should be ok + //@ check ok: r == \null; + if (v) { + r = wmemchr(buf2, 0, 2); // red alarm (uninit) + //@ assert unreachable:\false; + } + r = wmemchr(buf2, L'a', 3); // no warning + //@ check ok: r != \null; + if (v) buf2[1] = L'b'; + r = wmemchr(buf2, L'a', 3); // no warning + //@ check ok: r != \null; + r = wmemchr(buf2, L'b', 3); // warning: buf2[1] maybe uninit + //@ check ok: r != \null; + buf2[1] = L'b'; + r = wmemchr(buf2, L'b', 3); // no warning + //@ check ok: r != \null; + wchar_t *wsrc = L"wide thing"; + wchar_t wdst[10]; + r = wcsncpy(wdst, wsrc, 10); // no warning + //@ check ok: r == wdst; + //@ check ok: \initialized(&wdst[9]); + if (v) { + r = wcsncpy(wdst, wsrc, wcslen(wsrc)+1); // error: not enough room + //@ assert unreachable:\false; + } + if (v) { + wcsncpy(wdst, wdst, 10); // error: no separation + //@ assert unreachable:\false; + } + if (v) { + wcsncpy(0, wsrc, 10); // error: invalid dest + //@ assert unreachable:\false; + } + if (v) { + wcsncpy(wdst, 0, 10); // error: invalid src + //@ assert unreachable:\false; + } + if (v) { + wcsncpy(wsrc, wdst, 10); // error: non-writable dest + //@ assert unreachable:\false; + } + wcsncmp(wsrc, wsrc, 11); // no warning + wcsncmp(wsrc, wdst, 11); // warning: wdst possibly invalid + wchar_t wdst2[20] = {0}; + wcsncat(wdst2, wsrc, 11); // no warning + wcsncat(wdst2, wsrc, 10); // no warning (if wdst2 is precise) + //@ loop unroll 10; + for (int i = 0; i < 10; i++) + wdst2[i] = L'A'; + wdst2[10] = L'\0'; // wdst2 now has length 10 + if (v) { + wcsncat(wdst2+10, wdst2, 10); // error: no separation + //@ assert unreachable:\false; + } return 0; } diff --git a/tests/metrics/oracle/func_ptr.0.res.oracle b/tests/metrics/oracle/func_ptr.0.res.oracle index 428986010691df4429d28efc6da6ca2e449b53bb..0a380c923213a518b44cc5ab6df690031a0bcdcb 100644 --- a/tests/metrics/oracle/func_ptr.0.res.oracle +++ b/tests/metrics/oracle/func_ptr.0.res.oracle @@ -48,7 +48,7 @@ [eva] done for function main [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 8): 12% coverage. + 1 function analyzed (out of 4): 25% coverage. In this function, 6 statements reached (out of 13): 46% coverage. ---------------------------------------------------------------------------- Some errors and warnings have been raised during the analysis: diff --git a/tests/metrics/oracle/func_ptr.1.res.oracle b/tests/metrics/oracle/func_ptr.1.res.oracle index 703415595918a67d1441bee0b6d26d1cef1dddd4..b44df54a2fe98e9eaaf8914d44887efdcafcf7d7 100644 --- a/tests/metrics/oracle/func_ptr.1.res.oracle +++ b/tests/metrics/oracle/func_ptr.1.res.oracle @@ -48,7 +48,7 @@ [eva] done for function foobar [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 2 functions analyzed (out of 2): 100% coverage. + 2 functions analyzed (out of 4): 50% coverage. In these functions, 5 statements reached (out of 5): 100% coverage. ---------------------------------------------------------------------------- Some errors and warnings have been raised during the analysis: diff --git a/tests/metrics/oracle/libc.0.res.oracle b/tests/metrics/oracle/libc.0.res.oracle index 76a9cd7cd795af18278d1e949a4e6407dcbec6a9..c3bb5a741d5ae3a77120a0d2459ee3498e48cef0 100644 --- a/tests/metrics/oracle/libc.0.res.oracle +++ b/tests/metrics/oracle/libc.0.res.oracle @@ -40,7 +40,7 @@ [eva] done for function main [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 4 functions analyzed (out of 4): 100% coverage. + 4 functions analyzed (out of 5): 80% coverage. In these functions, 10 statements reached (out of 10): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/metrics/oracle/libc.1.res.oracle b/tests/metrics/oracle/libc.1.res.oracle index 8c8f0e6b9987c0efcc1d96fb117a3d40096d755c..24cfd8d35b1ec774597df2d92db5dcd32f240b4b 100644 --- a/tests/metrics/oracle/libc.1.res.oracle +++ b/tests/metrics/oracle/libc.1.res.oracle @@ -53,7 +53,7 @@ ============== Sloc = 17 Decision point = 0 - Global variables = 15 + Global variables = 17 If = 0 Loop = 0 Goto = 0 @@ -73,7 +73,7 @@ [eva] done for function main [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 4 functions analyzed (out of 4): 100% coverage. + 4 functions analyzed (out of 5): 80% coverage. In these functions, 10 statements reached (out of 10): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/metrics/oracle/reach.res.oracle b/tests/metrics/oracle/reach.res.oracle index e568528660bde94fa24656908310b1b9822a4dd9..76558191ccef8ba929bce7f1571de2c98c5c21f7 100644 --- a/tests/metrics/oracle/reach.res.oracle +++ b/tests/metrics/oracle/reach.res.oracle @@ -85,7 +85,7 @@ [eva] done for function main [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 6): 16% coverage. + 1 function analyzed (out of 3): 33% coverage. In this function, 7 statements reached (out of 12): 58% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/metrics/oracle/unreachable.res.oracle b/tests/metrics/oracle/unreachable.res.oracle index f542548237b0d0a7f7567f3951bbb2da54de561c..38770a200d191a2cfe6964fe6a343e78ba57eef8 100644 --- a/tests/metrics/oracle/unreachable.res.oracle +++ b/tests/metrics/oracle/unreachable.res.oracle @@ -37,7 +37,7 @@ [eva] done for function main [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 5): 20% coverage. + 1 function analyzed (out of 2): 50% coverage. In this function, 6 statements reached (out of 10): 60% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. @@ -69,7 +69,7 @@ [eva] done for function foo [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. + 1 function analyzed (out of 2): 50% coverage. In this function, 2 statements reached (out of 2): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. 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/misc/custom_machdep/__fc_machdep_custom.h b/tests/misc/custom_machdep/__fc_machdep_custom.h index fff2b8698abe93f750aeb65fe8ad3506a2a06396..27db308403368e394b64d739b9ac7e2c9699f936 100644 --- a/tests/misc/custom_machdep/__fc_machdep_custom.h +++ b/tests/misc/custom_machdep/__fc_machdep_custom.h @@ -74,6 +74,8 @@ /* POSIX */ #define __SSIZE_T int +/* stdio.h */ +#define __FC_L_tmpnam 1024 /* stdint.h */ #define __FC_PTRDIFF_MIN __FC_INT_MIN #define __FC_PTRDIFF_MAX __FC_INT_MAX diff --git a/tests/misc/interpreted_automata_dataflow.i b/tests/misc/interpreted_automata_dataflow.i new file mode 100644 index 0000000000000000000000000000000000000000..9446609755e0db82db642ed1331e1ec2ae8e9b6e --- /dev/null +++ b/tests/misc/interpreted_automata_dataflow.i @@ -0,0 +1,26 @@ +/* run.config +OPT: -load-script tests/misc/interpreted_automata_dataflow.ml +*/ + +/* Tests the dataflow functor of interpreted automata via a caml script + implementing a propagation of constants. */ + +void main(int x) +{ + int y = 3; + y = y * 2; + + int z = y + 1; + int w = y + x; + int a = 1; + + for (int i = 0 ; i < 10 ; i ++) { + int b = 3; + int c = i + 1; + a = a + 1; + } + + if (x != 3) + x = 3; +} + diff --git a/tests/misc/interpreted_automata_dataflow.ml b/tests/misc/interpreted_automata_dataflow.ml new file mode 100644 index 0000000000000000000000000000000000000000..04843ba93f65bdc060783952b279b25231942995 --- /dev/null +++ b/tests/misc/interpreted_automata_dataflow.ml @@ -0,0 +1,115 @@ +open Cil_types + +module Map = Cil_datatype.Varinfo.Map + +module ConstantsDomain = +struct + type t = int Map.t + + let top = Map.empty + + let pretty fmt v = + let pp_entry vi x = + Format.fprintf fmt "%s -> %d@." vi.vorig_name x + in + Map.iter pp_entry v + + let join v1 v2 = + let merge_entry _vi o1 o2 = + match o1, o2 with + | None, _ | _, None -> None + | Some x, Some x' -> if x = x' then Some x else None + in + Map.merge merge_entry v1 v2 + + let widen v1 v2 = + let same_entry vi x = + Map.find_opt vi v2 = Some x + in + if Map.for_all same_entry v1 then + None (* Inclusion *) + else + Some v2 (* No widening necessary *) + + exception Not_constant + + let rec eval v exp = + match exp.enode with + | Const (CInt64 (i,_,_)) -> + (try Integer.to_int i with _ -> raise Not_constant) + | Lval (Var vi, NoOffset) -> + (try Map.find vi v with Not_found -> raise Not_constant) + | SizeOf typ -> + Cil.bytesSizeOf typ + | UnOp (Neg, e, _) -> + -(eval v e) + | BinOp (PlusA, e1, e2, _) -> + (eval v e1) + (eval v e2) + | BinOp (MinusA, e1, e2, _) -> + (eval v e1) - (eval v e2) + | BinOp (Mult, e1, e2, _) -> + (eval v e1) * (eval v e2) + | BinOp (Div, e1, e2, _) -> + let x = eval v e2 in + if x <> 0 then (eval v e1) / x else raise Not_constant + | _ -> + raise Not_constant + + let eval_opt v exp = + try Some (eval v exp) with Not_constant -> None + + let assume v exp kind = + match exp.enode, kind with + | BinOp (Eq, e1, e2, _), Interpreted_automata.Then + | BinOp (Ne, e1, e2, _), Interpreted_automata.Else -> + begin match eval_opt v e1, eval_opt v e2 with + | None, None -> Some v + | Some x, None -> + begin match e2.enode with + | Lval (Var vi, NoOffset) -> Some (Map.add vi x v) + | _ -> Some v + end + | None, Some x -> + begin match e1.enode with + | Lval (Var vi, NoOffset) -> Some (Map.add vi x v) + | _ -> Some v + end + | Some x, Some y -> + if x = y then Some v else None + end + | _ -> Some v + + let assign v vi exp = + try + Map.add vi (eval v exp) v + with Not_constant -> + Map.remove vi v + + let transfer t v = + let open Interpreted_automata in + match t with + | Skip | Return _ | Prop _ | Enter _ | Leave _ -> Some v + | Guard (exp, kind, _) -> assume v exp kind + | Instr (Set ((Var vi, NoOffset), exp, _), _) -> Some (assign v vi exp) + | Instr (Local_init (vi, AssignInit (SingleInit exp), _), _) -> + Some (assign v vi exp) + | Instr (Local_init (_vi, AssignInit (CompoundInit _), _), _) -> Some v + | Instr ((Call _ | Local_init _ | Set _ | Asm _), _) -> Some top + | Instr ((Cil_types.Skip _ | Code_annot _), _) -> Some v +end + + +module Dataflow = Interpreted_automata.Dataflow (ConstantsDomain) + +let run () = + let main_kf, _ = Globals.entry_point () in + let results = Dataflow.fixpoint main_kf ConstantsDomain.top in + let result = Interpreted_automata.( + Vertex.Hashtbl.find results (get_automaton main_kf).return_point) + in + Kernel.result "Results at the end of function %s:@.%a" + (Kernel_function.get_name main_kf) + ConstantsDomain.pretty result + +let () = + Db.Main.extend run diff --git a/tests/misc/oracle/bts1201.res.oracle b/tests/misc/oracle/bts1201.res.oracle index bf9968e480cc7fb94343c74c0e71eb5a44bef38d..b15cb77c71ad3712d598439a18afb2b5be94afb6 100644 --- a/tests/misc/oracle/bts1201.res.oracle +++ b/tests/misc/oracle/bts1201.res.oracle @@ -8,7 +8,7 @@ [eva] done for function main [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. + 1 function analyzed (out of 2): 50% coverage. In this function, 2 statements reached (out of 2): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. @@ -28,7 +28,7 @@ [eva] done for function main2 [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. + 1 function analyzed (out of 2): 50% coverage. In this function, 1 statements reached (out of 1): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/misc/oracle/interpreted_automata_dataflow.res.oracle b/tests/misc/oracle/interpreted_automata_dataflow.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..75741cada58b18ee94e100a57b6256d8121c8c7f --- /dev/null +++ b/tests/misc/oracle/interpreted_automata_dataflow.res.oracle @@ -0,0 +1,5 @@ +[kernel] Parsing tests/misc/interpreted_automata_dataflow.i (no preprocessing) +[kernel] Results at the end of function main: + x -> 3 + y -> 6 + z -> 7 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/rte/oracle/value_rte.res.oracle b/tests/rte/oracle/value_rte.res.oracle index fe5023c92a121cd742479c4988f5163e4386ec40..2cf4947a7f1281fb2a53427ea27d2d494282ebd9 100644 --- a/tests/rte/oracle/value_rte.res.oracle +++ b/tests/rte/oracle/value_rte.res.oracle @@ -43,6 +43,7 @@ cpt ∈ {0; 1; 2; 3; 4} tmp ∈ [-2147483648..4] __retres ∈ {1} + S___fc_stdin[0..1] ∈ [--..--] [report] Computing properties status... -------------------------------------------------------------------------------- --- Global Properties @@ -114,6 +115,10 @@ Unverifiable but considered Valid. [ Extern ] Axiom 'wcsncmp_zero' Unverifiable but considered Valid. +[ Extern ] Axiom 'wmemchr_def' + Unverifiable but considered Valid. +[ Valid ] Axiomatic 'GetsLength' + by Frama-C kernel. [ Valid ] Axiomatic 'MemChr' by Frama-C kernel. [ Valid ] Axiomatic 'MemCmp' @@ -128,6 +133,8 @@ by Frama-C kernel. [ Valid ] Axiomatic 'StrNCmp' by Frama-C kernel. +[ Valid ] Axiomatic 'WMemChr' + by Frama-C kernel. [ Valid ] Axiomatic 'WcsChr' by Frama-C kernel. [ Valid ] Axiomatic 'WcsCmp' @@ -145,8 +152,12 @@ --- Properties of Function 'remove' -------------------------------------------------------------------------------- +[ Extern ] Post-condition 'result_ok_or_error' + Unverifiable but considered Valid. [ Extern ] Assigns nothing Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 76) + Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -154,8 +165,12 @@ --- Properties of Function 'rename' -------------------------------------------------------------------------------- +[ Extern ] Post-condition 'result_ok_or_error' + Unverifiable but considered Valid. [ Extern ] Assigns nothing Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 85) + Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -167,7 +182,7 @@ Unverifiable but considered Valid. [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 80) +[ Extern ] Froms (file share/libc/stdio.h, line 95) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -176,11 +191,15 @@ --- Properties of Function 'tmpnam' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 87) +[ Extern ] Post-condition 'result_string_or_null' + Unverifiable but considered Valid. +[ Extern ] Assigns (file share/libc/stdio.h, line 109) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 87) +[ Extern ] Froms (file share/libc/stdio.h, line 109) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 88) +[ Extern ] Froms (file share/libc/stdio.h, line 111) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 112) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -193,7 +212,7 @@ Unverifiable but considered Valid. [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 95) +[ Extern ] Froms (file share/libc/stdio.h, line 121) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -204,12 +223,32 @@ [ Extern ] Post-condition 'result_zero_or_EOF' Unverifiable but considered Valid. -[ Extern ] Assigns nothing +[ Extern ] Assigns (file share/libc/stdio.h, line 130) + Unverifiable but considered Valid. +[ Extern ] Assigns for 'flush_all' (file share/libc/stdio.h, line 137) + Unverifiable but considered Valid. +[ Extern ] Assigns for 'flush_stream' (file share/libc/stdio.h, line 142) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 130) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 132) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 132) + Unverifiable but considered Valid. +[ Extern ] Froms for 'flush_all' (file share/libc/stdio.h, line 137) + Unverifiable but considered Valid. +[ Extern ] Froms for 'flush_all' (file share/libc/stdio.h, line 139) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 103) +[ Extern ] Froms for 'flush_stream' (file share/libc/stdio.h, line 142) + Unverifiable but considered Valid. +[ Extern ] Froms for 'flush_stream' (file share/libc/stdio.h, line 143) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. +[ Valid ] Behavior 'flush_all' + by Frama-C kernel. +[ Valid ] Behavior 'flush_stream' + by Frama-C kernel. -------------------------------------------------------------------------------- --- Properties of Function 'fopen' @@ -219,7 +258,7 @@ Unverifiable but considered Valid. [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 112) +[ Extern ] Froms (file share/libc/stdio.h, line 152) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -230,11 +269,11 @@ [ Extern ] Post-condition 'result_null_or_valid_fd' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 121) +[ Extern ] Assigns (file share/libc/stdio.h, line 162) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 121) +[ Extern ] Froms (file share/libc/stdio.h, line 162) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 121) +[ Extern ] Froms (file share/libc/stdio.h, line 162) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -247,11 +286,11 @@ Unverifiable but considered Valid. [ Extern ] Post-condition 'stream_opened' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 132) +[ Extern ] Assigns (file share/libc/stdio.h, line 174) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 132) +[ Extern ] Froms (file share/libc/stdio.h, line 174) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 134) +[ Extern ] Froms (file share/libc/stdio.h, line 176) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -260,9 +299,9 @@ --- Properties of Function 'setbuf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 145) +[ Extern ] Assigns (file share/libc/stdio.h, line 187) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 145) +[ Extern ] Froms (file share/libc/stdio.h, line 187) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -271,9 +310,9 @@ --- Properties of Function 'setvbuf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 149) +[ Extern ] Assigns (file share/libc/stdio.h, line 191) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 149) +[ Extern ] Froms (file share/libc/stdio.h, line 191) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -282,9 +321,9 @@ --- Properties of Function 'vfprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 178) +[ Extern ] Assigns (file share/libc/stdio.h, line 220) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 178) +[ Extern ] Froms (file share/libc/stdio.h, line 220) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -293,9 +332,9 @@ --- Properties of Function 'vfscanf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 183) +[ Extern ] Assigns (file share/libc/stdio.h, line 225) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 183) +[ Extern ] Froms (file share/libc/stdio.h, line 225) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -304,9 +343,9 @@ --- Properties of Function 'vprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 189) +[ Extern ] Assigns (file share/libc/stdio.h, line 231) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 189) +[ Extern ] Froms (file share/libc/stdio.h, line 231) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -315,9 +354,9 @@ --- Properties of Function 'vscanf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 193) +[ Extern ] Assigns (file share/libc/stdio.h, line 235) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 193) +[ Extern ] Froms (file share/libc/stdio.h, line 235) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -326,9 +365,9 @@ --- Properties of Function 'vsnprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 198) +[ Extern ] Assigns (file share/libc/stdio.h, line 240) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 198) +[ Extern ] Froms (file share/libc/stdio.h, line 240) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -337,9 +376,9 @@ --- Properties of Function 'vsprintf' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 204) +[ Extern ] Assigns (file share/libc/stdio.h, line 246) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 204) +[ Extern ] Froms (file share/libc/stdio.h, line 246) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -350,11 +389,11 @@ [ Extern ] Post-condition 'result_uchar_or_eof' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 217) +[ Extern ] Assigns (file share/libc/stdio.h, line 259) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 217) +[ Extern ] Froms (file share/libc/stdio.h, line 259) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 218) +[ Extern ] Froms (file share/libc/stdio.h, line 260) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -365,13 +404,15 @@ [ Extern ] Post-condition 'result_null_or_same' Unverifiable but considered Valid. +[ Extern ] Post-condition 'initialization,at_least_one' + Unverifiable but considered Valid. [ Extern ] Post-condition 'terminated_string_on_success' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 225) +[ Extern ] Assigns (file share/libc/stdio.h, line 268) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 225) +[ Extern ] Froms (file share/libc/stdio.h, line 268) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 226) +[ Extern ] Froms (file share/libc/stdio.h, line 269) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -380,7 +421,11 @@ --- Properties of Function 'fputc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 234) +[ Extern ] Assigns (file share/libc/stdio.h, line 282) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 282) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 283) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -389,9 +434,11 @@ --- Properties of Function 'fputs' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 237) +[ Extern ] Assigns (file share/libc/stdio.h, line 289) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 237) +[ Extern ] Froms (file share/libc/stdio.h, line 289) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 290) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -400,11 +447,11 @@ --- Properties of Function 'getc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 241) +[ Extern ] Assigns (file share/libc/stdio.h, line 297) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 241) +[ Extern ] Froms (file share/libc/stdio.h, line 297) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 241) +[ Extern ] Froms (file share/libc/stdio.h, line 297) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -413,9 +460,11 @@ --- Properties of Function 'getchar' -------------------------------------------------------------------------------- -[ Extern ] Assigns nothing +[ Extern ] Assigns (file share/libc/stdio.h, line 302) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 302) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 244) +[ Extern ] Froms (file share/libc/stdio.h, line 302) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -426,11 +475,13 @@ [ Extern ] Post-condition 'result_null_or_same' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 248) +[ Extern ] Assigns (file share/libc/stdio.h, line 315) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 248) +[ Extern ] Froms (file share/libc/stdio.h, line 315) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 249) +[ Extern ] Froms (file share/libc/stdio.h, line 316) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 317) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -439,9 +490,11 @@ --- Properties of Function 'putc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 254) +[ Extern ] Assigns (file share/libc/stdio.h, line 324) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 254) +[ Extern ] Froms (file share/libc/stdio.h, line 324) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 325) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -450,9 +503,11 @@ --- Properties of Function 'putchar' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 257) +[ Extern ] Assigns (file share/libc/stdio.h, line 330) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 330) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 257) +[ Extern ] Froms (file share/libc/stdio.h, line 331) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -461,9 +516,11 @@ --- Properties of Function 'puts' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 260) +[ Extern ] Assigns (file share/libc/stdio.h, line 337) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 260) +[ Extern ] Froms (file share/libc/stdio.h, line 337) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 338) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -472,9 +529,13 @@ --- Properties of Function 'ungetc' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 263) +[ Extern ] Post-condition 'result_ok_or_error' + Unverifiable but considered Valid. +[ Extern ] Assigns (file share/libc/stdio.h, line 344) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 263) +[ Extern ] Froms (file share/libc/stdio.h, line 344) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 345) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -487,11 +548,13 @@ Unverifiable but considered Valid. [ Extern ] Post-condition 'initialization' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 269) +[ Extern ] Assigns (file share/libc/stdio.h, line 353) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 269) +[ Extern ] Froms (file share/libc/stdio.h, line 353) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 270) +[ Extern ] Froms (file share/libc/stdio.h, line 353) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 355) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -502,11 +565,11 @@ [ Extern ] Post-condition 'size_written' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 282) +[ Extern ] Assigns (file share/libc/stdio.h, line 366) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 282) +[ Extern ] Froms (file share/libc/stdio.h, line 366) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 282) +[ Extern ] Froms (file share/libc/stdio.h, line 366) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -515,9 +578,11 @@ --- Properties of Function 'fgetpos' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 290) +[ Extern ] Assigns (file share/libc/stdio.h, line 377) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 290) +[ Extern ] Froms (file share/libc/stdio.h, line 377) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 378) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -526,13 +591,13 @@ --- Properties of Function 'fseek' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 297) +[ Extern ] Assigns (file share/libc/stdio.h, line 386) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 297) +[ Extern ] Froms (file share/libc/stdio.h, line 386) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 298) +[ Extern ] Froms (file share/libc/stdio.h, line 387) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 298) +[ Extern ] Froms (file share/libc/stdio.h, line 387) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -541,9 +606,9 @@ --- Properties of Function 'fsetpos' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 303) +[ Extern ] Assigns (file share/libc/stdio.h, line 396) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 303) +[ Extern ] Froms (file share/libc/stdio.h, line 396) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -554,11 +619,11 @@ [ Extern ] Post-condition 'success_or_error' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 308) +[ Extern ] Assigns (file share/libc/stdio.h, line 402) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 308) +[ Extern ] Froms (file share/libc/stdio.h, line 402) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 308) +[ Extern ] Froms (file share/libc/stdio.h, line 402) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -567,9 +632,9 @@ --- Properties of Function 'rewind' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 314) +[ Extern ] Assigns (file share/libc/stdio.h, line 410) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 314) +[ Extern ] Froms (file share/libc/stdio.h, line 410) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -578,9 +643,9 @@ --- Properties of Function 'clearerr' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 317) +[ Extern ] Assigns (file share/libc/stdio.h, line 416) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 317) +[ Extern ] Froms (file share/libc/stdio.h, line 416) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -591,7 +656,7 @@ [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 320) +[ Extern ] Froms (file share/libc/stdio.h, line 422) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -602,7 +667,7 @@ [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 323) +[ Extern ] Froms (file share/libc/stdio.h, line 428) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -611,9 +676,9 @@ --- Properties of Function 'flockfile' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 326) +[ Extern ] Assigns (file share/libc/stdio.h, line 434) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 326) +[ Extern ] Froms (file share/libc/stdio.h, line 434) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -622,9 +687,9 @@ --- Properties of Function 'funlockfile' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 329) +[ Extern ] Assigns (file share/libc/stdio.h, line 440) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 329) +[ Extern ] Froms (file share/libc/stdio.h, line 440) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -633,11 +698,11 @@ --- Properties of Function 'ftrylockfile' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 332) +[ Extern ] Assigns (file share/libc/stdio.h, line 446) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 332) +[ Extern ] Froms (file share/libc/stdio.h, line 446) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 332) +[ Extern ] Froms (file share/libc/stdio.h, line 446) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -648,7 +713,7 @@ [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 335) +[ Extern ] Froms (file share/libc/stdio.h, line 452) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -657,9 +722,9 @@ --- Properties of Function 'perror' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 338) +[ Extern ] Assigns (file share/libc/stdio.h, line 458) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 338) +[ Extern ] Froms (file share/libc/stdio.h, line 458) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -668,11 +733,11 @@ --- Properties of Function 'getc_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 341) +[ Extern ] Assigns (file share/libc/stdio.h, line 464) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 341) +[ Extern ] Froms (file share/libc/stdio.h, line 464) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 341) +[ Extern ] Froms (file share/libc/stdio.h, line 464) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -683,7 +748,7 @@ [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 343) +[ Extern ] Froms (file share/libc/stdio.h, line 469) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -692,9 +757,11 @@ --- Properties of Function 'putc_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 345) +[ Extern ] Assigns (file share/libc/stdio.h, line 475) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 345) +[ Extern ] Froms (file share/libc/stdio.h, line 475) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 476) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -703,9 +770,11 @@ --- Properties of Function 'putchar_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 347) +[ Extern ] Assigns (file share/libc/stdio.h, line 481) + Unverifiable but considered Valid. +[ Extern ] Froms (file share/libc/stdio.h, line 481) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 347) +[ Extern ] Froms (file share/libc/stdio.h, line 482) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -714,9 +783,9 @@ --- Properties of Function 'clearerr_unlocked' -------------------------------------------------------------------------------- -[ Extern ] Assigns (file share/libc/stdio.h, line 350) +[ Extern ] Assigns (file share/libc/stdio.h, line 488) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 350) +[ Extern ] Froms (file share/libc/stdio.h, line 488) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -727,7 +796,7 @@ [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 352) +[ Extern ] Froms (file share/libc/stdio.h, line 494) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -738,7 +807,7 @@ [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 354) +[ Extern ] Froms (file share/libc/stdio.h, line 500) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -749,7 +818,7 @@ [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 356) +[ Extern ] Froms (file share/libc/stdio.h, line 506) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -760,11 +829,11 @@ [ Extern ] Post-condition 'result_error_or_valid_open_pipe' Unverifiable but considered Valid. -[ Extern ] Assigns (file share/libc/stdio.h, line 381) +[ Extern ] Assigns (file share/libc/stdio.h, line 533) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 381) +[ Extern ] Froms (file share/libc/stdio.h, line 533) Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 383) +[ Extern ] Froms (file share/libc/stdio.h, line 535) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -777,7 +846,7 @@ Unverifiable but considered Valid. [ Extern ] Assigns nothing Unverifiable but considered Valid. -[ Extern ] Froms (file share/libc/stdio.h, line 395) +[ Extern ] Froms (file share/libc/stdio.h, line 547) Unverifiable but considered Valid. [ Valid ] Default behavior by Frama-C kernel. @@ -796,8 +865,8 @@ -------------------------------------------------------------------------------- --- Status Report Summary -------------------------------------------------------------------------------- - 68 Completely validated - 168 Considered valid + 72 Completely validated + 198 Considered valid 1 To be validated - 237 Total + 271 Total -------------------------------------------------------------------------------- diff --git a/tests/saveload/basic.i b/tests/saveload/basic.i index e08f72217afc5872f078df8e68ece4bf9bd9d130..1f733301b5c7942857df1515ef02528852f4a8bf 100644 --- a/tests/saveload/basic.i +++ b/tests/saveload/basic.i @@ -1,11 +1,11 @@ /* run.config EXECNOW: make -s @PTEST_DIR@/@PTEST_NAME@.cmxs - EXECNOW: LOG basic_sav.res LOG basic_sav.err BIN basic.sav @frama-c@ -load-module @PTEST_DIR@/@PTEST_NAME@.cmxs -eva -out -input -deps -eva-show-progress ./@PTEST_DIR@/@PTEST_NAME@.i -save ./tests/saveload/result/basic.sav > ./tests/saveload/result/basic_sav.res 2> ./tests/saveload/result/basic_sav.err - EXECNOW: LOG basic_sav.1.res LOG basic_sav.1.err BIN basic.1.sav ./bin/toplevel.opt -save ./tests/saveload/result/basic.1.sav @PTEST_DIR@/@PTEST_NAME@.i -eva -out -input -deps -eva-show-progress > ./tests/saveload/result/basic_sav.1.res 2> ./tests/saveload/result/basic_sav.1.err - STDOPT: +"-load ./tests/saveload/result/basic.sav -eva -out -input -deps -journal-disable" + EXECNOW: LOG basic_sav.res LOG basic_sav.err BIN basic.sav @frama-c@ -load-module @PTEST_DIR@/@PTEST_NAME@.cmxs -eva @EVA_OPTIONS@ -out -input -deps ./@PTEST_DIR@/@PTEST_NAME@.i -save ./tests/saveload/result/basic.sav > ./tests/saveload/result/basic_sav.res 2> ./tests/saveload/result/basic_sav.err + EXECNOW: LOG basic_sav.1.res LOG basic_sav.1.err BIN basic.1.sav ./bin/toplevel.opt -save ./tests/saveload/result/basic.1.sav @PTEST_DIR@/@PTEST_NAME@.i -eva @EVA_OPTIONS@ -out -input -deps > ./tests/saveload/result/basic_sav.1.res 2> ./tests/saveload/result/basic_sav.1.err + STDOPT: +"-load ./tests/saveload/result/basic.sav -eva @EVA_OPTIONS@ -out -input -deps -journal-disable" CMD: @frama-c@ -load-module @PTEST_DIR@/@PTEST_NAME@.cmxs - STDOPT: +"-load ./tests/saveload/result/basic.1.sav -eva -out -input -deps -journal-disable -print" - STDOPT: +"-load ./tests/saveload/result/basic.1.sav -eva -out -input -deps -journal-disable" + STDOPT: +"-load ./tests/saveload/result/basic.1.sav -eva @EVA_OPTIONS@ -out -input -deps -journal-disable -print" + STDOPT: +"-load ./tests/saveload/result/basic.1.sav -eva @EVA_OPTIONS@ -out -input -deps -journal-disable" EXECNOW: make -s @PTEST_DIR@/status.cmxs EXECNOW: LOG status_sav.res LOG status_sav.err BIN status.sav @frama-c@ -load-module @PTEST_DIR@/status -save ./tests/saveload/result/status.sav @PTEST_DIR@/@PTEST_NAME@.i > ./tests/saveload/result/status_sav.res 2> ./tests/saveload/result/status_sav.err STDOPT: +"-load-module @PTEST_DIR@/status -load ./tests/saveload/result/status.sav" diff --git a/tests/saveload/bool.c b/tests/saveload/bool.c index 5453ccfe23850403af7beb11fbc4ed95c3ce6534..5f757c7f0cf39a6306df9054d570f2ef8bb52c8f 100644 --- a/tests/saveload/bool.c +++ b/tests/saveload/bool.c @@ -1,7 +1,7 @@ /* run.config - EXECNOW: BIN bool.sav LOG bool_sav.res LOG bool_sav.err ./bin/toplevel.opt -save ./tests/saveload/result/bool.sav -eva -eva-show-progress ./tests/saveload/bool.c > tests/saveload/result/bool_sav.res 2> tests/saveload/result/bool_sav.err + EXECNOW: BIN bool.sav LOG bool_sav.res LOG bool_sav.err ./bin/toplevel.opt -save ./tests/saveload/result/bool.sav -eva @EVA_OPTIONS@ ./tests/saveload/bool.c > tests/saveload/result/bool_sav.res 2> tests/saveload/result/bool_sav.err STDOPT: +"-load ./tests/saveload/result/bool.sav -out -input -deps" - STDOPT: +"-load ./tests/saveload/result/bool.sav -eva" + STDOPT: +"-load ./tests/saveload/result/bool.sav -eva @EVA_OPTIONS@" */ #include "stdbool.h" diff --git a/tests/saveload/deps.i b/tests/saveload/deps.i index 1e7dddc3a3c06bda23bc341a1df1a8b95e3d7922..ee704399b403bbf61ee9da3eab241d193b7a9426 100644 --- a/tests/saveload/deps.i +++ b/tests/saveload/deps.i @@ -1,7 +1,7 @@ /* run.config EXECNOW: make -s ./tests/saveload/deps_A.cmxs ./tests/saveload/deps_B.cmxs ./tests/saveload/deps_C.cmxs ./tests/saveload/deps_D.cmxs ./tests/saveload/deps_E.cmxs - EXECNOW: LOG deps_sav.res LOG deps_sav.err BIN deps.sav @frama-c@ -load-module ./tests/saveload/deps_A.cmxs -eva -out -input -deps -eva-show-progress ./tests/saveload/deps.i -save ./tests/saveload/result/deps.sav > ./tests/saveload/result/deps_sav.res 2> ./tests/saveload/result/deps_sav.err - STDOPT: +"-load-module ./tests/saveload/deps_A -load ./tests/saveload/result/deps.sav -eva -out -input -deps " + EXECNOW: LOG deps_sav.res LOG deps_sav.err BIN deps.sav @frama-c@ -load-module ./tests/saveload/deps_A.cmxs -eva @EVA_OPTIONS@ -out -input -deps ./tests/saveload/deps.i -save ./tests/saveload/result/deps.sav > ./tests/saveload/result/deps_sav.res 2> ./tests/saveload/result/deps_sav.err + STDOPT: +"-load-module ./tests/saveload/deps_A -load ./tests/saveload/result/deps.sav -eva @EVA_OPTIONS@ -out -input -deps " STDOPT: +"-load-module ./tests/saveload/deps_B -load ./tests/saveload/result/deps.sav -out -input -deps " STDOPT: +"-load-module ./tests/saveload/deps_C -load ./tests/saveload/result/deps.sav -out -input -deps " STDOPT: +"-load-module ./tests/saveload/deps_D -load ./tests/saveload/result/deps.sav -out -input -deps " diff --git a/tests/saveload/isset.c b/tests/saveload/isset.c index e490c3405e835d7c65980bd84767a42dd5f47449..720c3d635f2f3bc362c24fe83422bf51766ddfa6 100644 --- a/tests/saveload/isset.c +++ b/tests/saveload/isset.c @@ -1,9 +1,9 @@ /* run.config - EXECNOW: LOG isset_sav.res LOG isset_sav.err BIN isset.sav ./bin/toplevel.opt -quiet -eva -save tests/saveload/result/isset.sav tests/saveload/isset.c > ./tests/saveload/result/isset_sav.res 2> ./tests/saveload/result/isset_sav.err + EXECNOW: LOG isset_sav.res LOG isset_sav.err BIN isset.sav ./bin/toplevel.opt -quiet -eva @EVA_OPTIONS@ -save tests/saveload/result/isset.sav tests/saveload/isset.c > ./tests/saveload/result/isset_sav.res 2> ./tests/saveload/result/isset_sav.err STDOPT: +"-quiet -load ./tests/saveload/result/isset.sav" STDOPT: +"-load ./tests/saveload/result/isset.sav" - STDOPT: +"-eva -load ./tests/saveload/result/isset.sav" - STDOPT: +"-quiet -eva -load ./tests/saveload/result/isset.sav" + STDOPT: +"-eva @EVA_OPTIONS@ -load ./tests/saveload/result/isset.sav" + STDOPT: +"-quiet -eva @EVA_OPTIONS@ -load ./tests/saveload/result/isset.sav" */ int main() { diff --git a/tests/saveload/multi_project.i b/tests/saveload/multi_project.i index 3a98905ee05a858635d65a496b77f0e75e664535..ab0d9a44fd15de6c80394627618705578bd54744 100644 --- a/tests/saveload/multi_project.i +++ b/tests/saveload/multi_project.i @@ -1,9 +1,9 @@ /* run.config - EXECNOW: BIN multi_project.sav LOG multi_project_sav.res LOG multi_project_sav.err ./bin/toplevel.opt -save ./tests/saveload/result/multi_project.sav -eva-show-progress -semantic-const-folding @PTEST_DIR@/@PTEST_NAME@.i > tests/saveload/result/multi_project_sav.res 2> tests/saveload/result/multi_project_sav.err + EXECNOW: BIN multi_project.sav LOG multi_project_sav.res LOG multi_project_sav.err ./bin/toplevel.opt -save ./tests/saveload/result/multi_project.sav @EVA_OPTIONS@ -semantic-const-folding @PTEST_DIR@/@PTEST_NAME@.i > tests/saveload/result/multi_project_sav.res 2> tests/saveload/result/multi_project_sav.err EXECNOW: make -s @PTEST_DIR@/@PTEST_NAME@.cmxs STDOPT: +"-load ./tests/saveload/result/multi_project.sav -journal-disable" CMD: @frama-c@ -load-module @PTEST_DIR@/@PTEST_NAME@.cmxs - OPT: -eva -eva-show-progress + OPT: -eva @EVA_OPTIONS@ */ int f(int x) { return x + x; diff --git a/tests/saveload/oracle/basic_sav.1.res b/tests/saveload/oracle/basic_sav.1.res index d2c84cb5472a81605ccd30aad3736fefb3012431..056059606204259f47c4619d6aa71f6dd14adaa0 100644 --- a/tests/saveload/oracle/basic_sav.1.res +++ b/tests/saveload/oracle/basic_sav.1.res @@ -15,21 +15,6 @@ i ∈ [-2147483648..9] j ∈ {5} __retres ∈ {0} -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. - In this function, 12 statements reached (out of 12): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 1 alarm generated by the analysis: - 1 integer overflow - ---------------------------------------------------------------------------- - Evaluation of the logical properties reached by the analysis: - Assertions 1 valid 0 unknown 0 invalid 1 total - Preconditions 0 valid 0 unknown 0 invalid 0 total - 100% of the logical properties reached have been proven. - ---------------------------------------------------------------------------- [from] Computing for function main [from] Done for function main [from] ====== DEPENDENCIES COMPUTED ====== diff --git a/tests/saveload/oracle/basic_sav.res b/tests/saveload/oracle/basic_sav.res index d2c84cb5472a81605ccd30aad3736fefb3012431..056059606204259f47c4619d6aa71f6dd14adaa0 100644 --- a/tests/saveload/oracle/basic_sav.res +++ b/tests/saveload/oracle/basic_sav.res @@ -15,21 +15,6 @@ i ∈ [-2147483648..9] j ∈ {5} __retres ∈ {0} -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. - In this function, 12 statements reached (out of 12): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 1 alarm generated by the analysis: - 1 integer overflow - ---------------------------------------------------------------------------- - Evaluation of the logical properties reached by the analysis: - Assertions 1 valid 0 unknown 0 invalid 1 total - Preconditions 0 valid 0 unknown 0 invalid 0 total - 100% of the logical properties reached have been proven. - ---------------------------------------------------------------------------- [from] Computing for function main [from] Done for function main [from] ====== DEPENDENCIES COMPUTED ====== diff --git a/tests/saveload/oracle/bool_sav.res b/tests/saveload/oracle/bool_sav.res index 42cfadd177d9795b61e0ab5ef909a7f2ab78dc5c..91b80def8d2d6316bebfd69690759d3c1442a3d0 100644 --- a/tests/saveload/oracle/bool_sav.res +++ b/tests/saveload/oracle/bool_sav.res @@ -54,18 +54,3 @@ x ∈ {1} y ∈ {2} S___fc_stdout[0..1] ∈ [--..--] -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 2 functions analyzed (out of 2): 100% coverage. - In these functions, 24 statements reached (out of 24): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 1 alarm generated by the analysis: - 1 integer overflow - ---------------------------------------------------------------------------- - Evaluation of the logical properties reached by the analysis: - Assertions 1 valid 0 unknown 0 invalid 1 total - Preconditions 5 valid 0 unknown 0 invalid 5 total - 100% of the logical properties reached have been proven. - ---------------------------------------------------------------------------- diff --git a/tests/saveload/oracle/callbacks_initial.res b/tests/saveload/oracle/callbacks_initial.res index 25b036ba64125f63b83322c481bbdb8145af540e..ca27cc9df7cc3081e5c5ad7bbd1f98d0b479dbef 100644 --- a/tests/saveload/oracle/callbacks_initial.res +++ b/tests/saveload/oracle/callbacks_initial.res @@ -35,7 +35,7 @@ [eva] done for function main1 [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 4 functions analyzed (out of 4): 100% coverage. + 4 functions analyzed (out of 6): 66% coverage. In these functions, 9 statements reached (out of 9): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/saveload/oracle/deps_sav.res b/tests/saveload/oracle/deps_sav.res index c52779de1ee27f18ae17e8ab60348d97820dbefe..40f9aeda11453a63ab6d1a1c2a1b0b9083ec2cbe 100644 --- a/tests/saveload/oracle/deps_sav.res +++ b/tests/saveload/oracle/deps_sav.res @@ -14,18 +14,6 @@ i ∈ [-2147483648..9] j ∈ {5} __retres ∈ {0} -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. - In this function, 11 statements reached (out of 11): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 1 alarm generated by the analysis: - 1 integer overflow - ---------------------------------------------------------------------------- - No logical properties have been reached by the analysis. - ---------------------------------------------------------------------------- [from] Computing for function main [from] Done for function main [from] ====== DEPENDENCIES COMPUTED ====== diff --git a/tests/saveload/oracle/multi_project.1.res.oracle b/tests/saveload/oracle/multi_project.1.res.oracle index 1ca91d867296f076e2a0a71a83f86eddebc8b32a..1cd5eaed301e7605d863fc6f45aa6e8ca1326a5a 100644 --- a/tests/saveload/oracle/multi_project.1.res.oracle +++ b/tests/saveload/oracle/multi_project.1.res.oracle @@ -18,20 +18,6 @@ x ∈ {2} y ∈ {4} __retres ∈ {8} -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 2 functions analyzed (out of 2): 100% coverage. - In these functions, 7 statements reached (out of 7): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 0 alarms generated by the analysis. - ---------------------------------------------------------------------------- - Evaluation of the logical properties reached by the analysis: - Assertions 1 valid 0 unknown 0 invalid 1 total - Preconditions 0 valid 0 unknown 0 invalid 0 total - 100% of the logical properties reached have been proven. - ---------------------------------------------------------------------------- [kernel] Checking "foo" [kernel] Checking "foobar" [kernel] Checking "default" diff --git a/tests/saveload/oracle/multi_project_sav.res b/tests/saveload/oracle/multi_project_sav.res index 6968a8ec6bec3d45c4bafa4c62f29beab29467df..c6cb667f22790752799c6073a046dd5a4f4d07a2 100644 --- a/tests/saveload/oracle/multi_project_sav.res +++ b/tests/saveload/oracle/multi_project_sav.res @@ -12,20 +12,6 @@ [eva] tests/saveload/multi_project.i:15: assertion got status valid. [eva] Recording results for main [eva] done for function main -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 2 functions analyzed (out of 2): 100% coverage. - In these functions, 7 statements reached (out of 7): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 0 alarms generated by the analysis. - ---------------------------------------------------------------------------- - Evaluation of the logical properties reached by the analysis: - Assertions 1 valid 0 unknown 0 invalid 1 total - Preconditions 0 valid 0 unknown 0 invalid 0 total - 100% of the logical properties reached have been proven. - ---------------------------------------------------------------------------- /* Generated by Frama-C */ int f(int x) { diff --git a/tests/saveload/oracle/segfault_datatypes_sav.res b/tests/saveload/oracle/segfault_datatypes_sav.res index 1cf0a3182aa799855b6b8135f9bfc4bcc08f6746..a67d19e53c35d8b2b99e4d14186c88dd929a4f51 100644 --- a/tests/saveload/oracle/segfault_datatypes_sav.res +++ b/tests/saveload/oracle/segfault_datatypes_sav.res @@ -14,18 +14,6 @@ i ∈ [-2147483648..9] j ∈ {5} __retres ∈ {0} -[eva:summary] ====== ANALYSIS SUMMARY ====== - ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. - In this function, 11 statements reached (out of 11): 100% coverage. - ---------------------------------------------------------------------------- - No errors or warnings raised during the analysis. - ---------------------------------------------------------------------------- - 1 alarm generated by the analysis: - 1 integer overflow - ---------------------------------------------------------------------------- - No logical properties have been reached by the analysis. - ---------------------------------------------------------------------------- [from] Computing for function main [from] Done for function main [from] ====== DEPENDENCIES COMPUTED ====== diff --git a/tests/saveload/segfault_datatypes.i b/tests/saveload/segfault_datatypes.i index 0e64333dd66e888dfbe6f51bc17a9c3f820de664..7d6c97c42832cdb0edb6beadd038443b9e925186 100644 --- a/tests/saveload/segfault_datatypes.i +++ b/tests/saveload/segfault_datatypes.i @@ -1,8 +1,8 @@ /* run.config EXECNOW: make -s ./tests/saveload/segfault_datatypes_A.cmxs ./tests/saveload/segfault_datatypes_B.cmxs - EXECNOW: LOG segfault_datatypes_sav.res LOG segfault_datatypes_sav.err BIN segfault_datatypes.sav @frama-c@ -load-module ./tests/saveload/segfault_datatypes_A -eva -out -input -deps ./tests/saveload/segfault_datatypes.i -eva-show-progress -save ./tests/saveload/result/segfault_datatypes.sav > ./tests/saveload/result/segfault_datatypes_sav.res 2> ./tests/saveload/result/segfault_datatypes_sav.err + EXECNOW: LOG segfault_datatypes_sav.res LOG segfault_datatypes_sav.err BIN segfault_datatypes.sav @frama-c@ -load-module ./tests/saveload/segfault_datatypes_A -eva @EVA_OPTIONS@ -out -input -deps ./tests/saveload/segfault_datatypes.i -save ./tests/saveload/result/segfault_datatypes.sav > ./tests/saveload/result/segfault_datatypes_sav.res 2> ./tests/saveload/result/segfault_datatypes_sav.err CMD: @frama-c@ -load-module ./tests/saveload/segfault_datatypes_B - STDOPT: +"-load ./tests/saveload/result/segfault_datatypes.sav -eva -out -input -deps -journal-disable" + STDOPT: +"-load ./tests/saveload/result/segfault_datatypes.sav -eva @EVA_OPTIONS@ -out -input -deps -journal-disable" */ 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/spec/oracle/rm_qualifiers.res.oracle b/tests/spec/oracle/rm_qualifiers.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c1fcfb54dce01b8338946cf06f02e27845482c67 --- /dev/null +++ b/tests/spec/oracle/rm_qualifiers.res.oracle @@ -0,0 +1,14 @@ +[kernel] Parsing tests/spec/rm_qualifiers.i (no preprocessing) +[kernel] Parsing tests/spec/result/rm_qualifiers_res.i (no preprocessing) +/* Generated by Frama-C */ +extern void G(void const *p); + +void *ptr; +/*@ ensures ptr ≡ (void *)((int const volatile *)*(\old(ftab) + 1)); */ +void F(int const volatile (*ftab)[3], unsigned int const id) +{ + G((void const *)(*(ftab + 1))); + return; +} + + diff --git a/tests/spec/rm_qualifiers.i b/tests/spec/rm_qualifiers.i new file mode 100644 index 0000000000000000000000000000000000000000..66d6d336519ad00ab153d800784078580d692d82 --- /dev/null +++ b/tests/spec/rm_qualifiers.i @@ -0,0 +1,11 @@ +/* run.config +OPT: @PTEST_FILE@ -ocode @PTEST_DIR@/result/@PTEST_NAME@_res.i -print -then @PTEST_DIR@/result/@PTEST_NAME@_res.i -ocode="" -print +*/ +extern void G(const void* p); +typedef volatile int ARR[42][3]; +void* ptr; + +//@ ensures ptr == (void *)ftab[1]; +void F(const ARR ftab, const unsigned id) { + G((void *)ftab[1]); +} diff --git a/tests/syntax/anon_enum_libc.c b/tests/syntax/anon_enum_libc.c new file mode 100644 index 0000000000000000000000000000000000000000..3c420cf6e6fe62b7f6becb62555d2708a710c471 --- /dev/null +++ b/tests/syntax/anon_enum_libc.c @@ -0,0 +1,14 @@ +/* run.config +FILTER: sed -e 's|#include *"\([^/]*[/]\)*\([^/]*\)"|#include "PTESTS_DIR/\2"|' +OPT: -cpp-extra-args="-I @PTEST_DIR@" -ocode @PTEST_DIR@/result/@PTEST_NAME@.c -print -then -ocode="" @PTEST_DIR@/result/@PTEST_NAME@.c -print +*/ + +struct { int x; float y; } s1; + +enum { BLA=4, BLI=12 }; + +#include "anon_enum_libc.h" + +int f() { return BLA + s1.x; } + +int g() { return FOO + s2.t; } diff --git a/tests/syntax/anon_enum_libc.h b/tests/syntax/anon_enum_libc.h new file mode 100644 index 0000000000000000000000000000000000000000..e659c07ea7ea7e8c9b91dd5d2351d341af180ca6 --- /dev/null +++ b/tests/syntax/anon_enum_libc.h @@ -0,0 +1,5 @@ +#include "features.h" +__PUSH_FC_STDLIB +struct { char z; unsigned long t; } s2; +enum { FOO, BAR=3 }; +__POP_FC_STDLIB 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/anon_enum_libc.res.oracle b/tests/syntax/oracle/anon_enum_libc.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7a8098f266bdd68a621604cce083c1cd2619aaa8 --- /dev/null +++ b/tests/syntax/oracle/anon_enum_libc.res.oracle @@ -0,0 +1,28 @@ +[kernel] Parsing tests/syntax/anon_enum_libc.c (with preprocessing) +[kernel] Parsing tests/syntax/result/anon_enum_libc.c (with preprocessing) +/* Generated by Frama-C */ +#include "PTESTS_DIR/anon_enum_libc.h" +struct __anonstruct_s1_1 { + int x ; + float y ; +}; +enum __anonenum_2 { + BLA = 4, + BLI = 12 +}; +struct __anonstruct_s1_1 s1; +int f(void) +{ + int __retres; + __retres = BLA + s1.x; + return __retres; +} + +int g(void) +{ + int __retres; + __retres = (int)((unsigned long)FOO + s2.t); + return __retres; +} + + 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/loop-case-switch-for-unroll.0.res.oracle b/tests/syntax/oracle/loop-case-switch-for-unroll.0.res.oracle index 4407cbebb995be38963c081af07126d4ee7385ce..bc309572e3c93311052a35b023b615d0bb7335a5 100644 --- a/tests/syntax/oracle/loop-case-switch-for-unroll.0.res.oracle +++ b/tests/syntax/oracle/loop-case-switch-for-unroll.0.res.oracle @@ -114,7 +114,7 @@ gen_nondet_i ∈ {31} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 2 functions analyzed (out of 5): 40% coverage. + 2 functions analyzed (out of 2): 100% coverage. In these functions, 45 statements reached (out of 48): 93% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/syntax/oracle/loop-case-switch-for-unroll.1.res.oracle b/tests/syntax/oracle/loop-case-switch-for-unroll.1.res.oracle index ccd8dec4937e12ce19a03bca5e7be6379d4cb91c..92c05ca5ff89cdd99b6e91c527dbe54d925fe132 100644 --- a/tests/syntax/oracle/loop-case-switch-for-unroll.1.res.oracle +++ b/tests/syntax/oracle/loop-case-switch-for-unroll.1.res.oracle @@ -114,7 +114,7 @@ gen_nondet_i ∈ {31} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 2 functions analyzed (out of 52): 3% coverage. + 2 functions analyzed (out of 2): 100% coverage. In these functions, 75 statements reached (out of 125): 60% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/syntax/oracle/loop-case-switch-for-unroll.2.res.oracle b/tests/syntax/oracle/loop-case-switch-for-unroll.2.res.oracle index f029ae319170bc1e849e524390a368aca68a6c87..93eb615f7f19c1b9e96c932e2fe84d4c6de0451d 100644 --- a/tests/syntax/oracle/loop-case-switch-for-unroll.2.res.oracle +++ b/tests/syntax/oracle/loop-case-switch-for-unroll.2.res.oracle @@ -114,7 +114,7 @@ gen_nondet_i ∈ {31} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 2 functions analyzed (out of 166): 1% coverage. + 2 functions analyzed (out of 2): 100% coverage. In these functions, 74 statements reached (out of 238): 31% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/syntax/oracle/temporary_location.res.oracle b/tests/syntax/oracle/temporary_location.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8ba7b0ae166cd14b33bf0876e803391c5cd12cab --- /dev/null +++ b/tests/syntax/oracle/temporary_location.res.oracle @@ -0,0 +1,50 @@ +[kernel] Parsing tests/syntax/temporary_location.c (with preprocessing) +[kernel] __retres -> tests/syntax/temporary_location.c:7 +[kernel] __retres -> tests/syntax/temporary_location.c:7 +[kernel] __retres -> tests/syntax/temporary_location.c:7 +[kernel] __retres -> tests/syntax/temporary_location.c:17 +[kernel] tmp_0 -> tests/syntax/temporary_location.c:11 +[kernel] f -> tests/syntax/temporary_location.c:6 +[kernel] tmp_0 -> tests/syntax/temporary_location.c:11 +[kernel] __retres -> tests/syntax/temporary_location.c:17 +[kernel] x -> tests/syntax/temporary_location.c:15 +[kernel] tmp -> tests/syntax/temporary_location.c:16 +[kernel] x -> tests/syntax/temporary_location.c:15 +[kernel] x -> tests/syntax/temporary_location.c:15 +[kernel] x -> tests/syntax/temporary_location.c:15 +[kernel] x -> tests/syntax/temporary_location.c:15 +[kernel] y -> tests/syntax/temporary_location.c:16 +[kernel] tmp -> tests/syntax/temporary_location.c:16 +[kernel] __retres -> tests/syntax/temporary_location.c:17 +[kernel] y -> tests/syntax/temporary_location.c:16 +[kernel] __retres -> tests/syntax/temporary_location.c:17 +/* Generated by Frama-C */ +int f(void) +{ + int __retres; + __retres = 1; + return __retres; +} + +int main(void) +{ + int __retres; + int tmp_0; + tmp_0 = f(); + if (tmp_0) { + __retres = 0; + goto return_label; + } + else { + int tmp; + int x = 0; + tmp = x; + x ++; + int y = tmp + 1; + __retres = y + 3; + goto return_label; + } + return_label: return __retres; +} + + 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); diff --git a/tests/syntax/temporary_location.c b/tests/syntax/temporary_location.c new file mode 100644 index 0000000000000000000000000000000000000000..765e6bccedee2df52e4d8551c4fac28faa06523e --- /dev/null +++ b/tests/syntax/temporary_location.c @@ -0,0 +1,19 @@ +/* run.config + EXECNOW: make -s @PTEST_DIR@/@PTEST_NAME@.cmxs + OPT: -load-module @PTEST_DIR@/@PTEST_NAME@.cmxs -print +*/ + +int f(void) { + return 1; +} + +int main(void) { + if(f()){ + return 0; + } + else { + int x = 0; + int y = x++ + 1; + return y + 3; + } +} diff --git a/tests/syntax/temporary_location.ml b/tests/syntax/temporary_location.ml new file mode 100644 index 0000000000000000000000000000000000000000..c6792bd916b11be0921473018addb73a3b3e714e --- /dev/null +++ b/tests/syntax/temporary_location.ml @@ -0,0 +1,18 @@ +open Cil_types + +class vis = object(_) + inherit Visitor.frama_c_inplace + + method! vvrbl vi = + Kernel.result "%s -> %a" vi.vname Printer.pp_location vi.vdecl; + Cil.DoChildren + +end + +let main () = + Ast.compute (); + Cil.visitCilFile (new vis :> Cil.cilVisitor) (Ast.get ()) + +let () = + Db.Main.extend main + diff --git a/tests/test_config b/tests/test_config index 6efe608ac844b6bfd35b978ccf9915ef6adab07f..3349a7b04de557ca065dddc3267824bed2662dbb 100644 --- a/tests/test_config +++ b/tests/test_config @@ -1,3 +1,3 @@ -MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary +MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-auto-loop-unroll 0 MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/test_config_apron b/tests/test_config_apron index 2d6cff1926f6598e15c22f97ede264377dedf042..f2cc7c99925549ed501f9c2920742c71f2896639 100644 --- a/tests/test_config_apron +++ b/tests/test_config_apron @@ -1,3 +1,3 @@ -MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-apron-oct -eva-msg-key experimental-ok +MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-auto-loop-unroll 0 -eva-apron-oct -eva-msg-key experimental-ok MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/test_config_bitwise b/tests/test_config_bitwise index 7e1be236655fdf63e47056f790c1e3c9b30dcdb0..78b3b47c351dd5164adf860a4276680135700ccb 100644 --- a/tests/test_config_bitwise +++ b/tests/test_config_bitwise @@ -1,3 +1,3 @@ -MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-bitwise-domain +MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-auto-loop-unroll 0 -eva-bitwise-domain MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/test_config_equalities b/tests/test_config_equalities index d84a7e2a8b21674dad528c1927b0630aa948a2f3..c386ea89a05c577a7ce1ca5f9a01308c1b02948a 100644 --- a/tests/test_config_equalities +++ b/tests/test_config_equalities @@ -1,3 +1,3 @@ -MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-equality-domain +MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-auto-loop-unroll 0 -eva-equality-domain MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/test_config_gauges b/tests/test_config_gauges index b6a460ae1e45ec4c85dc60eb2a4851b6d84f63b7..bc7593f4e6be173da86718fce2727ad8c60be77e 100644 --- a/tests/test_config_gauges +++ b/tests/test_config_gauges @@ -1,3 +1,3 @@ -MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-gauges-domain +MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-auto-loop-unroll 0 -eva-gauges-domain MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/test_config_octagons b/tests/test_config_octagons new file mode 100644 index 0000000000000000000000000000000000000000..701bc8421e733eb40844d0b62ab65400925c498e --- /dev/null +++ b/tests/test_config_octagons @@ -0,0 +1,3 @@ +MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-octagon-domain +MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic +OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/test_config_symblocs b/tests/test_config_symblocs index 47ce23088d402b091d071c21699c8fb9d4f7f268..8cbbc295b177df03ddd9d2655b1bba2d2e68acde 100644 --- a/tests/test_config_symblocs +++ b/tests/test_config_symblocs @@ -1,3 +1,3 @@ -MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-symbolic-locations-domain +MACRO: EVA_OPTIONS -eva-show-progress -eva-msg-key=-summary -eva-auto-loop-unroll 0 -eva-symbolic-locations-domain MACRO: EVA_CONFIG @EVA_OPTIONS@ -no-autoload-plugins -load-module from,inout,eva,scope,variadic OPT: -eva @EVA_CONFIG@ -journal-disable -out -input -deps diff --git a/tests/value/auto_loop_unroll.c b/tests/value/auto_loop_unroll.c new file mode 100644 index 0000000000000000000000000000000000000000..d3a1a1ce141f3d23490482ee26cd1bd80b54995b --- /dev/null +++ b/tests/value/auto_loop_unroll.c @@ -0,0 +1,192 @@ +/* run.config* + STDOPT: +"-eva-auto-loop-unroll 10" + STDOPT: +"-eva-auto-loop-unroll 128" +*/ + +/* Tests the automatic loop unrolling heuristic. */ + +#include <__fc_builtin.h> + +volatile int undet; + +int g = 0; +void incr_g () { + g++; +} + +int incr (int i) { + return i+1; +} + +void simple_loops () { + int res = 0; + /* This loop should be automatically unrolled on the second run. */ + for (int i = 0; i < 100; i++) { + res++; + } + Frama_C_show_each_auto(res); + res = 0; + /* This loop should not be automatically unrolled. */ + for (int i = 0; i < 1000; i++) { + res++; + } + Frama_C_show_each_imprecise(res); + res = 0; + /* The annotation has priority over the automatic loop unrolling: + this loop should never be unrolled. */ + /*@ loop unroll 0; */ + for (int i = 0; i < 100; i++) { + res++; + } + Frama_C_show_each_imprecise(res); + res = 0; + /* The annnotation has priority over the automatic loop unrolling: + this loop should always be unrolled. */ + /*@ loop unroll 100; */ + for (int i = 0; i < 100; i++) { + res++; + } + Frama_C_show_each_singleton(res); +} + +/* Examples of various loops that should be automatically unrolled + on the second run, but not on the first. */ +void various_loops () { + int res = 0; + /* Decreasing loop counter. */ + for (int i = 64; i > 0; i--) + res++; + Frama_C_show_each_64(res); + res = 0; + /* Decrements the loop counter by 3. */ + for (int i = 120; i > 0; i -= 3) + res++; + Frama_C_show_each_40(res); + res = 0; + /* Several increments of the loop counter. */ + for (int i = 0; i < 160; i++) { + i += 2; + res++; + i--; + } + Frama_C_show_each_80(res); + res = 0; + /* Random increments of the loop counter. */ + for (int i = 0; i < 160;) { + res++; + if (undet) + i += 2; + else + i += 5; + } + Frama_C_show_each_32_80(res); + res = 0; + /* Other loop breaking condition. */ + for (int i = 0; i < 111; i++) { + res++; + if (undet && res > 10) + break; + } + Frama_C_show_each_11_111(res); + res = 0; + /* More complex loop condition. */ + int x = 24; + int k = Frama_C_interval(0, 10); + for (int i = 75; i + x > 2 * k; i -= 2) + res++; + Frama_C_show_each_40_50(res); + res = 0; + /* Loop calling some functions that do not modify the loop counter. */ + for (int i = 0; i < 25; i++) { + incr_g(); + int t = incr(i); + res = incr(res); + } + Frama_C_show_each_25(res); + res = 0; + /* Nested loops. */ + res = 0; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < i; j++) { + res++; + } + } + Frama_C_show_each_120(res); + res = 0; +} + +/* Loops that cannot be unrolled. */ +void complex_loops () { + /* Loop counter modified through a pointer. */ + int res = 0; + int i = 0; + int *p = &i; + while (i < 64) { + (*p)++; + res++; + } + Frama_C_show_each_imprecise(res); + /* Loop counter modified within a nested loop. */ + res = 0; + i = 0; + while (i < 64) { + for (int j = 0; j < i; j++) { + i++; + } + res++; + i++; + } + Frama_C_show_each_imprecise(res); + /* Loop counter incremented under a condition. */ + res = 0; + i = 0; + while (i < 10) { + if (undet) + i++; + res++; + } + Frama_C_show_each_imprecise(res); + res = 0; + i = 0; + while (i < 10) { + if (undet) + i++; + else + i++; + res++; + } + Frama_C_show_each_imprecise(res); + /* Loop counter modified by a function. */ + res = 0; + g = 0; + while (g < 64) { + incr_g(); + g++; + res++; + } + Frama_C_show_each_imprecise(res); + res = 0; + /* Too complex loop condition. */ + int t[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + i = 0; + while (t[i] < 6) { + i++; + res++; + } + Frama_C_show_each_imprecise(res); + res = 0; + /* Random loop condition. */ + i = 0; + while (i < 64 && undet) { + i++; + res++; + } + Frama_C_show_each_imprecise(res); +} + + +void main () { + simple_loops (); + various_loops (); + complex_loops (); +} diff --git a/tests/value/diff_apron b/tests/value/diff_apron index 2ead3a445bbc76a876c5e89fb0e57325a79f52a0..e43d97743cb15e14e2c12e5d5ca200006be5b5a1 100644 --- a/tests/value/diff_apron +++ b/tests/value/diff_apron @@ -670,6 +670,17 @@ diff tests/value/oracle/modulo.res.oracle tests/value/oracle_apron/modulo.res.or 60a109,110 > [eva] tests/value/modulo.i:64: Frama_C_show_each_3: [-10..10], [-9..9], [-8..8] > [eva] tests/value/modulo.i:64: Frama_C_show_each_3: [-9..9], [-8..8], [-7..7] +diff tests/value/oracle/octagons.res.oracle tests/value/oracle_apron/octagons.res.oracle +270,273c270,273 +< a ∈ [-1024..2147483647] +< b ∈ [-1023..2147483647] +< c ∈ [-1023..2147483647] +< d ∈ [-1032..2147483647] +--- +> a ∈ [-603..2147483646] +> b ∈ [-602..2147483647] +> c ∈ [-602..1446] +> d ∈ [-611..2147483647] diff tests/value/oracle/offsetmap.0.res.oracle tests/value/oracle_apron/offsetmap.0.res.oracle 62,63c62 < a[bits 0 to 7] ∈ {1; 6} diff --git a/tests/value/diff_equalities b/tests/value/diff_equalities index 821b7e3c2fc6803fa2584c2b2deedc7692ba8b60..83d093f00364f8bd80e50ed2ff37c260660b6c70 100644 --- a/tests/value/diff_equalities +++ b/tests/value/diff_equalities @@ -610,6 +610,15 @@ diff tests/value/oracle/nonlin.res.oracle tests/value/oracle_equalities/nonlin.r < q ∈ {{ &x + [-400..400],0%4 }} --- > q ∈ {{ &x }} +diff tests/value/oracle/octagons.res.oracle tests/value/oracle_equalities/octagons.res.oracle +29c29 +< Frama_C_show_each_unreduced_unsigned: [0..4294967295], [0..4294967295] +--- +> Frama_C_show_each_unreduced_unsigned: [0..4294967295], [6..4294967295] +255c255 +< t ∈ [--..--] or UNINITIALIZED +--- +> t ∈ [6..4294967295] or UNINITIALIZED diff tests/value/oracle/offsetmap.0.res.oracle tests/value/oracle_equalities/offsetmap.0.res.oracle 38d37 < [eva] Recording results for g diff --git a/tests/value/diff_gauges b/tests/value/diff_gauges index e0312fea2b92804faca6c4ccae3d2e2afc83fda6..ab9ecdc28fc62ed33d66256204e38c85a05476ed 100644 --- a/tests/value/diff_gauges +++ b/tests/value/diff_gauges @@ -889,6 +889,34 @@ diff tests/value/oracle/noreturn.res.oracle tests/value/oracle_gauges/noreturn.r > [eva] tests/value/noreturn.i:7: starting to merge loop iterations 36a40 > [eva] tests/value/noreturn.i:13: starting to merge loop iterations +diff tests/value/oracle/octagons.res.oracle tests/value/oracle_gauges/octagons.res.oracle +121,128d120 +< [eva:alarm] tests/value/octagons.c:107: Warning: +< signed overflow. assert a + 2 ≤ 2147483647; +< [eva:alarm] tests/value/octagons.c:108: Warning: +< signed overflow. assert b + 2 ≤ 2147483647; +< [eva:alarm] tests/value/octagons.c:110: Warning: +< signed overflow. assert a + k ≤ 2147483647; +< [eva:alarm] tests/value/octagons.c:113: Warning: +< signed overflow. assert -2147483648 ≤ c - a; +130c122 +< [eva] tests/value/octagons.c:116: Frama_C_show_each_imprecise: [-2147483648..1] +--- +> [eva] tests/value/octagons.c:116: Frama_C_show_each_imprecise: [-2468..1] +270,273c262,265 +< a ∈ [-1024..2147483647] +< b ∈ [-1023..2147483647] +< c ∈ [-1023..2147483647] +< d ∈ [-1032..2147483647] +--- +> a ∈ [-182..1866] +> b ∈ [-181..1867] +> c ∈ [-602..1446] +> d ∈ [-190..1874] +275c267 +< d2 ∈ [-2147483648..1] +--- +> d2 ∈ [-2468..1] diff tests/value/oracle/reduce_formals.res.oracle tests/value/oracle_gauges/reduce_formals.res.oracle 10a11 > [eva] tests/value/reduce_formals.i:5: starting to merge loop iterations diff --git a/tests/value/diff_octagons b/tests/value/diff_octagons new file mode 100644 index 0000000000000000000000000000000000000000..2b5ae606dfe09be4f1aa091b2742ab58c421eb1f --- /dev/null +++ b/tests/value/diff_octagons @@ -0,0 +1,399 @@ +diff tests/value/oracle/alias.1.res.oracle tests/value/oracle_octagons/alias.1.res.oracle +85c85 +< z ∈ {0; 1; 2} +--- +> z ∈ {0; 2} +diff tests/value/oracle/alias.2.res.oracle tests/value/oracle_octagons/alias.2.res.oracle +76c76 +< z ∈ {-5; -4; -3; -2; -1; 0; 1; 1000} +--- +> z ∈ {-2; -1; 0; 1000} +diff tests/value/oracle/alias.3.res.oracle tests/value/oracle_octagons/alias.3.res.oracle +67c67 +< z ∈ {0; 1; 2} +--- +> z ∈ {0; 2} +diff tests/value/oracle/alias.5.res.oracle tests/value/oracle_octagons/alias.5.res.oracle +59a60 +> [eva] tests/value/alias.i:260: starting to merge loop iterations +diff tests/value/oracle/alias.6.res.oracle tests/value/oracle_octagons/alias.6.res.oracle +82c82 +< t ∈ {4; 5; 6} +--- +> t ∈ {5} +87c87 +< y ∈ {0; 1} +--- +> y ∈ {1} +94,96c94,96 +< tz1 ∈ {0; 1} +< tz2 ∈ {0; 1} +< tz3 ∈ {0; 1} +--- +> tz1 ∈ {1} +> tz2 ∈ {1} +> tz3 ∈ {1} +diff tests/value/oracle/bitfield.res.oracle tests/value/oracle_octagons/bitfield.res.oracle +132a133,135 +> [eva] tests/value/bitfield.i:71: +> Frama_C_show_each: +> {{ garbled mix of &{b} (origin: Misaligned {tests/value/bitfield.i:70}) }} +diff tests/value/oracle/builtins_split.res.oracle tests/value/oracle_octagons/builtins_split.res.oracle +70a71,84 +> [eva] tests/value/builtins_split.c:104: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:104: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:104: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:104: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:104: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:104: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:104: +> Call to builtin Frama_C_builtin_split_all +81a96,109 +> [eva] tests/value/builtins_split.c:112: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:112: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:112: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:112: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:112: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:112: +> Call to builtin Frama_C_builtin_split_all +> [eva] tests/value/builtins_split.c:112: +> Call to builtin Frama_C_builtin_split_all +diff tests/value/oracle/call_simple.res.oracle tests/value/oracle_octagons/call_simple.res.oracle +28c28 +< c ∈ [--..--] +--- +> c ∈ [-2147483648..2147483646] +diff tests/value/oracle/descending.res.oracle tests/value/oracle_octagons/descending.res.oracle +42c42 +< i ∈ {31; 32} +--- +> i ∈ {31} +diff tests/value/oracle/downcast.res.oracle tests/value/oracle_octagons/downcast.res.oracle +61c61 +< [100000..2147483647], [100145..2147483647], [100145..2147483647] +--- +> [100000..2147483502], [100145..2147483647], [100145..2147483647] +167c167 +< x_0 ∈ [100000..2147483647] +--- +> x_0 ∈ [100000..2147483502] +diff tests/value/oracle/equality.res.oracle tests/value/oracle_octagons/equality.res.oracle +29,30c29,30 +< y ∈ [0..42] or UNINITIALIZED +< w ∈ [0..42] or UNINITIALIZED +--- +> y ∈ [0..42] +> w ∈ [0..42] +diff tests/value/oracle/find_ivaltop.res.oracle tests/value/oracle_octagons/find_ivaltop.res.oracle +32,33c32,33 +< j ∈ {0; 1; 2; 3; 4; 5; 6; 7} +< X ∈ {1; 2; 3; 4; 5; 6; 7; 8} +--- +> j ∈ {7} +> X ∈ {8} +39c39 +< \result FROM t[0..7] +--- +> \result FROM t[7] +44c44 +< t[0..7] +--- +> t[7] +diff tests/value/oracle/for_loops.3.res.oracle tests/value/oracle_octagons/for_loops.3.res.oracle +20c20 +< v ∈ [0..2147483647] +--- +> v ∈ [5..2147483647] +diff tests/value/oracle/gauges.res.oracle tests/value/oracle_octagons/gauges.res.oracle +209,210d208 +< [eva:alarm] tests/value/gauges.c:156: Warning: +< signed overflow. assert -2147483648 ≤ toCopy - 1; +272,273d269 +< [eva:alarm] tests/value/gauges.c:201: Warning: +< signed overflow. assert -2147483648 ≤ numNonZero - 1; +296,300d291 +< [eva] tests/value/gauges.c:218: Frama_C_show_each: +< [eva] tests/value/gauges.c:218: Frama_C_show_each: +< [eva] tests/value/gauges.c:218: Frama_C_show_each: +< [eva:alarm] tests/value/gauges.c:220: Warning: +< signed overflow. assert -2147483648 ≤ n - 1; +787c778 +< numNonZero ∈ [-2147483648..8] +--- +> numNonZero ∈ {-1} +798c789 +< n ∈ [-2147483648..99] +--- +> n ∈ {-1} +859c850 +< toCopy ∈ [-2147483648..99] +--- +> toCopy ∈ {-1} +diff tests/value/oracle/loop.res.oracle tests/value/oracle_octagons/loop.res.oracle +26c26 +< r ∈ [0..2147483646],0%2 +--- +> r ∈ [46..2147483646],0%2 +diff tests/value/oracle/loop_wvar.1.res.oracle tests/value/oracle_octagons/loop_wvar.1.res.oracle +12,13d11 +< [eva:alarm] tests/value/loop_wvar.i:57: Warning: +< signed overflow. assert next + 1 ≤ 2147483647; +41c39 +< next ∈ [0..2147483647] +--- +> next ∈ [0..25] +diff tests/value/oracle/modulo.res.oracle tests/value/oracle_octagons/modulo.res.oracle +40a41,56 +> [eva] tests/value/modulo.i:41: Frama_C_show_each_1: [-10..-1], [-9..-1], [-8..0] +> [eva] tests/value/modulo.i:41: Frama_C_show_each_1: [-10..-1], [1..9], [-8..0] +> [eva] tests/value/modulo.i:41: Frama_C_show_each_1: [1..10], [-9..-1], [0..8] +> [eva] tests/value/modulo.i:41: Frama_C_show_each_1: [1..10], [1..9], [0..8] +> [eva] tests/value/modulo.i:41: +> Frama_C_show_each_1: +> [1..9], {1; 2; 3; 4; 5; 6; 7; 8}, {0; 1; 2; 3; 4; 5; 6; 7} +> [eva] tests/value/modulo.i:41: +> Frama_C_show_each_1: +> [-9..-1], {1; 2; 3; 4; 5; 6; 7; 8}, {-7; -6; -5; -4; -3; -2; -1; 0} +> [eva] tests/value/modulo.i:41: +> Frama_C_show_each_1: +> [1..9], {-8; -7; -6; -5; -4; -3; -2; -1}, {0; 1; 2; 3; 4; 5; 6; 7} +> [eva] tests/value/modulo.i:41: +> Frama_C_show_each_1: +> [-9..-1], {-8; -7; -6; -5; -4; -3; -2; -1}, {-7; -6; -5; -4; -3; -2; -1; 0} +50a67,82 +> [eva] tests/value/modulo.i:53: Frama_C_show_each_2: [-10..-1], [1..9], [-8..0] +> [eva] tests/value/modulo.i:53: Frama_C_show_each_2: [-10..-1], [-9..-1], [-8..0] +> [eva] tests/value/modulo.i:53: Frama_C_show_each_2: [1..10], [1..9], [0..8] +> [eva] tests/value/modulo.i:53: Frama_C_show_each_2: [1..10], [-9..-1], [0..8] +> [eva] tests/value/modulo.i:53: +> Frama_C_show_each_2: +> [-9..-1], {1; 2; 3; 4; 5; 6; 7; 8}, {-7; -6; -5; -4; -3; -2; -1; 0} +> [eva] tests/value/modulo.i:53: +> Frama_C_show_each_2: +> [1..9], {1; 2; 3; 4; 5; 6; 7; 8}, {0; 1; 2; 3; 4; 5; 6; 7} +> [eva] tests/value/modulo.i:53: +> Frama_C_show_each_2: +> [-9..-1], {-8; -7; -6; -5; -4; -3; -2; -1}, {-7; -6; -5; -4; -3; -2; -1; 0} +> [eva] tests/value/modulo.i:53: +> Frama_C_show_each_2: +> [1..9], {-8; -7; -6; -5; -4; -3; -2; -1}, {0; 1; 2; 3; 4; 5; 6; 7} +60a93,94 +> [eva] tests/value/modulo.i:64: Frama_C_show_each_3: [-10..10], [-9..9], [-8..8] +> [eva] tests/value/modulo.i:64: Frama_C_show_each_3: [-9..9], [-8..8], [-7..7] +diff tests/value/oracle/non_natural.res.oracle tests/value/oracle_octagons/non_natural.res.oracle +58a59,60 +> [kernel] tests/value/non_natural.i:30: +> more than 200(12500) elements to enumerate. Approximating. +65a68,69 +> [kernel] tests/value/non_natural.i:23: +> more than 200(12500) elements to enumerate. Approximating. +70a75,76 +> [kernel] tests/value/non_natural.i:24: +> more than 200(12500) elements to enumerate. Approximating. +78a85,86 +> [kernel] tests/value/non_natural.i:25: +> more than 200(12500) elements to enumerate. Approximating. +86a95,96 +> [kernel] tests/value/non_natural.i:26: +> more than 200(12500) elements to enumerate. Approximating. +94a105,106 +> [kernel] tests/value/non_natural.i:27: +> more than 200(12500) elements to enumerate. Approximating. +102a115,116 +> [kernel] tests/value/non_natural.i:28: +> more than 200(12500) elements to enumerate. Approximating. +110a125,126 +> [kernel] tests/value/non_natural.i:29: +> more than 200(12500) elements to enumerate. Approximating. +129,130d144 +< [kernel] tests/value/non_natural.i:23: +< more than 200(12500) elements to enumerate. Approximating. +133,146d146 +< [kernel] tests/value/non_natural.i:24: +< more than 200(12500) elements to enumerate. Approximating. +< [kernel] tests/value/non_natural.i:25: +< more than 200(12500) elements to enumerate. Approximating. +< [kernel] tests/value/non_natural.i:26: +< more than 200(12500) elements to enumerate. Approximating. +< [kernel] tests/value/non_natural.i:27: +< more than 200(12500) elements to enumerate. Approximating. +< [kernel] tests/value/non_natural.i:28: +< more than 200(12500) elements to enumerate. Approximating. +< [kernel] tests/value/non_natural.i:29: +< more than 200(12500) elements to enumerate. Approximating. +< [kernel] tests/value/non_natural.i:30: +< more than 200(12500) elements to enumerate. Approximating. +199a200,201 +> [kernel] tests/value/non_natural.i:39: +> more than 200(12500) elements to enumerate. Approximating. +diff tests/value/oracle/nonlin.res.oracle tests/value/oracle_octagons/nonlin.res.oracle +105a106,107 +> [eva:nonlin] tests/value/nonlin.c:67: non-linear 'x * x', lv 'x' +> [eva:nonlin] tests/value/nonlin.c:67: subdividing on x +108a111,113 +> [eva:nonlin] tests/value/nonlin.c:68: subdividing on x +> [eva:nonlin] tests/value/nonlin.c:68: non-linear 'y * y', lv 'y' +> [eva:nonlin] tests/value/nonlin.c:68: subdividing on y +111a117,118 +> [eva:nonlin] tests/value/nonlin.c:70: non-linear 'z * x + x * y', lv 'x' +> [eva:nonlin] tests/value/nonlin.c:70: subdividing on x +176,178c183,185 +< square ∈ [-48..400] +< square2 ∈ [-48..400] +< res ∈ [-144..400] +--- +> square ∈ [-200..400] +> square2 ∈ [-200..400] +> res ∈ [-200..400] +diff tests/value/oracle/plevel.res.oracle tests/value/oracle_octagons/plevel.res.oracle +12d11 +< [eva] Recording results for main +14a14 +> [eva] Recording results for main +diff tests/value/oracle/ptr_relation.1.res.oracle tests/value/oracle_octagons/ptr_relation.1.res.oracle +24c24 +< j ∈ {-1; 0; 1} +--- +> j ∈ {0} +diff tests/value/oracle/relation_reduction.res.oracle tests/value/oracle_octagons/relation_reduction.res.oracle +24,27d23 +< [eva:alarm] tests/value/relation_reduction.i:20: Warning: +< accessing out of bounds index. assert 0 ≤ y; +< [eva:alarm] tests/value/relation_reduction.i:20: Warning: +< accessing out of bounds index. assert y < 9; +34,37c30,33 +< R1 ∈ [-2147483648..2147483637] +< R2 ∈ [-2147483638..2147483647] +< R3 ∈ [--..--] +< R4 ∈ {0; 1; 2; 3; 4; 5} +--- +> R1 ∈ {0; 2} +> R2 ∈ {0; 12} +> R3 ∈ {0; 7} +> R4 ∈ {0; 2} +48c44 +< R4 FROM tab[0..8]; x (and SELF) +--- +> R4 FROM tab[0..5]; x (and SELF) +53c49 +< y; t; tab[0..8] +--- +> y; t; tab[0..5] +diff tests/value/oracle/relation_shift.res.oracle tests/value/oracle_octagons/relation_shift.res.oracle +18,25d17 +< [eva:alarm] tests/value/relation_shift.i:15: Warning: +< signed overflow. assert -2147483648 ≤ x - y; +< [eva:alarm] tests/value/relation_shift.i:15: Warning: +< signed overflow. assert x - y ≤ 2147483647; +< [eva:alarm] tests/value/relation_shift.i:16: Warning: +< signed overflow. assert -2147483648 ≤ z - y; +< [eva:alarm] tests/value/relation_shift.i:16: Warning: +< signed overflow. assert z - y ≤ 2147483647; +31,32c23,24 +< r1 ∈ [--..--] +< r2 ∈ [--..--] +--- +> r1 ∈ {2} +> r2 ∈ {7} +35,37c27,29 +< x ∈ [-2147483647..2147483647] +< y ∈ [-2147483648..2147483646] +< z ∈ [-2147483642..2147483647] +--- +> x ∈ [-2147483646..2147483642] +> y ∈ [-2147483648..2147483640] +> z ∈ [-2147483641..2147483647] +49,50c41,42 +< r1 ∈ [--..--] +< r2 ∈ [--..--] +--- +> r1 ∈ {2} +> r2 ∈ {7} +53,55c45,47 +< x ∈ [-2147483647..2147483647] +< y ∈ [-2147483648..2147483646] +< z ∈ [-2147483642..2147483647] +--- +> x ∈ [-2147483646..2147483642] +> y ∈ [-2147483648..2147483640] +> z ∈ [-2147483641..2147483647] +diff tests/value/oracle/relations.res.oracle tests/value/oracle_octagons/relations.res.oracle +80,81c80,82 +< e ∈ [--..--] +< f ∈ [--..--] +--- +> e ∈ {1} +> f[bits 0 to 7] ∈ {1; 4} +> [bits 8 to 31] ∈ [--..--] +diff tests/value/oracle/relations2.res.oracle tests/value/oracle_octagons/relations2.res.oracle +25c25 +< len ∈ [--..--] +--- +> len ∈ [0..1023] +36,37c36 +< [eva] tests/value/relations2.i:17: +< Frama_C_show_each_end: [0..4294967295], [0..64] +--- +> [eva] tests/value/relations2.i:17: Frama_C_show_each_end: [0..1023], [0..64] +59c58 +< n ∈ [0..512] +--- +> n ∈ [1..512] +69,71d67 +< [eva:alarm] tests/value/relations2.i:34: Warning: +< accessing out of bounds index. +< assert (unsigned int)(i - (unsigned int)(t + 1)) < 514; +80c76 +< n ∈ [0..512] +--- +> n ∈ [1..512] +97c93 +< n ∈ [0..512] +--- +> n ∈ [1..512] +140c136 +< len ∈ [--..--] +--- +> len ∈ [0..1023] +diff tests/value/oracle/semaphore.res.oracle tests/value/oracle_octagons/semaphore.res.oracle +65c65 +< c ∈ {-26; -1} +--- +> c ∈ {-1} +diff tests/value/oracle/struct2.res.oracle tests/value/oracle_octagons/struct2.res.oracle +81,84d80 +< accessing out of bounds index. assert 0 ≤ (int)(i + j); +< [eva:alarm] tests/value/struct2.i:185: Warning: +< accessing out of bounds index. assert (int)(i + j) < 2; +< [eva:alarm] tests/value/struct2.i:185: Warning: +106d101 +< [scope:rm_asserts] removing 2 assertion(s) +diff tests/value/oracle/test.0.res.oracle tests/value/oracle_octagons/test.0.res.oracle +17,18d16 +< [eva:alarm] tests/value/test.i:11: Warning: +< signed overflow. assert j + ecart ≤ 2147483647; +29c27 +< j ∈ [-1073741822..1] +--- +> j ∈ {-1; 0; 1} +diff tests/value/oracle/unroll.res.oracle tests/value/oracle_octagons/unroll.res.oracle +22c22 +< G ∈ [17739..2147483647] +--- +> G ∈ [17854..2147483647] +diff tests/value/oracle/unroll_simple.res.oracle tests/value/oracle_octagons/unroll_simple.res.oracle +17c17 +< G ∈ [8772..2147483647] +--- +> G ∈ [8896..2147483647] diff --git a/tests/value/octagons.c b/tests/value/octagons.c new file mode 100644 index 0000000000000000000000000000000000000000..6d98523df71429efead57e87dd17633ea4ca4560 --- /dev/null +++ b/tests/value/octagons.c @@ -0,0 +1,196 @@ +/* run.config* + STDOPT: +" -eva-octagon-domain -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue" +*/ + +#include <__fc_builtin.h> + +volatile int undet; + +/* Minimal example from the Eva user manual. */ +void demo () { + int y = undet; + int k = Frama_C_interval(0, 10); + int x = y - k; + int r = x + 3 - y; // r \in [-7..3] + int t; + if (y > 15) + t = x; // t \in [6..] +} + +/* Same example as [demo] but with other integer types. */ +void integer_types () { + unsigned int k, x, y, r, t; + y = undet; + k = Frama_C_interval(0, 10); + x = y - k; // No octagon inferred as [y - k] may overflow. + r = x + 3 - y; + if (y > 15) + t = x; + Frama_C_show_each_unreduced_unsigned(r, t); + char ck, cx, cy, cr, ct; + cy = undet; + ck = Frama_C_interval(0, 10); + cx = cy - ck; // An octagon should be inferred despite the casts to int. + cr = cx + 3 - cy; + if (cy > 15) + ct = cx; + Frama_C_show_each_reduced_char(cr, ct); +} + +/* A test with multiple mathematical operations to complicate the inference + and use of octagons. */ +void arith () { + int k = Frama_C_interval(0, 4); + int a, b, x, y, r; + /* 1. Infer octagons from assignments. */ + a = Frama_C_interval(5, 25); + b = Frama_C_interval(-12, 12); + x = 1 - (a + 2*k - 4); // x + a ∈ [-3..5] + y = 4*4 - k + (1 + b); // y - b ∈ [13..17] + /* 1.1 Use octagons in the evaluation of expressions. */ + r = 2 * (10 - (b - 1 - y) - (x - 2 + a)); // r ∈ [42..66] + Frama_C_show_each_precise(r); + r = 2 * (10 - (b + x - 3 - y + a)); // r ∈ [42..66] + Frama_C_show_each_imprecise(r); + k = Frama_C_interval(0, 4); + /* 1.1 Use octagons to propagate variable reductions. */ + if (12 - x < (k+1)*3) { // x > -3 + r = 10 * a; // so a < 8 + Frama_C_show_each(r); // {50; 60; 70} + } + /* 2. Infer octagons from conditions. */ + a = Frama_C_interval(-1024, 1024); + b = Frama_C_interval(-1024, 1024); + if (20*k - a - 17 < 5 - b + (1 << 3) // a - b > -30 + && a + (k+6)/2 - b <= 32) { // a - b <= 29 + r = b - a; + Frama_C_show_each(r); // [-29..29] + } + if (a < b && b <= a) + Frama_C_show_each_BOTTOM(a, b); +} + +/* Tests the join of the octagon domain. */ +void join () { + int a, b, r; + int k = Frama_C_interval(-1, 4); + if (undet) { + a = undet; + b = a + k; + } else { + a = Frama_C_interval(-32, -10); + b = k * 5; + } + // In both cases, we have b - a >= -1. The "else" branch was more precise. + r = b - a + 1; + Frama_C_show_each_join_positive(r); + if (undet) { + a = undet; + b = - (a + k); + } else { + a = Frama_C_interval(-32, -10); + b = k * 5; + } + // In both cases, we have b + a <= 10. The "then" branch was more precise. + r = b + a - 10; + Frama_C_show_each_join_negative(r); +} + +/* Tests the octagon domain within loops. */ +void loop () { + int k = Frama_C_interval(-8, 8); + int a = Frama_C_interval(-1024, 1024); + int b = a + 1; + int c = a + 1; + int d = a + k; + for (int i = 0; i < 421; i++) { + a = a + 2; + b = b + 2; // The relation between a and b should be maintained in the loop. + c = c + 1; // The relation between a and c should be lost in the loop. + d = a + k; // This relation should be maintained. + } + int d1 = b - a; + int d2 = c - a; + int d3 = d - a; + Frama_C_show_each_singleton_1(d1); + Frama_C_show_each_imprecise(d2); + Frama_C_show_each_precise(d3); +} + +/* Tests the soundness of the octagon domain in presence of pointers. */ +void pointers () { + int x, y, r; + int *px = &x, *pr = &r; + x = Frama_C_interval(-1024, 1024); + y = x + 1; + r = y - x; + Frama_C_show_each_singleton_1(r); + *px = Frama_C_interval(-1024, 1024); + Frama_C_show_each_singleton_1(r); + *pr = Frama_C_interval(-1024, 1024); + Frama_C_show_each_unknown(r); + r = y - x; + Frama_C_show_each_unknown(r); + y = x + 2; + r = y - x; + Frama_C_show_each_singleton_2(r); +} + +/* Tests the saturation of octagons: inference of a relation between (x, z) + from relations between (x, y) and between (y, z). */ +void saturate () { + int k = Frama_C_interval(-6, 4); + int x = Frama_C_interval(-1024, 1024); + int y = k - x; + int z = y + 1; + int result = - z - x; // result == k + 1 + Frama_C_show_each_saturate(result); // ∈ [-5..5] +} + +int diff (int x, int y) { return x - y; } +int neg (int x) { return -x; } + +/* Tests the propagation of octagons through function calls. */ +void interprocedural () { + int a = Frama_C_interval(-4, 12); + int b = Frama_C_interval(-4, 12); + int neg_a = neg(a); + int neg_b = neg(b); + /* [r1] is the direct difference [a-b], [r2] uses the result of the function + [neg] (and thus need the octagon inferred in [neg]), and [r3] calls the + function [diff] (and the analysis of [diff] needs the octagons inferred + here about a and b). */ + int r1, r2, r3; + if (a > b) { + r1 = a - b; + r2 = a + neg_b; + r3 = diff (a, b); + } else { + r1 = b - a; + r2 = b + neg_a; + r3 = diff (b, a); + } + /* With the interprocedural octagons, r1, r2 and r3 must be equally precise. */ + Frama_C_show_each_equal(r1, r2, r3); +} + +/* Prints the octagons state. */ +void dump () { + char k = Frama_C_interval(0, 8); + char a = undet; + char b = a + k; + char c = b - k; + Frama_C_dump_each(); +} + +void main () { + demo (); + integer_types (); + arith (); + join (); + loop (); + pointers (); + saturate (); + interprocedural (); + dump (); +} diff --git a/tests/value/oracle/auto_loop_unroll.0.res.oracle b/tests/value/oracle/auto_loop_unroll.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..359bdb60f2fc65fdc7521795c3637c8ef6d68cbd --- /dev/null +++ b/tests/value/oracle/auto_loop_unroll.0.res.oracle @@ -0,0 +1,297 @@ +[kernel] Parsing tests/value/auto_loop_unroll.c (with preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + undet ∈ [--..--] + g ∈ {0} +[eva] computing for function simple_loops <- main. + Called from tests/value/auto_loop_unroll.c:189. +[eva] tests/value/auto_loop_unroll.c:24: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:25: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:27: Frama_C_show_each_auto: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:30: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:31: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:33: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:38: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:39: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:41: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:46: + Trace partitioning superposing up to 100 states +[eva] tests/value/auto_loop_unroll.c:49: Frama_C_show_each_singleton: {100} +[eva] Recording results for simple_loops +[eva] Done for function simple_loops +[eva] computing for function various_loops <- main. + Called from tests/value/auto_loop_unroll.c:190. +[eva] tests/value/auto_loop_unroll.c:57: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:58: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:59: Frama_C_show_each_64: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:62: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:63: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:64: Frama_C_show_each_40: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:67: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:69: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:72: Frama_C_show_each_80: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:75: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:76: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:82: + Frama_C_show_each_32_80: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:85: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:86: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:90: + Frama_C_show_each_11_111: [0..2147483647] +[eva] computing for function Frama_C_interval <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:94. +[eva] using specification for function Frama_C_interval +[eva] tests/value/auto_loop_unroll.c:94: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/auto_loop_unroll.c:95: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:96: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:97: + Frama_C_show_each_40_50: [0..2147483647] +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] tests/value/auto_loop_unroll.c:100: starting to merge loop iterations +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:103. +[eva] Recording results for incr +[eva] Done for function incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] tests/value/auto_loop_unroll.c:102: Reusing old results for call to incr +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:103. +[eva] Recording results for incr +[eva] Done for function incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva:alarm] tests/value/auto_loop_unroll.c:14: Warning: + signed overflow. assert g + 1 ≤ 2147483647; +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] tests/value/auto_loop_unroll.c:102: Reusing old results for call to incr +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:103. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:101: Reusing old results for call to incr_g +[eva] tests/value/auto_loop_unroll.c:102: Reusing old results for call to incr +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:103. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:101: Reusing old results for call to incr_g +[eva] tests/value/auto_loop_unroll.c:102: Reusing old results for call to incr +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:103. +[eva:alarm] tests/value/auto_loop_unroll.c:18: Warning: + signed overflow. assert i + 1 ≤ 2147483647; +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:105: Frama_C_show_each_25: [0..2147483647] +[eva:loop-unroll] tests/value/auto_loop_unroll.c:110: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:109: starting to merge loop iterations +[eva] tests/value/auto_loop_unroll.c:110: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:111: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:114: Frama_C_show_each_120: [0..2147483647] +[eva] Recording results for various_loops +[eva] Done for function various_loops +[eva] computing for function complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:191. +[eva] tests/value/auto_loop_unroll.c:124: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:126: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:128: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:132: starting to merge loop iterations +[eva] tests/value/auto_loop_unroll.c:133: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:134: Warning: + signed overflow. assert i + 1 ≤ 2147483647; +[eva:alarm] tests/value/auto_loop_unroll.c:137: Warning: + signed overflow. assert i + 1 ≤ 2147483647; +[eva:alarm] tests/value/auto_loop_unroll.c:136: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:139: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:143: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:146: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:148: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:151: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:156: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:158: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:163: Reusing old results for call to incr_g +[eva] tests/value/auto_loop_unroll.c:162: starting to merge loop iterations +[eva] computing for function incr_g <- complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:163. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr_g <- complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:163. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr_g <- complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:163. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] tests/value/auto_loop_unroll.c:163: Reusing old results for call to incr_g +[eva] tests/value/auto_loop_unroll.c:163: Reusing old results for call to incr_g +[eva:alarm] tests/value/auto_loop_unroll.c:165: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:167: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:172: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:174: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:176: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:180: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:182: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:184: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] Recording results for complex_loops +[eva] Done for function complex_loops +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function incr: + __retres ∈ [1..2147483647] +[eva:final-states] Values at end of function incr_g: + g ∈ [1..2147483647] +[eva:final-states] Values at end of function complex_loops: + g ∈ {64} + res ∈ [0..2147483647] + i ∈ [0..64] + p ∈ {{ &i }} + t[0] ∈ {0} + [1] ∈ {1} + [2] ∈ {2} + [3] ∈ {3} + [4] ∈ {4} + [5] ∈ {5} + [6] ∈ {6} + [7] ∈ {7} + [8] ∈ {8} + [9] ∈ {9} +[eva:final-states] Values at end of function simple_loops: + res ∈ {100} +[eva:final-states] Values at end of function various_loops: + Frama_C_entropy_source ∈ [--..--] + g ∈ [0..2147483647] + res ∈ {0} + x ∈ {24} + k ∈ [0..10] +[eva:final-states] Values at end of function main: + Frama_C_entropy_source ∈ [--..--] + g ∈ {64} +[from] Computing for function incr +[from] Done for function incr +[from] Computing for function incr_g +[from] Done for function incr_g +[from] Computing for function complex_loops +[from] Done for function complex_loops +[from] Computing for function simple_loops +[from] Done for function simple_loops +[from] Computing for function various_loops +[from] Computing for function Frama_C_interval <-various_loops +[from] Done for function Frama_C_interval +[from] Done for function various_loops +[from] Computing for function main +[from] Done for function main +[from] ====== DEPENDENCIES COMPUTED ====== + These dependencies hold at termination for the executions that terminate: +[from] Function Frama_C_interval: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) + \result FROM Frama_C_entropy_source; min; max +[from] Function incr: + \result FROM i +[from] Function incr_g: + g FROM g +[from] Function complex_loops: + g FROM \nothing +[from] Function simple_loops: + NO EFFECTS +[from] Function various_loops: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) + g FROM g (and SELF) +[from] Function main: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) + g FROM \nothing +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function incr: + __retres +[inout] Inputs for function incr: + \nothing +[inout] Out (internal) for function incr_g: + g +[inout] Inputs for function incr_g: + g +[inout] Out (internal) for function complex_loops: + g; res; i; p; j; t[0..9] +[inout] Inputs for function complex_loops: + undet; g +[inout] Out (internal) for function simple_loops: + res; i; i_0; i_1; i_2 +[inout] Inputs for function simple_loops: + \nothing +[inout] Out (internal) for function various_loops: + Frama_C_entropy_source; g; res; i; i_0; i_1; i_2; i_3; x; k; i_4; i_5; + t; i_6; j +[inout] Inputs for function various_loops: + Frama_C_entropy_source; undet; g +[inout] Out (internal) for function main: + Frama_C_entropy_source; g +[inout] Inputs for function main: + Frama_C_entropy_source; undet; g diff --git a/tests/value/oracle/auto_loop_unroll.1.res.oracle b/tests/value/oracle/auto_loop_unroll.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..775a7323bf9b696e565c5de92ee3cf0bbbcbeda7 --- /dev/null +++ b/tests/value/oracle/auto_loop_unroll.1.res.oracle @@ -0,0 +1,431 @@ +[kernel] Parsing tests/value/auto_loop_unroll.c (with preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + undet ∈ [--..--] + g ∈ {0} +[eva] computing for function simple_loops <- main. + Called from tests/value/auto_loop_unroll.c:189. +[eva:loop-unroll] tests/value/auto_loop_unroll.c:24: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:24: + Trace partitioning superposing up to 100 states +[eva] tests/value/auto_loop_unroll.c:27: Frama_C_show_each_auto: {100} +[eva] tests/value/auto_loop_unroll.c:30: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:31: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:33: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:38: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:39: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:41: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:49: Frama_C_show_each_singleton: {100} +[eva] Recording results for simple_loops +[eva] Done for function simple_loops +[eva] computing for function various_loops <- main. + Called from tests/value/auto_loop_unroll.c:190. +[eva:loop-unroll] tests/value/auto_loop_unroll.c:57: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:59: Frama_C_show_each_64: {64} +[eva:loop-unroll] tests/value/auto_loop_unroll.c:62: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:64: Frama_C_show_each_40: {40} +[eva:loop-unroll] tests/value/auto_loop_unroll.c:67: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:72: Frama_C_show_each_80: {80} +[eva:loop-unroll] tests/value/auto_loop_unroll.c:75: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:75: + Trace partitioning superposing up to 100 states +[eva] tests/value/auto_loop_unroll.c:82: Frama_C_show_each_32_80: [32..80] +[eva:loop-unroll] tests/value/auto_loop_unroll.c:85: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:90: Frama_C_show_each_11_111: [11..111] +[eva] computing for function Frama_C_interval <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:94. +[eva] using specification for function Frama_C_interval +[eva] tests/value/auto_loop_unroll.c:94: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva:loop-unroll] tests/value/auto_loop_unroll.c:95: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:97: Frama_C_show_each_40_50: [40..50] +[eva:loop-unroll] tests/value/auto_loop_unroll.c:100: Automatic loop unrolling. +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] computing for function incr_g <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:101. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr <- various_loops <- main. + Called from tests/value/auto_loop_unroll.c:102. +[eva] Recording results for incr +[eva] Done for function incr +[eva] tests/value/auto_loop_unroll.c:103: Reusing old results for call to incr +[eva] tests/value/auto_loop_unroll.c:105: Frama_C_show_each_25: {25} +[eva:loop-unroll] tests/value/auto_loop_unroll.c:109: Automatic loop unrolling. +[eva:loop-unroll] tests/value/auto_loop_unroll.c:110: Automatic loop unrolling. +[eva] tests/value/auto_loop_unroll.c:114: Frama_C_show_each_120: {120} +[eva] Recording results for various_loops +[eva] Done for function various_loops +[eva] computing for function complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:191. +[eva] tests/value/auto_loop_unroll.c:124: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:126: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:128: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:132: starting to merge loop iterations +[eva] tests/value/auto_loop_unroll.c:133: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:134: Warning: + signed overflow. assert i + 1 ≤ 2147483647; +[eva:alarm] tests/value/auto_loop_unroll.c:137: Warning: + signed overflow. assert i + 1 ≤ 2147483647; +[eva:alarm] tests/value/auto_loop_unroll.c:136: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:139: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:143: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:146: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:148: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:151: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:156: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:158: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:163: Reusing old results for call to incr_g +[eva] tests/value/auto_loop_unroll.c:162: starting to merge loop iterations +[eva] computing for function incr_g <- complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:163. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr_g <- complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:163. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] computing for function incr_g <- complex_loops <- main. + Called from tests/value/auto_loop_unroll.c:163. +[eva] Recording results for incr_g +[eva] Done for function incr_g +[eva] tests/value/auto_loop_unroll.c:163: Reusing old results for call to incr_g +[eva] tests/value/auto_loop_unroll.c:163: Reusing old results for call to incr_g +[eva:alarm] tests/value/auto_loop_unroll.c:165: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:167: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:172: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:174: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:176: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] tests/value/auto_loop_unroll.c:180: starting to merge loop iterations +[eva:alarm] tests/value/auto_loop_unroll.c:182: Warning: + signed overflow. assert res + 1 ≤ 2147483647; +[eva] tests/value/auto_loop_unroll.c:184: + Frama_C_show_each_imprecise: [0..2147483647] +[eva] Recording results for complex_loops +[eva] Done for function complex_loops +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function incr: + __retres ∈ [1..25] +[eva:final-states] Values at end of function incr_g: + g ∈ [1..63] +[eva:final-states] Values at end of function complex_loops: + g ∈ {64} + res ∈ [0..2147483647] + i ∈ [0..64] + p ∈ {{ &i }} + t[0] ∈ {0} + [1] ∈ {1} + [2] ∈ {2} + [3] ∈ {3} + [4] ∈ {4} + [5] ∈ {5} + [6] ∈ {6} + [7] ∈ {7} + [8] ∈ {8} + [9] ∈ {9} +[eva:final-states] Values at end of function simple_loops: + res ∈ {100} +[eva:final-states] Values at end of function various_loops: + Frama_C_entropy_source ∈ [--..--] + g ∈ {25} + res ∈ {0} + x ∈ {24} + k ∈ [0..10] +[eva:final-states] Values at end of function main: + Frama_C_entropy_source ∈ [--..--] + g ∈ {64} +[from] Computing for function incr +[from] Done for function incr +[from] Computing for function incr_g +[from] Done for function incr_g +[from] Computing for function complex_loops +[from] Done for function complex_loops +[from] Computing for function simple_loops +[from] Done for function simple_loops +[from] Computing for function various_loops +[from] Computing for function Frama_C_interval <-various_loops +[from] Done for function Frama_C_interval +[from] Done for function various_loops +[from] Computing for function main +[from] Done for function main +[from] ====== DEPENDENCIES COMPUTED ====== + These dependencies hold at termination for the executions that terminate: +[from] Function Frama_C_interval: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) + \result FROM Frama_C_entropy_source; min; max +[from] Function incr: + \result FROM i +[from] Function incr_g: + g FROM g +[from] Function complex_loops: + g FROM \nothing +[from] Function simple_loops: + NO EFFECTS +[from] Function various_loops: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) + g FROM g (and SELF) +[from] Function main: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) + g FROM \nothing +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function incr: + __retres +[inout] Inputs for function incr: + \nothing +[inout] Out (internal) for function incr_g: + g +[inout] Inputs for function incr_g: + g +[inout] Out (internal) for function complex_loops: + g; res; i; p; j; t[0..9] +[inout] Inputs for function complex_loops: + undet; g +[inout] Out (internal) for function simple_loops: + res; i; i_0; i_1; i_2 +[inout] Inputs for function simple_loops: + \nothing +[inout] Out (internal) for function various_loops: + Frama_C_entropy_source; g; res; i; i_0; i_1; i_2; i_3; x; k; i_4; i_5; + t; i_6; j +[inout] Inputs for function various_loops: + Frama_C_entropy_source; undet; g +[inout] Out (internal) for function main: + Frama_C_entropy_source; g +[inout] Inputs for function main: + Frama_C_entropy_source; undet; g diff --git a/tests/value/oracle/octagons.res.oracle b/tests/value/oracle/octagons.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2f2626a65ffa2d0009b042400cd207ba02de8264 --- /dev/null +++ b/tests/value/oracle/octagons.res.oracle @@ -0,0 +1,407 @@ +[kernel] Parsing tests/value/octagons.c (with preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + undet ∈ [--..--] +[eva] computing for function demo <- main. + Called from tests/value/octagons.c:187. +[eva] computing for function Frama_C_interval <- demo <- main. + Called from tests/value/octagons.c:12. +[eva] using specification for function Frama_C_interval +[eva] tests/value/octagons.c:12: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva:alarm] tests/value/octagons.c:13: Warning: + signed overflow. assert -2147483648 ≤ y - k; +[eva:alarm] tests/value/octagons.c:14: Warning: + signed overflow. assert x + 3 ≤ 2147483647; +[eva] Recording results for demo +[eva] Done for function demo +[eva] computing for function integer_types <- main. + Called from tests/value/octagons.c:188. +[eva] computing for function Frama_C_interval <- integer_types <- main. + Called from tests/value/octagons.c:24. +[eva] tests/value/octagons.c:24: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:29: + Frama_C_show_each_unreduced_unsigned: [0..4294967295], [0..4294967295] +[eva] computing for function Frama_C_interval <- integer_types <- main. + Called from tests/value/octagons.c:32. +[eva] tests/value/octagons.c:32: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:37: + Frama_C_show_each_reduced_char: [-7..3], [6..127] +[eva] Recording results for integer_types +[eva] Done for function integer_types +[eva] computing for function arith <- main. + Called from tests/value/octagons.c:189. +[eva] computing for function Frama_C_interval <- arith <- main. + Called from tests/value/octagons.c:43. +[eva] tests/value/octagons.c:43: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- arith <- main. + Called from tests/value/octagons.c:46. +[eva] tests/value/octagons.c:46: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- arith <- main. + Called from tests/value/octagons.c:47. +[eva] tests/value/octagons.c:47: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:52: Frama_C_show_each_precise: [42..66],0%2 +[eva] tests/value/octagons.c:54: Frama_C_show_each_imprecise: [2..106],0%2 +[eva] computing for function Frama_C_interval <- arith <- main. + Called from tests/value/octagons.c:55. +[eva] tests/value/octagons.c:55: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:59: Frama_C_show_each: {50; 60; 70} +[eva] computing for function Frama_C_interval <- arith <- main. + Called from tests/value/octagons.c:62. +[eva] tests/value/octagons.c:62: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- arith <- main. + Called from tests/value/octagons.c:63. +[eva] tests/value/octagons.c:63: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:67: Frama_C_show_each: [-29..29] +[eva] Recording results for arith +[eva] Done for function arith +[eva] computing for function join <- main. + Called from tests/value/octagons.c:190. +[eva] computing for function Frama_C_interval <- join <- main. + Called from tests/value/octagons.c:76. +[eva] tests/value/octagons.c:76: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva:alarm] tests/value/octagons.c:79: Warning: + signed overflow. assert -2147483648 ≤ a + k; +[eva:alarm] tests/value/octagons.c:79: Warning: + signed overflow. assert a + k ≤ 2147483647; +[eva] computing for function Frama_C_interval <- join <- main. + Called from tests/value/octagons.c:81. +[eva] tests/value/octagons.c:81: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:86: Frama_C_show_each_join_positive: [0..53] +[eva:alarm] tests/value/octagons.c:89: Warning: + signed overflow. assert -2147483648 ≤ a + k; +[eva:alarm] tests/value/octagons.c:89: Warning: + signed overflow. assert a + k ≤ 2147483647; +[eva:alarm] tests/value/octagons.c:89: Warning: + signed overflow. assert -((int)(a + k)) ≤ 2147483647; +[eva] computing for function Frama_C_interval <- join <- main. + Called from tests/value/octagons.c:91. +[eva] tests/value/octagons.c:91: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:96: Frama_C_show_each_join_negative: [-47..0] +[eva] Recording results for join +[eva] Done for function join +[eva] computing for function loop <- main. + Called from tests/value/octagons.c:191. +[eva] computing for function Frama_C_interval <- loop <- main. + Called from tests/value/octagons.c:101. +[eva] tests/value/octagons.c:101: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- loop <- main. + Called from tests/value/octagons.c:102. +[eva] tests/value/octagons.c:102: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:106: starting to merge loop iterations +[eva:alarm] tests/value/octagons.c:107: Warning: + signed overflow. assert a + 2 ≤ 2147483647; +[eva:alarm] tests/value/octagons.c:108: Warning: + signed overflow. assert b + 2 ≤ 2147483647; +[eva:alarm] tests/value/octagons.c:110: Warning: + signed overflow. assert a + k ≤ 2147483647; +[eva:alarm] tests/value/octagons.c:113: Warning: + signed overflow. assert -2147483648 ≤ c - a; +[eva] tests/value/octagons.c:115: Frama_C_show_each_singleton_1: {1} +[eva] tests/value/octagons.c:116: Frama_C_show_each_imprecise: [-2147483648..1] +[eva] tests/value/octagons.c:117: Frama_C_show_each_precise: [-8..8] +[eva] Recording results for loop +[eva] Done for function loop +[eva] computing for function pointers <- main. + Called from tests/value/octagons.c:192. +[eva] computing for function Frama_C_interval <- pointers <- main. + Called from tests/value/octagons.c:124. +[eva] tests/value/octagons.c:124: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:127: Frama_C_show_each_singleton_1: {1} +[eva] computing for function Frama_C_interval <- pointers <- main. + Called from tests/value/octagons.c:128. +[eva] tests/value/octagons.c:128: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:129: Frama_C_show_each_singleton_1: {1} +[eva] computing for function Frama_C_interval <- pointers <- main. + Called from tests/value/octagons.c:130. +[eva] tests/value/octagons.c:130: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:131: Frama_C_show_each_unknown: [-1024..1024] +[eva] tests/value/octagons.c:133: Frama_C_show_each_unknown: [-2047..2049] +[eva] tests/value/octagons.c:136: Frama_C_show_each_singleton_2: {2} +[eva] Recording results for pointers +[eva] Done for function pointers +[eva] computing for function saturate <- main. + Called from tests/value/octagons.c:193. +[eva] computing for function Frama_C_interval <- saturate <- main. + Called from tests/value/octagons.c:142. +[eva] tests/value/octagons.c:142: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- saturate <- main. + Called from tests/value/octagons.c:143. +[eva] tests/value/octagons.c:143: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:147: Frama_C_show_each_saturate: [-5..5] +[eva] Recording results for saturate +[eva] Done for function saturate +[eva] computing for function interprocedural <- main. + Called from tests/value/octagons.c:194. +[eva] computing for function Frama_C_interval <- interprocedural <- main. + Called from tests/value/octagons.c:155. +[eva] tests/value/octagons.c:155: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- interprocedural <- main. + Called from tests/value/octagons.c:156. +[eva] tests/value/octagons.c:156: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function neg <- interprocedural <- main. + Called from tests/value/octagons.c:157. +[eva] Recording results for neg +[eva] Done for function neg +[eva] computing for function neg <- interprocedural <- main. + Called from tests/value/octagons.c:158. +[eva] Recording results for neg +[eva] Done for function neg +[eva] computing for function diff <- interprocedural <- main. + Called from tests/value/octagons.c:167. +[eva] Recording results for diff +[eva] Done for function diff +[eva] computing for function diff <- interprocedural <- main. + Called from tests/value/octagons.c:171. +[eva] Recording results for diff +[eva] Done for function diff +[eva] tests/value/octagons.c:174: + Frama_C_show_each_equal: [0..16], [0..16], [0..16] +[eva] Recording results for interprocedural +[eva] Done for function interprocedural +[eva] computing for function dump <- main. + Called from tests/value/octagons.c:195. +[eva] computing for function Frama_C_interval <- dump <- main. + Called from tests/value/octagons.c:179. +[eva] tests/value/octagons.c:179: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] tests/value/octagons.c:183: + Frama_C_dump_each: + # Octagon domain: + {[ k - tmp ∈ {0} + a - b ∈ [-8..0] + b - c ∈ [0..8] + a - c ∈ [-8..8] + ]} + ==END OF DUMP== +[eva] Recording results for dump +[eva] Done for function dump +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function arith: + Frama_C_entropy_source ∈ [--..--] + k ∈ {0; 1; 2; 3; 4} + a ∈ [-1024..1024] + b ∈ [-1024..1024] + x ∈ [-28..0] + y ∈ [1..29] + r ∈ [-29..106] +[eva:final-states] Values at end of function demo: + Frama_C_entropy_source ∈ [--..--] + y ∈ [--..--] + k ∈ [0..10] + x ∈ [-2147483648..2147483644] + r ∈ [-7..3] + t ∈ [6..2147483644] or UNINITIALIZED +[eva:final-states] Values at end of function diff: + __retres ∈ [0..16] +[eva:final-states] Values at end of function dump: + Frama_C_entropy_source ∈ [--..--] + k ∈ [0..8] + a ∈ [--..--] + b ∈ [--..--] + c ∈ [--..--] +[eva:final-states] Values at end of function integer_types: + Frama_C_entropy_source ∈ [--..--] + k ∈ [0..10] + x ∈ [--..--] + y ∈ [--..--] + r ∈ [--..--] + t ∈ [--..--] or UNINITIALIZED + ck ∈ [0..10] + cx ∈ [--..--] + cy ∈ [--..--] + cr ∈ [-7..3] + ct ∈ [6..127] or UNINITIALIZED +[eva:final-states] Values at end of function join: + Frama_C_entropy_source ∈ [--..--] + a ∈ [--..--] + b ∈ [-2147483647..2147483647] + r ∈ [-47..0] + k ∈ {-1; 0; 1; 2; 3; 4} +[eva:final-states] Values at end of function loop: + Frama_C_entropy_source ∈ [--..--] + k ∈ [-8..8] + a ∈ [-1024..2147483647] + b ∈ [-1023..2147483647] + c ∈ [-1023..2147483647] + d ∈ [-1032..2147483647] + d1 ∈ {1} + d2 ∈ [-2147483648..1] + d3 ∈ [-8..8] +[eva:final-states] Values at end of function neg: + __retres ∈ [-12..4] +[eva:final-states] Values at end of function interprocedural: + Frama_C_entropy_source ∈ [--..--] + a ∈ [-4..12] + b ∈ [-4..12] + neg_a ∈ [-12..4] + neg_b ∈ [-12..4] + r1 ∈ [0..16] + r2 ∈ [0..16] + r3 ∈ [0..16] +[eva:final-states] Values at end of function pointers: + Frama_C_entropy_source ∈ [--..--] + x ∈ [-1024..1024] + y ∈ [-1022..1026] + r ∈ {2} + px ∈ {{ &x }} + pr ∈ {{ &r }} +[eva:final-states] Values at end of function saturate: + Frama_C_entropy_source ∈ [--..--] + k ∈ [-6..4] + x ∈ [-1024..1024] + y ∈ [-1030..1028] + z ∈ [-1029..1029] + result ∈ [-5..5] +[eva:final-states] Values at end of function main: + Frama_C_entropy_source ∈ [--..--] +[from] Computing for function arith +[from] Computing for function Frama_C_interval <-arith +[from] Done for function Frama_C_interval +[from] Done for function arith +[from] Computing for function demo +[from] Done for function demo +[from] Computing for function diff +[from] Done for function diff +[from] Computing for function dump +[from] Done for function dump +[from] Computing for function integer_types +[from] Done for function integer_types +[from] Computing for function join +[from] Done for function join +[from] Computing for function loop +[from] Done for function loop +[from] Computing for function neg +[from] Done for function neg +[from] Computing for function interprocedural +[from] Done for function interprocedural +[from] Computing for function pointers +[from] Done for function pointers +[from] Computing for function saturate +[from] Done for function saturate +[from] Computing for function main +[from] Done for function main +[from] ====== DEPENDENCIES COMPUTED ====== + These dependencies hold at termination for the executions that terminate: +[from] Function Frama_C_interval: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) + \result FROM Frama_C_entropy_source; min; max +[from] Function arith: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function demo: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function diff: + \result FROM x; y +[from] Function dump: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function integer_types: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function join: + Frama_C_entropy_source FROM Frama_C_entropy_source; undet (and SELF) +[from] Function loop: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function neg: + \result FROM x +[from] Function interprocedural: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function pointers: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function saturate: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] Function main: + Frama_C_entropy_source FROM Frama_C_entropy_source; undet (and SELF) +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function arith: + Frama_C_entropy_source; k; a; b; x; y; r +[inout] Inputs for function arith: + Frama_C_entropy_source +[inout] Out (internal) for function demo: + Frama_C_entropy_source; y; k; x; r; t +[inout] Inputs for function demo: + Frama_C_entropy_source; undet +[inout] Out (internal) for function diff: + __retres +[inout] Inputs for function diff: + \nothing +[inout] Out (internal) for function dump: + Frama_C_entropy_source; k; tmp; a; b; c +[inout] Inputs for function dump: + Frama_C_entropy_source; undet +[inout] Out (internal) for function integer_types: + Frama_C_entropy_source; k; x; y; r; t; tmp; ck; cx; cy; cr; ct; tmp_0 +[inout] Inputs for function integer_types: + Frama_C_entropy_source; undet +[inout] Out (internal) for function join: + Frama_C_entropy_source; a; b; r; k +[inout] Inputs for function join: + Frama_C_entropy_source; undet +[inout] Out (internal) for function loop: + Frama_C_entropy_source; k; a; b; c; d; i; d1; d2; d3 +[inout] Inputs for function loop: + Frama_C_entropy_source +[inout] Out (internal) for function neg: + __retres +[inout] Inputs for function neg: + \nothing +[inout] Out (internal) for function interprocedural: + Frama_C_entropy_source; a; b; neg_a; neg_b; r1; r2; r3 +[inout] Inputs for function interprocedural: + Frama_C_entropy_source +[inout] Out (internal) for function pointers: + Frama_C_entropy_source; x; y; r; px; pr +[inout] Inputs for function pointers: + Frama_C_entropy_source +[inout] Out (internal) for function saturate: + Frama_C_entropy_source; k; x; y; z; result +[inout] Inputs for function saturate: + Frama_C_entropy_source +[inout] Out (internal) for function main: + Frama_C_entropy_source +[inout] Inputs for function main: + Frama_C_entropy_source; undet diff --git a/tests/value/oracle/summary.0.res.oracle b/tests/value/oracle/summary.0.res.oracle index 18d328c7689fe090af56982f7196f186335068d2..fe68cdf367b9ebc43d0a69b2de88ec79fd1a6378 100644 --- a/tests/value/oracle/summary.0.res.oracle +++ b/tests/value/oracle/summary.0.res.oracle @@ -12,7 +12,7 @@ [eva] ====== VALUES COMPUTED ====== [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - No function to be analyzed. + 0 functions analyzed (out of 4): 0% coverage. ---------------------------------------------------------------------------- Some errors and warnings have been raised during the analysis: by the Eva analyzer: 0 errors 0 warnings diff --git a/tests/value/oracle/summary.1.res.oracle b/tests/value/oracle/summary.1.res.oracle index 05e3490c3ef8a52ea6ac273e8d1acadc8a85b390..c3d37ddacc8540eb714fae0b9b041752aa5a0383 100644 --- a/tests/value/oracle/summary.1.res.oracle +++ b/tests/value/oracle/summary.1.res.oracle @@ -12,7 +12,7 @@ [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 1): 100% coverage. + 1 function analyzed (out of 4): 25% coverage. In this function, 1 statements reached (out of 1): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/value/oracle/summary.2.res.oracle b/tests/value/oracle/summary.2.res.oracle index 7326ccc855202f51023362d23a736ca553142729..642453d63930e4727c5d6ac5f842e6f7657f2cce 100644 --- a/tests/value/oracle/summary.2.res.oracle +++ b/tests/value/oracle/summary.2.res.oracle @@ -15,7 +15,7 @@ NON TERMINATING FUNCTION [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 1 function analyzed (out of 2): 50% coverage. + 1 function analyzed (out of 4): 25% coverage. In this function, 1 statements reached (out of 2): 50% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. diff --git a/tests/value/oracle/summary.3.res.oracle b/tests/value/oracle/summary.3.res.oracle index 58a58f35480ae093a3f912184836bb2e09ad129b..800aa84f7f444f248e282ca4458e5872cd1cea8b 100644 --- a/tests/value/oracle/summary.3.res.oracle +++ b/tests/value/oracle/summary.3.res.oracle @@ -73,7 +73,7 @@ [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- - 2 functions analyzed (out of 2): 100% coverage. + 2 functions analyzed (out of 4): 50% coverage. In these functions, 32 statements reached (out of 32): 100% coverage. ---------------------------------------------------------------------------- Some errors and warnings have been raised during the analysis: