diff --git a/.gitattributes b/.gitattributes index e02a50f0e6e9b6515b6078a68ff9ed39722bb0d6..6b41e9483111166dc31ba8e496ab16eaa565536d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -109,6 +109,7 @@ src/plugins/e-acsl/examples/ensuresec/**/*.py -check-indent dune-project header_spec=CEA_LGPL dune header_spec=CEA_LGPL +dune-workspace.* header_spec=CEA_LGPL config* header_spec=CEA_LGPL @@ -198,8 +199,6 @@ README* header_spec=.ignore /bin/sed_get_* header_spec=.ignore -/dev/dune-workspace.* header_spec=.ignore - /dev/docker/*.sh header_spec=.ignore /dev/docker/Dockerfile header_spec=.ignore @@ -215,6 +214,7 @@ README* header_spec=.ignore /doc/MakeLaTeXModern header_spec=.ignore /doc/acsl_tutorial_slides/script header_spec=.ignore /doc/developer/METADOC.txt header_spec=.ignore +/doc/developer/dune-workspace.bench header_spec=.ignore /doc/developer/examples/**/* header_spec=.ignore /doc/developer/tutorial/**/* header_spec=.ignore /doc/qualification/testing header_spec=.ignore @@ -266,7 +266,9 @@ README* header_spec=.ignore /share/win32_installer.iss header_spec=.ignore /share/win32_manual_installation_step.txt header_spec=.ignore /share/compliance/*.json header_spec=.ignore - +/share/machdeps/.machdep_*.validated header_spec=.ignore +/share/machdeps/machdep-schema.yaml header_spec=.ignore +/share/machdeps/machdep_*.yaml header_spec=.ignore /tests/**/* header_spec=.ignore ####################### diff --git a/.gitignore b/.gitignore index fccad8e706ba06202443d4e05fd631b2d1543d15..0d9cfe2b2ecfb4a609ee6d1c3a813c24a3756795 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,8 @@ frama_c_journal.ml /.merlin /headers/hdrck /headers/hdrck.exe +/bin/ivette +.ivette #build /_opam/ @@ -51,6 +53,8 @@ _build /tests/crowbar/test_ghost_cfg /tests/*/*.opt +/.test-errors.log + /dev/fc-time /dev/fc-memuse /bin/ocamldep_transitive_closure @@ -190,12 +194,6 @@ Makefile.plugin.generated /src/kernel_internals/parsing/clexer.ml /src/kernel_internals/parsing/cparser.ml /src/kernel_internals/parsing/cparser.mli -# /src/plugins/callgraph/cg_viewer.ml -/src/plugins/gui/debug_manager.ml -/src/plugins/gui/dgraph_helper.ml -/src/plugins/gui/GSourceView.ml -/src/plugins/gui/GSourceView.mli -/src/plugins/gui/gtk_compat.ml /src/plugins/markdown-report/META # generated tar.gz files diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2b3f95777cc993fbea6088cf52928c941a60c56c..b93b0d75b691d863742a01e4f0f1c2d1baee15b8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -122,7 +122,7 @@ ivette: - node --version - npm --version - yarn --version - - make -C ivette + - make -C ivette check-lint dome-app tags: - docker @@ -139,6 +139,12 @@ e-acsl-tests: script: - ./nix/build-proxy.sh e-acsl-tests +e-acsl-dev-tests: + stage: tests + script: + - ./nix/build-proxy.sh e-acsl-dev-tests + allow_failure: true + .build_template: &eva_template stage: tests script: @@ -216,6 +222,7 @@ external-plugins: "meta", "minimal", "mthread", + "pathcrawler", "security", "volatile" ] diff --git a/Changelog b/Changelog index 1616be29fd88fbe3a00b8b10f78281cd18a8f76c..e619fceeedb77c384c4a7f965b2de3e7359104ff 100644 --- a/Changelog +++ b/Changelog @@ -14,23 +14,60 @@ # '#?nnn' : OLD-BTS entry #nnn # ############################################################################### -################################## +############################################################################### Open Source Release <next-release> -################################## +############################################################################### + +############################################################################### +Open Source Release 27.0 (Cobalt) +############################################################################### +-! Kernel [2023-05-15] New machdep mechanism, based on YAML files. A new + make_machdep.py script allows automatic machdep creation from a + C11-compatible (cross-)compiler. +- Eva [2023-05-04] The octagon domain can now infer relations between + any lvalues of integer or pointer types. +-* Ivette [2023-05-02] Ends properly frama-c process when Ivette is closed. +-* Ivette [2023-05-02] Custom views are correctly saved and reloaded. +-* Eva [2023-05-02] Fixes interpretation of Eva annotations at the end of + a block, and of multiple split annotations after a function call. +- Eva [2023-04-24] When possible, Eva shows the name of enumeration tags + instead of their integer values, in the log and the GUI. +- Aorai [2023-04-24] Allows comments in .ya automata files. +- Aorai [2023-04-24] Supports specification about floating-point variables. +- Ivette [2023-04-24] New callgraph component. +- Ivette [2023-04-07] The values table shows the status of uninitialized + and escaping variables. +- Eva [2023-04-05] Better display of large integer sets for high values + of the -eva-ilevel parameter. +- Ivette [2023-03-31] The values table shows values of function parameters. +- Ivette [2023-03-31] The values table can show the logical status of ACSL + predicates, and the values of C lvalues in these predicates. +o! GUI [2023-03-27] Remove GTK2 bindings. Only support GTK3 as of now. +- Ivette [2023-03-23] Improves function filtering in the left sidebar. +- Ivette [2023-03-23] Better display of dead and non-terminating statements. +-* Eva [2023-03-13] Fixes a soundness bug of the equality domain when + the same equality holds in two programs paths, but involving a + pointer pointing to different variables in the two paths. - Kernel [2023-03-03] Deprecate option -c11 (now enabled by default). +- Ivette [2023-02-15] Shows information about C types in the Inspector. +- Eva [2023-02-06] Fixes performance issues on programs with too many + function calls (more than 20000 callsites). -! Kernel [2023-01-25] Add support for C11's _Generic. Modifies Cabs AST. +-* Eva [2023-01-16] Fixes unsoundness of the bitwise domain on shifts + and casts on big-endian architectures. +- Eva [2023-01-12] Better partitioning splits on ACSL predicates. -############################### +############################################################################### Open Source Release 26.1 (Iron) -############################### +############################################################################### - Logic [2023-01-16] Accept \ghost attribute in logic annotations (##2638) - Logic [2023-01-10] Fix issue in pretty-printing ranges (##2639) -############################### +############################################################################### Open Source Release 26.0 (Iron) -############################### +############################################################################### - Ivette [2022-10-26] After an Eva analysis with taint, the taint status of lvalues is shown in the Inspector component and in Dive graphs. @@ -68,9 +105,9 @@ o! Pdg [2022-07-01] Removed from Db. Use proper Pdg API instead. - Eva [2022-05-11] Avoid false alarms of partially overlapping lvalue assignments when writing a struct array from itself. -#################################### +############################################################################### Open Source Release 25.0 (Manganese) -#################################### +############################################################################### o Kernel [2022-05-03] Prototype of AST comparison between two versions of the same program, via the new option -ast-diff. @@ -108,9 +145,9 @@ o! Kernel [2021-11-29] Integer.pretty does not have the optional argument hexa anymore. Use Integer.pretty_hex or Integer.pp_hex if you want to print integers in hexadecimal format. -################################### +############################################################################### Open Source Release 24.0 (Chromium) -################################### +############################################################################### -* Eva [2022-01-19] Always emits alarms about initialization, escaping pointers and special floating-point values for the arguments of @@ -173,13 +210,13 @@ o Ptests [2021-06-03] Add new PLUGIN directive and new predefined macros. Tainted properties can then be seen in the future GUI Ivette. - Eva [2021-05-11] Support for ACSL predicate \is_infinite. -################################### +############################################################################### Open Source Release 23.1 (Vanadium) -################################### +############################################################################### -################################### +############################################################################### Open Source Release 23.0 (Vanadium) -################################### +############################################################################### -* Kernel [2021-04-26] Do not crash on _Alignof(void): accept or properly reject, depending on machdep. Fixes pub/frama-c#2551 @@ -253,9 +290,9 @@ o Kernel [2020-11-27] Extract builtin-related functions from module Cil Frama_C_dump_each in ghost code. - Metrics [2020-10-27] Add json output in addition to text and html. -################################### +############################################################################### Open Source Release 22.0 (Titanium) -################################### +############################################################################### - MdR [2020-10-19] Update Sarif output to 2.1.0 + prettier URI - Dev [2020-10-20] Support for OCamlGraph 2.0.0 @@ -302,13 +339,13 @@ Open Source Release 22.0 (Titanium) - Eva [2020-05-20] Supports the ACSL mathematical operator \abs - Kernel [2020-05-18] Support for C11's _Noreturn function specifier -################################### +############################################################################### Open Source Release 21.1 (Scandium) -################################### +############################################################################### -################################### +############################################################################### Open Source Release 21.0 (Scandium) -################################### +############################################################################### -* Doc [2020-05-07] Fixes internal refs in generated pdfs (fixes #2505) -* Kernel [2020-05-04] Accept UCN-encoded unicode char in ACSL (fixes #@849) @@ -388,9 +425,9 @@ o! Kernel [2020-02-04] Removed FCBuffer, FCMap and FCSet. Use directly overrides the global option for the given functions; - via /*@ subdivide N; */ annotations on specific statements. -################################## +############################################################################### Open Source Release 20.0 (Calcium) -################################## +############################################################################### - Eva [2019-11-25] In the summary, fixes the number of alarms by category when the RTE plugin is used, and do not count logical @@ -447,9 +484,9 @@ 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 -#################################### +############################################################################### Open Source Release 19.0 (Potassium) -#################################### +############################################################################### -* RTE [2019-05-24] fixes a crash when visiting variable declarations - Eva [2019-04-19] The new annotation /*@ split exp; */ enumerates the @@ -516,9 +553,9 @@ o Kernel [2018-12-11] New functions for retrieving major and minor version -* Kernel [2018-12-04] Fixes AST integrity check wrt volatile accesses -* Kernel [2018-11-21] Fixes #@553 - pretty-printing of basic asm template -################################ +############################################################################### Open Source Release 18.0 (Argon) -################################ +############################################################################### -! Kernel [2018-10-24] Log.error and Log.failure will eventually make Frama-C exit with a non-zero status. Fixes #@552 @@ -627,15 +664,15 @@ o* Ptests [2018-07-02] Do not keep oracles for empty stderr. Fixes #@402 specific code annotations /*@ loop unroll N; */. The new strategy may affect analyses even without loop unrolling. -############################################ +############################################################################### Open Source Release 17.1 (Chlorine-20180502) -############################################ +############################################################################### - Libc [2018-07-05] Fix C++ compatibility for Frama-Clang plug-in -############################################ +############################################################################### Open Source Release 17.0 (Chlorine-20180501) -############################################ +############################################################################### - Eva [2018-04-25] Added scripts and templates to help automate case studies (in $FRAMAC_SHARE/analysis-scripts) @@ -767,9 +804,9 @@ o! Eva [2017-11-09] The Fval module now supports NaN and infinite values. -* Eva [2017-10-27] Fix bug in the handling of non-explicitly volatile fields inside volatile structs or unions -########################################## +############################################################################### Open Source Release 16.0 (Sulfur-20171101) -########################################## +############################################################################### -* Eva [2017-10-27] Fix bugs when evaluating \ìnitialized, \dangling and \separated on addresses of bitfields @@ -900,9 +937,9 @@ o! Kernel [2017-04-27] Completely separate types between Cil_types and - Eva [2017-04-06] More precise evaluation of \initialized and \dangling predicates. -############################################## +############################################################################### Open Source Release 15.0 (Phosphorus-20170501) -############################################## +############################################################################### -* Eva [2017-05-08] Fix widening in the gauges domain, in particular with nested loops and pointers that change base address through @@ -987,9 +1024,9 @@ o! Gui [2017-03-10] Signature change for constructor o* Eva [2016-10-22] Functions Db.Value.fun_set_args and Db.Value.globals_set_initial_state are now compatible with Eva. -########################################### +############################################################################### Open Source Release 14.0 (Silicon-20161101) -########################################### +############################################################################### -*! Eva [2016-10-29] Fix soundness bug on statements with RTE or programmatically-added user assertions (bts #2258). This @@ -1136,9 +1173,9 @@ o Makefile [2016-03-31] Warnings and warn-error are activated only if a file o! Kernel [2016-03-29] Functions Integer.pgcd and Integer.ppcm are now guaranteed to return a positive result. -############################################# +############################################################################### Open Source Release 13.0 (Aluminium-20160502) -############################################# +############################################################################### - Value [2016-04-19] Support for evaluation of predicate \valid_read_string on constant strings. @@ -1311,9 +1348,9 @@ o Ptests [2015-07-29] New EXEC: directive. - Kernel [2015-07-01] New option -remove-projects. - Kernel [2015-06-30] New option -set-project-as-default. -############################################# +############################################################################### Open Source Release 12.0 (Magnesium-20151002) -############################################# +############################################################################### o! Kernel [2016-01-03] Modules Dataflow is deprecated, and will be removed in Aluminium. Module Dataflow2 offers a very similar but simpler @@ -1535,9 +1572,9 @@ o! Kernel [2015-30-01] Fixed bug #!2012 about combining subdividing may avoid the emission of an alarm. - Value [2015-01-21] Support for \subset predicate. -########################################## +############################################################################### Open Source Release 11.0 (Sodium-20150201) -########################################## +############################################################################### - Kernel [2015-02-01] Tests are added to the distrib (make tests). -* Logic [2015-02-09] The ACSL parser accepts qualifiers in logic C types. @@ -1755,9 +1792,9 @@ o Logic [2014-03-04] Annotations.{iter,fold}_all_code_annot are now -* Configure [2014-03-10] fix for autoconf < 2.67 when checking ability of default pre-processor to keep comments -######################################## +############################################################################### Open Source Release 10.0 (Neon-20140301) -######################################## +############################################################################### -* Value [2014-03-04] Fix bug when writing imprecisely in a struct containing a 1-bit wide bitfield (bug #!1671) @@ -2126,15 +2163,15 @@ o! Value [2013-05-03] Remove functions Cvalue.Model.pretty_without_null and reference to the real function. Removed last argument of Cvalue.Model.pretty_filter. -########################################### +############################################################################### Open Source Release 9.2 (Fluorine-20130601) -########################################### +############################################################################### -* Value [2013-06-11] Add missing C library files. -########################################### +############################################################################### Open Source Release 9.1 (Fluorine-20130501) -########################################### +############################################################################### - Value [2013-05-22] Better precision for ^ (bitwise xor) operator when applied on intervals of positive integers @@ -2147,9 +2184,9 @@ o* Kernel [2013-05-06] Fixed Type.pp_ml_name for polymorphic types -* Makefile [2013-05-06] Fixed installation directory of the doc in plug-in's Makefile (bug #1278). -########################################### +############################################################################### Open Source Release 9.0 (Fluorine-20130401) -########################################### +############################################################################### o! Cil [2013-04-11] Remove Cil pretty-printer. Use module Printer instead. The script bin/oxygen2fluorine.sh may be used to @@ -2405,9 +2442,9 @@ o Kernel [2012-09-20] Provide Datatype.triple and Datatype.quadruple o* Kernel [2012-09-20] Fixed consistency check of descriptor when building polymorphic datatypes (fixed bts #1277). -######################################### +############################################################################### Open Source Release 8.0 (Oxygen-20120901) -######################################### +############################################################################### -! Kernel [2012-09-17] Remove useless negative options -no-help, -no-version, -no-print-share-path, -no-print-lib-path and @@ -2786,9 +2823,9 @@ o! Kernel [2011-10-18] Logic_preprocess.file takes an additional parameter, completely invalid. Soundness was not affected (the alarm for whatever made e invalid was present). -########################################### +############################################################################### Open Source Release 7.0 (Nitrogen-20111001) -########################################### +############################################################################### - Rte [2011-10-07] No longer position 'Don't know' statuses - Value [2011-10-07] New alarm for left shift of negative values. @@ -3240,9 +3277,9 @@ o Cil/Logic [2011-02-16] New functions Clexer.is_c_keyword and -* Value [2011-02-09] Changes related to 0., +0., -0., sort of thing. Unwarranted loss of precision fixed. -######################################### +############################################################################### Open Source Release 6.2 (Carbon-20110201) -######################################### +############################################################################### - WP [2011-02-07] Plug-in WP removed from kernel-releases (now an independent plug-in). @@ -3353,17 +3390,17 @@ o* Cil [2010-12-20] Fixed bug #645. Ast_info.constant_expr, ~loc:Cil_datatype.Location.unknown which is most of the time not accurate. -######################################### +############################################################################### Open Source Release 6.1 (Carbon-20101202) -######################################### +############################################################################### -* WP [2010-12-16] Fixed bug #639: no more Coq compilation to shared directory. - WP [2010-12-16] Accessibility of all provers from gui. -######################################### +############################################################################### Open Source Release 6.0 (Carbon-20101201) -######################################### +############################################################################### -! Kernel [2010-12-13] Fixed bug #548: limit.h now syntactically correct. Architectures other than x86_32 still unsupported. @@ -3564,9 +3601,9 @@ o! Kernel [2010-04-22] Ptmap (resp. Ptset) is renamed into Hptmap (Hptset) + Logic [2010-04-13] #!346 Formals have an \old label when used in post conditions -######################################## +############################################################################### Open Source Release 5.0 (Boron-20100401) -######################################## +############################################################################### - Kernel [2010-04-12] Preliminary standard C library in $FRAMAC_SHARE/libc o* Cil [2010-04-12] New hook after Cabs elaboration (fix bug #!446) @@ -3735,9 +3772,9 @@ o! Cil [2009-09-28] pAssigns now prints directly a whole list of assigns - Value [2009-09-25] Improved treatment of "assigns p[..]" clauses in -input -############################################ +############################################################################### Open Source Release 4.2 (Beryllium-20090902) -############################################ +############################################################################### -* Obfuscator [2009-09-23] obfuscator does not lose links between logic and C variables anymore (bts #250). @@ -3787,9 +3824,9 @@ o* Makefile [2009-09-18] Fixed bugs with the use of PLUGIN_EXTRA_BYTE which does not support native dynlink and with ocaml >= 3.11 (bts #224). -############################################ +############################################################################### Open Source Release 4.1 (Beryllium-20090901) -############################################ +############################################################################### -! Syntactic_callgraph [2009-08-27] New design of the callgraph in the GUI. Frama-C now requires ocamlgraph 1.2. @@ -3832,9 +3869,9 @@ o! Cil [2009-06-24] Added 2 components to Cil_types.typ to optimize -* Kernel [2009-06-24] Restore compatibility with ocaml 3.10.2 -* Configure [2009-06-24] Fixed bug with --disable-gui in configure.in -############################################ +############################################################################### Open Source Release 4.0 (Beryllium-20090601) -############################################ +############################################################################### o Value [2009-06-23] New constructor Signed_overflow_alarm for type Alarms.t @@ -4024,9 +4061,9 @@ o! Kernel [2009-01-05] Some changes in API of module Type - Value [2008-12-18] Improved support for state reduction on a memory read. -########################################## +############################################################################### Open Source Release 3.1 (Lithium-20081201) -########################################## +############################################################################### -! GUI [2008-12-09] Improved consistency of some information messages. - Value [2008-12-09] Abstract structs are now supported in @@ -4071,9 +4108,9 @@ o Cil [2008-11-17] New methods for visiting compinfo, enuminfo, o Makefile [2008-11-03] Support for native compilation in Makefile.template (require ocaml >= 3.11). -########################################## +############################################################################### Open Source Release 3.0 (Lithium-20081002) -########################################## +############################################################################### -! Value [2008-10-23] Changed behavior of option -context-valid-pointers to make it more like the @@ -4133,9 +4170,9 @@ o! Kernel [2008-09-11] Refined UnspecifiedSequence information. o! Cil [2008-07-17] AST changes for unspecified sequences (experimental). -* Jessie [2008-07-16] Fixed path problems with binary distributions. -######################################### +############################################################################### Open Source Release 2.0 (Helium-20080701) -######################################### +############################################################################### - Occurrence [2008-07-11] Occurrences of a variable can be computed from any occurrence of the program (not only from its declaration). @@ -4204,17 +4241,17 @@ o! Logic [2008-06-24] AST changes for invariants. -* Kernel [2008-06-03] Correct promotion rules from bitfields to integers. -* Kernel [2008-06-02] -machdep was ignored (bts #?309). -########################################### +############################################################################### Open Source Release 1.2 (Hydrogen-20080502) -########################################### +############################################################################### o* Makefile [2008-05-21] Fixed bug in "make clean-doc" (and "make distclean"). - GUI [2008-05-19] All internal options are available in the GUI preferences pannel. -########################################### +############################################################################### Open Source Release 1.1 (Hydrogen-20080501) -########################################### +############################################################################### -! Value [2008-04-24] Display a warning whenever an uninitialized value causes the death of a branch. @@ -4240,9 +4277,9 @@ o GUI [2008-04-07] Project management redesigned for older Gtk and -* Kernel [2008-04-01] Various Win32 path fixes. - Kernel [2008-04-01] Option -no-unicode : do not print Unicode chars. -###################################### +############################################################################### Binary Release 1.0 (Hydrogen-20080302) -###################################### +############################################################################### - Occurrence [2008-03-17] New option -occurrence. - Occurrence [2008-03-17] First release of the plug-in. @@ -4252,9 +4289,9 @@ Binary Release 1.0 (Hydrogen-20080302) -* Project [2008-03-14] Fixed bug with checksum computation during save/load. -* Slicing [2008-02-25] Fixed bug in interprocedural slicing (bts #?201). -########################################### +############################################################################### Open Source Release 1.0 (Hydrogen-20080301) -########################################### +############################################################################### - Kernel [2008-03-01] First release. diff --git a/Makefile b/Makefile index 9d94325ae423e998f608e5d2d06ac95347178f4e..e3ca12690f9ecc3cfe1c64a31c35aa2e783aa515 100644 --- a/Makefile +++ b/Makefile @@ -73,6 +73,21 @@ endif dune clean rm -rf _build .merlin +############################################################################## +# IVETTE +################################ + +.PHONY: ivette ivette-dev + +ivette: all + @$(MAKE) -C ivette + +ivette-api: all + @$(MAKE) -C ivette api + +ivette-dev: all + @$(MAKE) -C ivette dev + ############################################################################## # HELP ################################ diff --git a/README.md b/README.md index c79e89f7f68b7e95c4358f2c08ef2435f371c608..667cd21699597ecd39423c8b728879a6627c681f 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,6 @@ called **plug-ins**. Plug-ins can build upon results computed by other plug-ins in the platform. Thanks to this approach, Frama-C provides sophisticated tools, including: - - an analyzer based on abstract interpretation, aimed at verifying the absence of run-time errors (**Eva**); - a program proof framework based on weakest precondition calculus (**WP**); diff --git a/VERSION b/VERSION index 8d4b0111158d4ed44ddccdd1457f13b0e01a41f2..c49dfde59ea4943a4fad4f6f08b7c34f0d01e99d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -26.1+dev +27.0+dev diff --git a/VERSION_CODENAME b/VERSION_CODENAME index c9098b37e740d4c28384b3bee6358d2276ca8797..ae1216c1668e0b1213b1fff0a69d3f1a58409744 100644 --- a/VERSION_CODENAME +++ b/VERSION_CODENAME @@ -1 +1 @@ -Iron +Cobalt diff --git a/bin/frama-c b/bin/frama-c index 86398b26384daab1c1da65bfb4f7ba3e7f301a34..88838755bcbd17e06054b3cdd1f6666a0b0fc7c1 100755 --- a/bin/frama-c +++ b/bin/frama-c @@ -22,4 +22,4 @@ ########################################################################## -dune exec --root=$(dirname $0)/.. --no-build frama-c -- "$@" +dune exec --root=$(dirname $0)/.. --no-build --no-print-directory -- frama-c "$@" diff --git a/bin/test.sh b/bin/test.sh index 2e9558da3943989b9fb0281c5226ec96da649254..6faa03802ec431d776bdccf21c4d0c300117f360 100755 --- a/bin/test.sh +++ b/bin/test.sh @@ -26,12 +26,14 @@ CONFIG="<all>" VERBOSE= UPDATE= LOGS= +COMMIT= TESTS= SAVE= DUNE_ALIAS= DUNE_OPT= DUNE_LOG=./.test-errors.log +ALIAS_NAME=ptests CACHEDIR=$(pwd -P)/.wp-cache FRAMAC_WP_CACHE_GIT=git@git.frama-c.com:frama-c/wp-cache.git @@ -61,11 +63,13 @@ function Usage echo "" echo "OPTIONS" echo "" + echo " -n|--name <alias> set dune alias name (default to ptests)" echo " -r|--clean clean (remove all) test results (includes -p)" echo " -p|--ptests prepare (all) dune files" echo " -w|--wp-cache prepare (pull) WP-cache" - echo " -u|--update run tests and update (local) WP-cache" + echo " -u|--wp-update update (pull+add) WP-cache" echo " -l|--logs print output of tests (single file, no diff)" + echo " -k|--commit commit results as oracles (single file, no diff)" echo " -s|--save save dune logs into $DUNE_LOG" echo " -v|--verbose print executed commands" echo " -h|--help print this help" @@ -206,15 +210,15 @@ function TestDir CloneCache case "$CONFIG" in "<all>") - ALIAS=$1/ptests + ALIAS=$1/${ALIAS_NAME} CFG="(all configs)" ;; "<default>") - ALIAS=$1/ptests_config + ALIAS=$1/${ALIAS_NAME}_config CFG="(default config)" ;; *) - ALIAS=$1/ptests_config_$CONFIG + ALIAS=$1/${ALIAS_NAME}_config_$CONFIG CFG="(config $CONFIG)" ;; esac @@ -247,6 +251,9 @@ function TestFile else ALIAS=$DIR/$RESULT/${FILE%.*}.diff fi + if [ "$COMMIT" = "yes" ]; then + COMMITS="${COMMITS} $DIR/$RESULT/${FILE%.*}" + fi Head "Register test on file $1 $CFG" DUNE_ALIAS="${DUNE_ALIAS} @$ALIAS" } @@ -273,6 +280,27 @@ function Register done } +# -------------------------------------------------------------------------- +# --- Tests Commits +# -------------------------------------------------------------------------- + +function Commits +{ + while [ "$1" != "" ] + do + cd _build/default + for log in $1*.res.log + do + echo "Commit $log" + dest="${log//result/oracle}" + dest="${dest//res.log/res.oracle}" + cp -f $log "../../$dest" + done + cd ../.. + shift + done +} + # -------------------------------------------------------------------------- # --- Tests Numbering # -------------------------------------------------------------------------- @@ -303,8 +331,9 @@ function Status #-- Check wp-cache status if [ "$UPDATE" = "yes" ]; then - Head "Check $FRAMAC_WP_CACHEDIR status" + Head "Update $FRAMAC_WP_CACHEDIR and check status" RequiredTools git + Run git -C $FRAMAC_WP_CACHEDIR add -A Run git -C $FRAMAC_WP_CACHEDIR status -s fi } @@ -334,7 +363,8 @@ do "-w"|"--wp-cache") PullCache ;; - "-u"|"--update") + "-u"|"--wp-update") + PullCache FRAMAC_WP_CACHE=update UPDATE=yes ;; @@ -345,8 +375,11 @@ do "-l"|"--logs") LOGS=yes ;; + "-k"|"--commit") + COMMIT=yes + ;; "-s"|"--save" ) - SAVE=yes + SAVE=yes ;; "-d"|"--default") CONFIG="<default>" @@ -355,6 +388,10 @@ do CONFIG=$2 shift ;; + "-n"|"--name") + ALIAS_NAME=$2 + shift + ;; "-a"|"--all") TESTS="" for dir in $TEST_DIRS ; do @@ -371,4 +408,5 @@ do done Register $TESTS RunAlias ${DUNE_ALIAS} +Commits ${COMMITS} Status $DUNE_LOG diff --git a/dev/dune-workspace.bench b/dev/dune-workspace.bench index 87e6d04e0ad58aba035cac6a3f7b7c68eda27674..1f5ad5f7195c1c589acd1a37e04a56aa999a51c3 100644 --- a/dev/dune-workspace.bench +++ b/dev/dune-workspace.bench @@ -1,4 +1,26 @@ (lang dune 3.2) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; This file is part of Frama-C. ;; +;; ;; +;; Copyright (C) 2007-2023 ;; +;; 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). ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (context (default (name bench) diff --git a/dev/set-version.sh b/dev/set-version.sh new file mode 100755 index 0000000000000000000000000000000000000000..09f362f28ffe62fe940a815edbf52df74b40abcf --- /dev/null +++ b/dev/set-version.sh @@ -0,0 +1,127 @@ +#! /bin/bash +########################################################################## +# # +# This file is part of Frama-C. # +# # +# Copyright (C) 2007-2023 # +# 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). # +# # +########################################################################## + +NEXT=$1 + +if ! test -f VERSION; then + echo "This script must be run from Frama-C root directory" + exit 2 +fi +if test -z "$NEXT"; then + echo "Missing argument. Usage is:" + echo "\$ ./dev/set-version.sh [<NN.M>|dev]" + echo "See the Release Management Documentation for an example." + exit 2 +fi + +# For macOS: use gsed if available, otherwise test if sed is BSD +if command -v gsed &>/dev/null; then + SED=gsed +else + if sed --version 2>/dev/null | grep -q GNU; then + SED=sed + else + echo "GNU sed required" + exit 1 + fi +fi + +CURRENT=$(cat VERSION) +CURRENT_MAJOR=$(echo "$CURRENT" | $SED -e s/\\\([0-9]*\\\).[0-9]*.*/\\1/) +CURRENT_MINOR=$(echo "$CURRENT" | $SED -e s/[0-9]*.\\\([0-9]*\\\).*/\\1/) +CURRENT_CODENAME=$(grep "$CURRENT_MAJOR " ./doc/release/periodic-elements.txt | cut -d " " -f2) + +if [[ $NEXT == "dev" ]]; then + echo "Set VERSION to $CURRENT+dev" + echo "Continue? [y/N] " + read CHOICE + case "${CHOICE}" in + "Y" | "y") ;; + *) exit 1 ;; + esac + + echo "$CURRENT+dev" >VERSION + $SED -i "s/^version: .*/version: \"$CURRENT+dev\"/g" opam + $SED -i "s/^version: .*/version: \"$CURRENT+dev\"/g" tools/lint/frama-c-lint.opam + $SED -i "s/^version: .*/version: \"$CURRENT+dev\"/g" tools/hdrck/frama-c-hdrck.opam +else + NEXT_MAJOR=$(echo "$NEXT" | $SED -e s/\\\([0-9]*\\\).[0-9]*.*/\\1/) + NEXT_MINOR=$(echo "$NEXT" | $SED -e s/[0-9]*.\\\([0-9]*\\\).*/\\1/) + NEXT_CODENAME=$(grep "$NEXT_MAJOR " ./doc/release/periodic-elements.txt | cut -d " " -f2) + + echo "NEXT VERSION is:" + echo "- MAJOR: $NEXT_MAJOR" + echo "- MINOR: $NEXT_MINOR" + echo "- CODENAME: $NEXT_CODENAME" + + echo "" + echo "Continue? [y/N] " + read CHOICE + case "${CHOICE}" in + "Y" | "y") ;; + *) exit 1 ;; + esac + + # Version + + echo "$NEXT" >VERSION + echo "$NEXT_CODENAME" >VERSION_CODENAME + + # Opam files + $SED -i "s/^version: .*/version: \"$NEXT_MAJOR.$NEXT_MINOR\"/g" opam + $SED -i "s/\(.*\)$CURRENT_MAJOR.$CURRENT_MINOR-$CURRENT_CODENAME\(.*\)/\1$NEXT_MAJOR.$NEXT_MINOR-$NEXT_CODENAME\2/g" opam + + $SED -i "s/^version: .*/version: \"$NEXT_MAJOR.$NEXT_MINOR\"/g" tools/lint/frama-c-lint.opam + $SED -i "s/^version: .*/version: \"$NEXT_MAJOR.$NEXT_MINOR\"/g" tools/hdrck/frama-c-hdrck.opam + + # Changelogs + + FC_CL_MSG_FUTURE="Open Source Release <next-release>" + FC_CL_MSG_NEXT="Open Source Release $NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)" + FC_CL_LIN="###############################################################################" + + $SED -i "s/\($FC_CL_MSG_FUTURE\)/\1\n$FC_CL_LIN\n\n$FC_CL_LIN\n$FC_CL_MSG_NEXT/g" Changelog + + EA_CL_MSG_FUTURE="Plugin E-ACSL <next-release>" + EA_CL_MSG_NEXT="Plugin E-ACSL $NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)" + + $SED -i "s/\($EA_CL_MSG_FUTURE\)/\1\n$FC_CL_LIN\n\n$FC_CL_LIN\n$EA_CL_MSG_NEXT/g" src/plugins/e-acsl/doc/Changelog + + WP_CL_MSG_FUTURE="Plugin WP <next-release>" + WP_CL_MSG_NEXT="Plugin WP $NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)" + + $SED -i "s/\($WP_CL_MSG_FUTURE\)/\1\n$FC_CL_LIN\n\n$FC_CL_LIN\n$WP_CL_MSG_NEXT/g" src/plugins/wp/Changelog + + # API doc + find src -name '*.ml*' -exec $SED -i -e "s/Frama-C+dev/${NEXT}-${NEXT_CODENAME}/gI" '{}' ';' + + # Manuals changes + $SED -i "s/\(^\\\\section\*{Frama-C+dev}\)/%\1\n\n\\\\section\*{$NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)}/g" \ + doc/userman/user-changes.tex + $SED -i "s/\(^\\\\section\*{Frama-C+dev}\)/%\1\n\n\\\\section\*{$NEXT_MAJOR.$NEXT_MINOR ($NEXT_CODENAME)}/g" \ + doc/developer/changes.tex + $SED -i "s/\(^\\\\subsection{Frama-C+dev}\)/%\1\n\n\\\\subsection{Frama-C $NEXT_CODENAME}/g" \ + doc/aorai/main.tex + $SED -i "s/\(^\\\\section\*{E-ACSL \\\\eacslpluginversion \\\\eacslplugincodename}\)/%\1\n\n\\\\section\*{E-ACSL $NEXT_MAJOR.$NEXT_MINOR $NEXT_CODENAME}/g" \ + src/plugins/e-acsl/doc/userman/changes.tex +fi diff --git a/doc/aorai/main.tex b/doc/aorai/main.tex index 0c902318f7b36da17d9035a490b09dcf39f456d2..43ed2deea1de8f2e5f065c624d95c04b8d88d1fe 100644 --- a/doc/aorai/main.tex +++ b/doc/aorai/main.tex @@ -1123,6 +1123,8 @@ The plug-in is composed of three parts: \section{Recent updates} +%\subsection{Frama-C+dev} + \subsection{Frama-C Iron} \begin{itemize} \item Remove obsolete support for LTL and Promela input language diff --git a/doc/developer/advance.tex b/doc/developer/advance.tex index bdfec9acc732ea0b1516a19ee06f899857d7360f..13357f76e11e74b919a909d9d7c617ccaf669c6e 100644 --- a/doc/developer/advance.tex +++ b/doc/developer/advance.tex @@ -3213,114 +3213,60 @@ type-checked. Transformation hooks are registered through None. \end{prereq} +\subsection{Generating a custom model}\label{sec:gener-cust-model} Several aspects of the C standard that are implementation-defined, such as the width of standard integer types, endianness, signedness of the \texttt{char} type, etc., as well as a few compiler and architecture specific features, can be customized using a \texttt{machdep} configuration, defining a new machine model. -To create a new machine model, define an instance of \verb+Cil_types.mach+% -\scodeidxdef{Cil\_types}{mach}. You can base it on the examples available in -\verb+tests/misc/custom_machdep/custom_machdep.ml+ and -\verb+src/kernel_internals/runtime/machdeps.ml+. -The new definition can be added to \framac's database using -\verb+File.new_machdep+\scodeidxdef{File}{new\_machdep}. - -\begin{example} - A custom machine description may be implemented as follows - (the meaning of each field is presented later in this section): -\begin{ocamlcode} -let my_machine = -{ - version = "generic C compiler for my machine"; - compiler = "generic"; - cpp_arch_flags = []; - sizeof_short = 2; - sizeof_int = 4; - sizeof_long = 4; - sizeof_longlong = 8; - sizeof_ptr = 4; - sizeof_float = 4; - sizeof_double = 8; - sizeof_longdouble = 12; - sizeof_void = 1; - sizeof_fun = 1; - size_t = "unsigned long"; - wchar_t = "int"; - ptrdiff_t = "int"; - alignof_short = 2; - alignof_int = 4; - alignof_long = 4; - alignof_longlong = 4; - alignof_ptr = 4; - alignof_float = 4; - alignof_double = 4; - alignof_longdouble = 4; - alignof_str = 1; - alignof_fun = 1; - alignof_aligned = 16; - char_is_unsigned = false; - const_string_literals = true; - little_endian = true; - underscore_name = false ; - has__builtin_va_list = true; -} - -let () = File.new_machdep "my_machine" my_machine -\end{ocamlcode} -\end{example} - -\index{Command Line!-machdep@\texttt{-machdep}}% -After this code is loaded, \framac can be instructed to use the new machine -model using the \texttt{-machdep} command line option. - -If you intend to use \framac's standard library headers, you must also do the -following: - -\begin{itemize} -\item define constant \verb+__FC_MACHDEP_<CUSTOM>+, replacing \verb+<CUSTOM>+ - with the name (in uppercase letters) of your created machdep; - this can be done via \verb+-cpp-extra-args="-D__FC_MACHDEP_<CUSTOM>"+; -\item provide a header file with macro definitions corresponding to your \caml - definitions. For the most part, these are macros prefixed by \verb+__FC_+, - corresponding to standard C macro definitions, {\it e.g.}, - \verb+__FC_UCHAR_MAX+. These definitions are used by \framac's - \verb+<limits.h>+ and other headers to provide the standard C definitions. - The test file \verb+tests/misc/custom_machdep/__fc_machdep_custom.h+ - (reproduced below) - contains a complete example of the required definitions. Other examples can - be found in \verb+share/libc/__fc_machdep.h+. -\end{itemize} -Make sure that your custom header defines the \verb+__FC_MACHDEP+ -include guard, and that the program you are analyzing includes this header -before all other headers. One way to ensure this without having to modify any -source files is to use an option such as \verb+-include+ in GCC. - -\begin{example} - Contents of \verb+tests/misc/custom_machdep/__fc_machdep_custom.h+, used as - example for creating custom machdeps. Notice the unusual size for \verb+int+ - (3 bytes), selected for testing purposes only, and inconsistent with the - chosen values for \verb+INT_MIN+ and \verb+INT_MAX+, which do not fit - in 3 bytes. -\lstinputlisting{../../tests/misc/custom_machdep/__fc_machdep_custom.h} -\end{example} +Machine models are described as \texttt{YAML} files, following the +\texttt{machdeps/machdep-schema.yaml} schema in \texttt{FRAMAC\_SHARE}. +Predefined machdeps are also located in the \texttt{machdeps} directory +of \framac's \texttt{SHARE} directory and can be used as reference for +defining new \texttt{machdep}s by hand. It is also possible to automatically +generate an \texttt{YAML} file with the \texttt{make\_machdep.py} script in +the \texttt{machdeps/make\_machdep} directory. This script requires a +C11-compliant cross-compiler for the architecture you want to describe. +Its main options are: +\begin{description} +\item \texttt{-compiler <c>}: the cross-compiler to be used for generating + the machdep. +\item \texttt{-cpp-arch-flags <flag>}: an option given to the compiler for +selecting the desired architecture. Multiple occurrences of this option can +occur if you want to pass several options. +\item \texttt{-o <file>}: put the generated YAML into the given file (default +is to use standard output). +\item \texttt{--help}: outputs the list of all options of the script. +\end{description} -An example of the complete command-line is presented below, for a custom -machdep called \texttt{myarch}, defined in file \verb+my_machdep.ml+ and -with stdlib constants defined in \verb+machdep_myarch.h+: +Note that for some compiler setups, notably for non-POSIX compilation targets, +the script may fail to find an appropriate value for some fields and will +instead put some default value. In that case, warnings will give the names of +the problematic fields. Since the issue likely stems from the fact that the +corresponding C feature is not supported on the compilation target in the first +place, in practice, such feature is not expected to be found in code written for +such target. However, users are invited to review the generated YAML and +provide more appropriate values for these fields if needed. -\begin{listing-nonumber} - frama-c -load-script my_machdep.ml -machdep myarch \ - -cpp-extra-args="-D__FC_MACHDEP_MYARCH -include machdep_myarch.h" -\end{listing-nonumber} +In order to communicate machine-related information to the preprocessor (notably +the value of standard macros), \framac generates a specific header, +\verb+__fc_machdep.h+, that is automatically included by the standard headers from +\framac's standard C library. Field \verb+custom_defs+ of the YAML file allows +customizing this header (see next section for more information). -\section{Machdep record fields}\label{sec:machdep-fields} +\subsection{Machdep record fields}\label{sec:machdep-fields} -Each field in the machdep record is succintly described in the \verb+Cil_types+ -module. We present below a thorough description of each field. +Each field of the machdep is succintly described in the +\verb+machdep-schema.yaml+ file. +We present below a thorough description of each field. +\paragraph{Meta-data} \begin{description} \item[\texttt{version}]: human-readable textual description of the machdep. +\item[\texttt{machdep\_name}]: name of the machdep, must only contain alphanumeric + characters or underscore (\verb+_+). If it is e.g. \verb+custom_name+, the generated header will + define a macro of the form \verb+__FC_MACHDEP_CUSTOM_NAME+. \item[\texttt{compiler}]: defines whether special compiler-specific extensions will be enabled. It should be one of the strings below: \begin{itemize} @@ -3332,15 +3278,17 @@ module. We present below a thorough description of each field. compiler-specific extensions. \end{itemize} Note that some compiler extensions, such as attributes, are always enabled. -\item[\texttt{cpp\_arch\_flags}]: list of arguments to be added to the - command-line when invoking the C preprocessor. Typically used to ensure that - multiarch compilers apply the appropriate predefined macros\footnote{Note that - the sizes of standard integer types are already defined in the machdep, - so they do not depend on these flags.}. - E.g. use \verb+["-m32"]+ for a 32-bit machdep when preprocessing with a - 64-bit multiarch GCC. +\item[\texttt{cpp\_arch\_flags}]: list of arguments used by the compiler to + select the corresponding architecture, e.g. \verb+["-m32"]+ for a 32-bit + machdep. Older versions (up to 26.x - Iron) of \framac did pass these flags to the pre-processor, + in order for it to define a set of built-in macros related to said architecture. + Current versions do not use this field, and rely on \texttt{\texttt{custom\_defs}} + containing the appropriate definitions. Note that, in practice, very few programs rely on such predefined macros, such as \verb+__x86_64+ and \verb+__i386+. +\end{description} +\paragraph{Standard sizes and alignment constraints} +\begin{description} \item[\texttt{sizeof\_short}]: size (in bytes) of the \verb+short+ type. \item[\texttt{sizeof\_int}]: size (in bytes) of the \verb+int+ type. \item[\texttt{sizeof\_long}]: size (in bytes) of the \verb+long+ type. @@ -3352,7 +3300,7 @@ module. We present below a thorough description of each field. \item[\texttt{sizeof\_ptr}]: size (in bytes) of an object (non-function) pointer. \item[\texttt{sizeof\_float}]: size (in bytes) of a single-precision floating - point. In implementations compliant with ISO/IEC/IEEE 60559 -IEEE 754, + point. In implementations compliant with ISO/IEC/IEEE 60559 - IEEE 754, this is always 4. \item[\texttt{sizeof\_double}]: size (in bytes) of a double-precision floating point. In implementations compliant with ISO/IEC/IEEE 60559 - IEEE 754, @@ -3363,16 +3311,10 @@ module. We present below a thorough description of each field. \framac plugins, but this field exists for future expansion, and to compute \verb+sizeof+ of aggregates properly. \item[\texttt{sizeof\_void}]: the result of evaluating \verb+sizeof(void)+ - by the compiler (or 0 if unsupported). + by the compiler (or negative if unsupported). \item[\texttt{sizeof\_fun}]: the result of evaluating \verb+sizeof(f)+, where \verb+f+ is a function ({\em not} a function pointer) by the compiler (or negative if unsupported). - \item[\texttt{size\_t}]: a string containing the actual type that - \verb+size_t+ expands to, e.g. \verb+"unsigned long"+. - \item[\texttt{wchar\_t}]: a string containing the actual type that - \verb+wchar_t+ expands to. If unsupported, you can use \verb+int+. - \item[\texttt{ptrdiff\_t}]: a string containing the actual type that - \verb+ptrdiff_t+ expands to. If unsupported, you can use \verb+int+. \item[\texttt{alignof\_short}]: the result of evaluating \verb+_Alignof(short)+. \item[\texttt{alignof\_int}]: the result of evaluating \verb+_Alignof(int)+. @@ -3395,31 +3337,120 @@ module. We present below a thorough description of each field. \verb+aligned+ attribute (or 1 if unsupported). This corresponds to the default alignment when using \verb+#pragma packed()+ without a numeric argument. +\end{description} + +\paragraph{Standard types} + +\begin{description} +\item[\texttt{int\_fast8\_t}]: a string containing the actual type that + \verb+int_fast8_t+ expands to. Usually \verb+signed char+. +\item[\texttt{int\_fast16\_t}]: a string containing the actual type that + \verb+int_fast16_t+ expands to. Usually \verb+int+ or \verb+long+. +\item[\texttt{int\_fast32\_t}]: a string containing the actual type that + \verb+int_fast_32_t+ expands to. Usually \verb+int+ or \verb+long+. +\item[\texttt{int\_fast64\_t}]: a string containing the actual type that + \verb+int_fast64_t+ expands to. Usually \verb+long+ or \verb+long long+. +\item[\texttt{uint\_fast8\_t}]: a string containing the actual type that + \verb+uint_fast8_t+ expands to. Usually \verb+unsigned char+. +\item[\texttt{uint\_fast16\_t}]: a string containing the actual type that + \verb+uint_fast16_t+ expands to. Usually \verb+unsigned int+ or \verb+unsigned long+. +\item[\texttt{uint\_fast32\_t}]: a string containing the actual type that + \verb+uint_fast_32_t+ expands to. Usually \verb+unsigned int+ or \verb+unsigned long+. +\item[\texttt{uint\_fast64\_t}]: a string containing the actual type that + \verb+uint_fast64_t+ expands to. Usually \verb+unsigned long+ or + \verb+unsigned long long+. +\item[\texttt{intptr\_t}]: a string containing the actual type that + \verb+intptr_t+ expands to, e.g. \verb+long+ +\item[\texttt{uintptr\_t}]: a string containing the actual type that + \verb+uintptr_t+ expands to, e.g. \verb+unsigned long+ +\item[\texttt{size\_t}]: a string containing the actual type that + \verb+size_t+ expands to, e.g. \verb+unsigned long+. +\item[\texttt{ssize\_t}]: a string containing the actual type that + \verb+ssize_t+ expands to, e.g. \verb+long+ +\item[\texttt{wchar\_t}]: a string containing the actual type that + \verb+wchar_t+ expands to. If unsupported, you can use \verb+int+. +\item[\texttt{ptrdiff\_t}]: a string containing the actual type that + \verb+ptrdiff_t+ expands to. If unsupported, you can use \verb+int+. +\item[\texttt{sig\_atomic\_t}]: a string containing the actual type that + \verb+sig_atomic_t+ expands to (i.e. an integer type that can be + accessed atomically even in presence of interrupts). +\item[\texttt{time\_t}]: a string containing the actual type that + \verb+time_t+ expands to (i.e. an integer type that can hold time + values in seconds). +\item[\texttt{wint\_t}]: a string containing the actual type that + \verb+wint_t+ expands to (i.e. an integer type capable of holding any + \verb+wchar_t+ and \verb+WEOF+) +\end{description} + +\paragraph{Standard macros} + +Note that all fields described in this paragraph have \texttt{string} values, +even if they denote numeric constants. In order to avoid errors when loading the +YAML file, you can force them to be considered as strings by enclosing them between +single or double quotes, as in \verb+eof: '(-1)'+ (as a sidenote, negative values +should be enclosed in parentheses, in order to ensure safe macro expansions). + +\begin{description} + \item[\texttt{bufsiz}]: value of the \texttt{BUFSIZ} macro, i.e. the size + of buffers used by I/O functions in \texttt{stdio.h}. + \item[\texttt{eof}]: value of the \texttt{EOF} macro, the value returned by input + functions in \texttt{stdio.h} to indicate the end of the stream. + \item[\texttt{errno}]: list of possible errors with their numeric value. In order + to be easier to read, the content of this field is in fact written itself as an + object whose fields are the name of the errors. For instance, for a machdep defining + only the three errors mandated by the C standard, we would have: + \begin{verbatim} + errno: + edom: 1 + eilseq: 2 + erange: 3 + \end{verbatim} + \item[\texttt{filename\_max}]: value of the \texttt{FILENAME\_MAX} macro, which + denotes the longest name that is guaranteed to be accepted by \texttt{fopen}. + \item[\texttt{fopen\_max}]: value of the \texttt{FOPEN\_MAX} macro, which denotes the + greatest number of streams that can be simultaneously opened by the program. + \item[\texttt{host\_name\_max}]: value of the \texttt{HOST\_NAME\_MAX} macro, which + denotes the maximum length of a hostname (without terminating null byte). + \item[\texttt{l\_tmpnam}]: value of the \texttt{L\_tmpnam} macro, which denotes + the maximum size of a temporary filename as returned by \texttt{tmpnam}. + \item[\texttt{mb\_cur\_max}]: value of the \texttt{MB\_CUR\_MAX} macro, which denotes + the maximum number of bytes for a character in the current locale (usually + \texttt{'1'}). + \item[\texttt{nsig}]: number of possible signals (non-standard macro, can be left + empty if undefined for the current machdep). + \item[\texttt{path\_max}]: value of the \texttt{PATH\_MAX} macro, which denotes + the maximum size (including terminating null) that can be stored in a buffer + when returning a pathname. + \item[\texttt{posix\_version}]: value of the \texttt{\_POSIX\_VERSION} macro. + Leave empty on non-POSIX machdeps. + \item[\texttt{rand\_max}]: value of the \texttt{RAND\_MAX} macro, which denotes + the maximum value returned by \texttt{rand}. + \item[\texttt{tmp\_max}]: value of the \texttt{TMP\_MAX} macro, which denotes + the minimum number of temporary filenames returned by \texttt{tmpnam} that + are guaranteed to be distinct. + \item[\texttt{tty\_name\_max}]: value of the \texttt{TTY\_NAME\_MAX} macro, which + denotes the maximum length of a terminal device name (including terminating null byte). + \item[\texttt{weof}]: value of the \texttt{WEOF} macro, similar to \texttt{EOF}, + but for wide chars. + \item[\texttt{wordsize}]: value of the \texttt{\_\_WORDSIZE} macro, which denotes + the length of a word on the current architecture. +\end{description} + +\paragraph{Other features} +\begin{description} \item[\texttt{char\_is\_unsigned}]: whether type \verb+char+ is unsigned. - \item[\texttt{const\_string\_literals}]: whether string literals have const - chars, or are writable. If \verb+true+, the following code has undefined - behavior, otherwise it is defined: \verb+char *s = "no"; s[0] = 'g';+. - \item[\texttt{little\_endian}]: whether the machine is little endian. - \item[\texttt{underscore\_name}]: whether the compiler generates assembly - labels by prepending \verb+_+ to the identifier. That is, will function - \verb+foo()+ have the label \verb+foo+, or \verb+_foo+? + \item[\texttt{little\_endian}]: whether the machine is little endian or big + endian\footnote{More exotic endianness such as mixed-endian are currently unsupported.}. \item[\texttt{has\_\_builtin\_va\_list}]: whether \verb+__builtin_va_list+ is a (built-in) type known by the preprocessor. \item[\texttt{\_\_thread\_is\_keyword}]: whether \verb+__thread+ is a keyword (otherwise, it can be used as a standard identifier). + \item[\texttt{custom\_defs}]: arbitrary text that will be appended + verbatim at the + end of the generated header file (this is empty in machdeps that are + generated by the \texttt{make\_machdep.py} script). \end{description} -\paragraph{Writing a new machdep} - -Writing a machdep for a new architecture is not trivial, due to the fact -that some steps are hard to automate. If you have a working compiler for the -target architecture, you can use it to produce an executable that will print -the contents of expressions such as \verb+sizeof(long)+, \verb+_Alignof(int)+, -etc. You can also use the compiler to test for unsupported features. -In case \verb+printf+ is not available, you can use the exit code of the -program (return code of \verb+main+). In case you can only preprocess, but not -compile and run the program, the assembly code may provide some useful data. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Visitors}\label{adv:visitors}\index{Visitor|bfit} @@ -3974,7 +4005,7 @@ can be used in ACSL specification. Namely, specification: -\begin{lstlisting}[language=C,alsolanguage=ACSL] +\begin{lstlisting}[style=c] /*@ ext_type load: foo ; */ /*@ axiomatic Pred { @@ -4209,9 +4240,9 @@ For quick usage of the library: \item install the instrumented \framac: \texttt{make install DUNE\_WS=bench}. \item enable instrumentation {\em during execution} of \framac, using the \texttt{OCAML\_LANDMARKS} environment variable: - \begin{lstlisting} - OCAML_LANDMARKS=<options> frama-c [files] [options] - \end{lstlisting} +\begin{logs} +OCAML_LANDMARKS=<options> frama-c [files] [options] +\end{logs} The easiest setup is \texttt{OCAML\_LANDMARKS=auto}, which will instrument everything and output timing information to \texttt{stderr} after program termination. @@ -4219,10 +4250,10 @@ For quick usage of the library: output the timing information to file \texttt{landmarks.log}. \item you can also run the instrumented \framac without installing it, via \texttt{dune exec}: - \begin{lstlisting} - OCAML_LANDMARKS=auto dune exec --workspace dev/dune-workspace.bench \ - --context bench -- frama-c [files] [options] - \end{lstlisting} +\begin{logs} +OCAML_LANDMARKS=auto dune exec --workspace dev/dune-workspace.bench \ + --context bench -- frama-c [files] [options] +\end{logs} The \verb+--workspace dev/dune-workspace.bench+ argument tells Dune to use the workspace in which Landmarks is configured. @@ -4238,8 +4269,49 @@ of the file. To instrument a single function: add \verb+[@landmark]+ after the \texttt{let}, e.g.: -\begin{lstlisting} +\begin{ocamlcode} let[@landmark] add_visitor vis = -\end{lstlisting} +\end{ocamlcode} Check \url{https://github.com/LexiFi/landmarks} for its documentation. + +\section{Profiling a custom plug-in} + +To profile your own plug-in using Landmarks, do the following: + +\begin{enumerate} +\item Add \verb|(instrumentation (backend landmarks))| to your plug-in's + \verb|dune| file, inside the \verb|library| stanza, as in the example below: +\begin{dunecode} + (library + (name my-plug-in) + (public_name frama-c-my-plug-in.core) + ... + (libraries frama-c.kernel) + (instrumentation (backend landmarks)) ; <<< ADD THIS LINE + ) +\end{dunecode} +\item Create a \verb|dune-workspace.bench| file in your plugin's top-level + directory: + \listingname{dune-workspace.bench} + \duneinput{dune-workspace.bench} +\item Add \verb|--workspace=dune-workspace.bench| to the \verb|dune build| + and \verb|dune install| commands that you run, e.g.: +\begin{logs} +dune build --workspace=dune-workspace.bench @install +dune install --workspace=dune-workspace.bench +\end{logs} +This will compile and install the plug-in with Landmarks instrumentation +enabled. Then you just need to set \verb|OCAML_LANDMARKS| as described in the +previous section, e.g.: +\begin{logs} +OCAML_LANDMARKS=auto frama-c [my-plugin-options] +\end{logs} +\item For \verb|dune exec|, you need to add the \verb|--workspace| option + as well as \verb|--context bench|. Combined with \verb|OCAML_LANDMARKS|, + the command-line will resemble the following: +\begin{logs} +OCAML_LANDMARKS=auto dune exec --workspace dev/dune-workspace.bench \ + --context bench -- frama-c [files] [options] +\end{logs} +\end{enumerate} diff --git a/doc/developer/changes.tex b/doc/developer/changes.tex index 4e949abc3b74503bb9715505ec5d5ce087691834..d0ee85277359173857a81b900decd4ab713eb009 100644 --- a/doc/developer/changes.tex +++ b/doc/developer/changes.tex @@ -5,10 +5,13 @@ This chapter summarizes the major changes in this documentation between each \framac release, from newest to oldest. -%\section*{dev} -%\begin{itemize} -%\item … -%\end{itemize} +%\section*{Frama-C+dev} + +\section*{27.0 (Cobalt)} +\begin{itemize} +\item \textbf{Customizing the machine model}: Rewrite section according to new + machdep management mechanism +\end{itemize} \section*{26.0 Iron} \begin{itemize} diff --git a/doc/developer/dune-workspace.bench b/doc/developer/dune-workspace.bench new file mode 100644 index 0000000000000000000000000000000000000000..87e6d04e0ad58aba035cac6a3f7b7c68eda27674 --- /dev/null +++ b/doc/developer/dune-workspace.bench @@ -0,0 +1,9 @@ +(lang dune 3.2) +(context + (default + (name bench) + (profile bench) + (instrument_with landmarks) + (env + (_ (env-vars ("OCAML_LANDMARKS" "auto"))))) +) diff --git a/doc/eva/examples/nondet.c b/doc/eva/examples/nondet.c index 808ba9c653ee9a33e59b006d03dac4c9224c1a6d..b73510ecab61fbce6e8034709be01b4a68484b06 100644 --- a/doc/eva/examples/nondet.c +++ b/doc/eva/examples/nondet.c @@ -1,9 +1,11 @@ #include "__fc_builtin.h" int A,B,X; +int arr[20]; void main(void) { A = Frama_C_nondet(6, 15); B = Frama_C_interval(-3, 10); X = A * B; + Frama_C_make_unknown(arr, sizeof(arr)); } diff --git a/doc/eva/examples/parametrizing/split-array.log b/doc/eva/examples/parametrizing/split-array.log index 53a9ddd932748d851458163c1c4c9e1f4d461370..5adefbaf6d4c26f05da62738388ced7a7cab5977 100644 --- a/doc/eva/examples/parametrizing/split-array.log +++ b/doc/eva/examples/parametrizing/split-array.log @@ -27,7 +27,7 @@ [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- 1 function analyzed (out of 1): 100% coverage. - In this function, 9 statements reached (out of 9): 100% coverage. + In this function, 10 statements reached (out of 10): 100% coverage. ---------------------------------------------------------------------------- No errors or warnings raised during the analysis. ---------------------------------------------------------------------------- diff --git a/doc/eva/main.tex b/doc/eva/main.tex index b3c5be5239cf7e0bf761765a6392fc75349eacc3..fc9d9c1af019942617ce5a4bc107308f39f54d86 100644 --- a/doc/eva/main.tex +++ b/doc/eva/main.tex @@ -4203,13 +4203,13 @@ Most domains are also presented in more details in the following subsections. \tabularnewline \midrule octagon & d-octagon & \ref{sec:octagons} & - Infers relations between scalar variables. \\ - Efficient but limited. + Infers relations of the form $l \leq \pm X \pm Y \leq u$ between integer or + pointer lvalues. Efficient. \tabularnewline \midrule multidim & d-multidim & \ref{sec:multidim} & More precise representation of arrays of structures, - multidimensional arrays and arrays invariants. \\ + multidimensional arrays and arrays invariants. Experimental. \tabularnewline \midrule @@ -4435,7 +4435,8 @@ and \texttt{y} is not affine. Activating option \texttt{-eva-domains octagon} 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. +u$, where $X$ and $Y$ are program variables or lvalues, +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 @@ -4455,16 +4456,23 @@ void main (int y) { \end{listing-nonumber} -Currently, the octagon domain is fast but has two strong limitations: +Currently, the octagon domain is fast but has some limitations: \begin{itemize} \item - The domain only infers relations between scalar variables of integer types. - It ignores pointers, arrays and structure fields. + The domain only infers relations between lvalues of integer or + pointer types. + It does not support relations between floating-point values. \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. +\item + The domain has no involved memory model and can only infer and use relations + about the syntactic lvalues as they appear in the program. + For instance, if two pointers \lstinline|p| and \lstinline|q| point to the + same location, and a relation is inferred on \lstinline|*p|, the domain cannot + use it to improve the value of \lstinline|*q|. \end{itemize} The domain is intraprocedural by default: the inferred relations are local to @@ -4474,8 +4482,9 @@ 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. +The analysis of a function can then use the relations previously inferred in the +callers, and at the end, the inferred relations are propagated back to the +caller. \subsection{Multidim} @@ -5574,7 +5583,11 @@ allocation fails. \label{nondeterminism} The following functions, declared in \lstinline|share/libc/__fc_builtin.h|, allow to -introduce some non-determinism in the analysis. The results given by +introduce some non-determinism in the analysis. +These functions are not specific to \Eva{}; their ACSL specifications +(omitted here for brevity) can be understood by other \FramaC plug-ins. + +The results given by \Eva{} are valid \textbf{for all values proposed by the user}, as opposed to what a test-generation tool would typically do. A tool based @@ -5590,31 +5603,55 @@ int Frama_C_nondet(int a, int b); void *Frama_C_nondet_ptr(void *a, void *b); /* returns either a or b */ +void Frama_C_make_unknown(char *p, size_t l); + /* assigns an arbitrary value to each byte between *p and *(p+l-1) */ + int Frama_C_interval(int min, int max); - /* returns any value in the interval from min to max inclusive */ + /* returns any int value in the interval from min to max inclusive */ float Frama_C_float_interval(float min, float max); - /* returns any value in the interval from min to max inclusive */ + /* returns any float value in the interval from min to max inclusive */ double Frama_C_double_interval(double min, double max); - /* returns any value in the interval from min to max inclusive */ + /* returns any double value in the interval from min to max inclusive */ \end{listing-nonumber} -The implementation of these functions might change in future versions -of Frama-C, but their types and their behavior will stay the same. +A series of functions equivalent to \lstinline|Frama_C_interval| +is defined for other integer and floating-point types: +they generate ranges containing all values between their two arguments +(\texttt{min} and \texttt{max}, inclusive) for the given type. +Here is a complete list of these functions: + +\begin{table}[!ht] + \centering + \begin{tabular}{ll} + \lstinline|Frama_C_unsigned_char_interval| & + \lstinline|Frama_C_char_interval| \\ + \lstinline|Frama_C_unsigned_short_interval| & + \lstinline|Frama_C_short_interval| \\ + \lstinline|Frama_C_unsigned_int_interval| & + \lstinline|Frama_C_int_interval| \\ + \lstinline|Frama_C_unsigned_long_interval| & + \lstinline|Frama_C_long_interval| \\ + \lstinline|Frama_C_unsigned_long_long_interval| & + \lstinline|Frama_C_long_long_interval| \\ + \lstinline|Frama_C_interval| (synonym of \lstinline|Frama_C_int_interval|) & + \lstinline|Frama_C_size_t_interval| \\ + \lstinline|Frama_C_float_interval| & + \lstinline|Frama_C_double_interval| \\ + \lstinline|Frama_C_real_interval_as_double| + \end{tabular} +\end{table} Example of use of the functions introducing non-determinism: \csource{examples/nondet.c} With the command below, the obtained result for -variable \lstinline|X| is \lstinline|[-45..150],0%3|. +variable \lstinline|X| is \lstinline|[-45..150],0%3|, and for the +array \lstinline|arr|, \lstinline|[0..19] ∈ [--..--]|. \begin{frama-c-commands} -frama-c -eva ex_nondet.c .../share/libc/__fc_builtin.c +frama-c -eva ex_nondet.c \end{frama-c-commands} -The inclusion of \lstinline|.../share/libc/__fc_builtin.c| is only required -when using the functions \lstinline|Frama_C_float_interval| and -\lstinline|Frama_C_double_interval|. Otherwise, including the file -\lstinline|__fc_builtin.h| is sufficient. Note that reads of volatile variables also return a non-deterministic value. diff --git a/doc/frama-c-book.cls b/doc/frama-c-book.cls index 93ad4c82df983532f19de21c25b4498bf5483100..3436b3c0c2628484ed962268e2149f9f701725c9 100644 --- a/doc/frama-c-book.cls +++ b/doc/frama-c-book.cls @@ -432,6 +432,7 @@ \definecolor{lstmodule}{rgb}{0.3,0.6,0.2} \definecolor{lstspecial}{rgb}{0.2,0.6,0.0} \definecolor{lstfile}{gray}{0.85} +\definecolor{lstcomments}{rgb}{0.35,0.35,0.35} \newcommand{\lstbrk}{\mbox{$\color{blue}\scriptstyle\cdots$}} @@ -439,7 +440,7 @@ \def\lp@inline{\ifmmode\normalfont\mathtt\scriptstyle\else\normalfont\ttfamily\mdseries\normalsize\fi} \def\lp@keyword{} \def\lp@special{\color{frama-c-dark-orange}} -\def\lp@comment{\normalfont\ttfamily\mdseries} +\def\lp@comment{\normalfont\ttfamily\mdseries\color{lstcomments}} \def\lp@string{\color{frama-c-dark-green}} \def\lp@ident{} \def\lp@number{\rmfamily\tiny\color{lstnum}\noncopynumber} @@ -614,17 +615,18 @@ {é}{{\'e}}1% , style=frama-c-style,% - morekeywords={ - action, alias, as, deps, dune, executable, files, flags, from, - generate_opam_files, install, lang, libraries, library, name, optional, - package, plugin, progn, public_name, rule, section, select, site, - targets, using + alsoletter=:-,% + keywords={% + action,alias,as,backend,context,default,deps,dune,executable,% + env,env-vars,files,flags,from,generate_opam_files,install,% + instrument_with,instrumentation,lang,libraries,library,name,optional,% + package,plugin,profile,progn,public_name,rule,section,select,site,% + targets,using% },% - alsoletter=:, - morekeywords=[2]{ - :standard - }, - morecomment=[l]{;}, + morekeywords=[2]{% + :standard% + },% + morecomment=[l]{;},% } \lstdefinestyle{dune-basic}{% diff --git a/doc/release/branch.tex b/doc/release/branch.tex index 7313f46e5b9f437eb76841a23cb2e767432b599d..3c3f9d5943ddb7d0263b27b5b822b22dde8941a9 100644 --- a/doc/release/branch.tex +++ b/doc/release/branch.tex @@ -61,63 +61,28 @@ Check public issue tracker at \url{https://git.frama-c.com/pub/frama-c/issues/}. All issues should have been at least acknowledged: at least they should be assigned to someone, preferably tagged appropriately. -Send a message to the Frama-C channel on LSL's Mattermost. -Each developer should have a -look at their own assigned/monitored/reported issues. Depending on their severity, -the issues should be tagged with the current release, or with the next one. +Send a message to the Frama-C channel on LSL's Mattermost. Each developer should +have a look at their own assigned/monitored/reported issues. Depending on their +severity, the issues should be tagged with the current release, or with the next +one. -\section{Changelog} +\section{Version} -Create headers in the Changelog(s). This is to avoid some merge conflicts, -but also so that merge requests add information in the proper part of -the Changelog. - -\begin{itemize} -\item Add the following in the Changelogs, in \texttt{stable/element} -\begin{verbatim} - #################################### - Open Source Release <nb> (<element>) - #################################### -\end{verbatim} - -This should go directly below -\begin{verbatim} - ################################## - Open Source Release <next-release> - ################################## -\end{verbatim} - -The changelogs to update are the global Frama-C changelog and each plugin -changelog in \texttt{src/plugins}. - -\item Check the manuals if they contain a changelog, usually in files named -\texttt{changes.tex} or a variation of it. Add the following in -\texttt{stable/element} -\begin{verbatim} -\section*{<nb> (<element>)} -\end{verbatim} - -This should go directly below +Execute the script: \begin{verbatim} -\section*{\framacversion} +./dev/set-version.sh NN.M # to be replaced with actual major/minor version \end{verbatim} -and this line should be commented out. - +This will: \begin{itemize} - \item \emph{Take care to adapt the format of the version according to the - content of the file}. - \item \emph{Check for manual changelogs in \texttt{doc/}, but also in - \texttt{src/plugins/**/doc}}. -\end{itemize} - -\item Merge this branch in \texttt{master} + \item update the \texttt{Changelog}s + \item update the changes in the manuals (excluding ACSL and E-ACSL references) + \item update the \texttt{VERSION} and \texttt{VERSION\_CODENAME} files + \item update the \texttt{opam} file + \item update the API doc \end{itemize} -From now on, Changelog items corresponding to MR merged into \texttt{master} -must be placed between these two banners. This should minimize conflicts when -merging back \texttt{stable/element} into \texttt{master}. - -\todo{Can we simplify this?} +Merge the branch in \texttt{master} and add a commit to \texttt{master} by +adding \texttt{"+dev"} in the \texttt{VERSION} file. \section{Copyright} diff --git a/doc/release/deploy.tex b/doc/release/deploy.tex index 1de8304b27dacdfe3eebfff7b12998008f035a17..962db136ff2c9399e0ed7ae9011356ad0930cb1f 100644 --- a/doc/release/deploy.tex +++ b/doc/release/deploy.tex @@ -150,10 +150,6 @@ Check if other \FramaC (and related) repositories need to be updated: \item other \texttt{pub} repositories related to Frama-C... \end{itemize} -\section{Preparing the Next Release} - -Just update the \texttt{VERSION} file in \texttt{master}, by adding \texttt{"+dev"}. - \section{Docker image preparation} \textbf{Note:} you need access to the \texttt{framac} Docker Hub account to be diff --git a/doc/release/validation.tex b/doc/release/validation.tex index fd9ccc5fe0b912b7d783f7ceb074d0a0487e6a18..bc6ee9d90e10ef028896fa022a20e70cc9aea92c 100644 --- a/doc/release/validation.tex +++ b/doc/release/validation.tex @@ -46,25 +46,8 @@ Change version and codename in the following files: \end{itemize} \end{itemize} -Also check the headers in Changelogs : -\begin{itemize} - \item \texttt{Changelog} - \item \texttt{src/plugins/wp/Changelog} - \item \texttt{src/plugins/e-acsl/doc/Changelog} -\end{itemize} - \subsection{Versions in source: API documentation} -To update the \textsf{API} documentation, you must update the \texttt{@since} -tags. This involves the following script (\texttt{sed -i} must work for this -purpose): -\begin{shell} -./dev/update_api_doc.sh <NEXT> -\end{shell} -\verb+<NEXT>+ is the long name of the final release, i.e. -\verb+`cat VERSION`-`VERSION_CODENAME`+ -(without the \verb+beta+ suffix, if any). - Check that no \verb|+dev| suffix remains inside comments: \begin{shell} diff --git a/doc/userman/user-changes.tex b/doc/userman/user-changes.tex index 2c9097889fe6b3eab1e7409d805cf593136f4890..f5f6cc841c170e5783f3034849f6e508ecf700f7 100644 --- a/doc/userman/user-changes.tex +++ b/doc/userman/user-changes.tex @@ -3,8 +3,11 @@ This chapter summarizes the changes in this documentation between each \FramaC release. First we list changes of the last release. -\section*{Frama-C+dev} +%\section*{Frama-C+dev} + +\section*{27.0 (Cobalt)} \begin{itemize} +\item \textbf{Normalizing the Source Code:} new usage of \texttt{-machdep} \item \textbf{Normalizing the Source Code:} deprecated option \texttt{-c11} (enabled by default). \end{itemize} diff --git a/doc/userman/user-sources.tex b/doc/userman/user-sources.tex index b748156775df3412b336012ef6b37269a5608bef..b2256fa875b8c8d2cfdd7ed539652bfd0db76be3 100644 --- a/doc/userman/user-sources.tex +++ b/doc/userman/user-sources.tex @@ -296,8 +296,11 @@ The list of supported platforms can be obtained by typing: \$ frama-c -machdep help \end{frama-c-commands} -The process for adding a new platform is described in the Plug-in -Development Guide~\cite{plugin-dev-guide}. +Apart from these default platforms, it is possible to give as argument +to \texttt{-machdep} option the path of a YAML file containing the information +needed by \FramaC. The Plug-in Development Guide~\cite{plugin-dev-guide} describes +this format in more detail, as well as the use of the \texttt{make\_machdep.py} +script to automatically generate it. \item \optiondef{-}{simplify-cfg} allows \FramaC to remove break, continue and switch statements. This option is automatically set by some plug-ins that diff --git a/headers/headache_config.txt b/headers/headache_config.txt index 1b9796eb7a29140f1deeb877ca7f8aef54a17006..da136e6e52e5e19823c90dfa5eb466551f0e30a0 100644 --- a/headers/headache_config.txt +++ b/headers/headache_config.txt @@ -58,6 +58,8 @@ ######## | "dune-project" -> frame open:";;" line:";" close:";;" | ".*dune-project" -> skip match:"(lang.*" +| "dune-workspace.*" -> frame open:";;" line:";" close:";;" +| ".*dune-workspace.*" -> skip match:"(lang.*" | "dune" -> frame open:";;" line:";" close:";;" ############ diff --git a/ivette/.eslintrc.js b/ivette/.eslintrc.js index 3c9037c5af45b12f4b943734ed882bf55333d240..b2580f8d832220299877a3d52e9e4a436e1f22f0 100644 --- a/ivette/.eslintrc.js +++ b/ivette/.eslintrc.js @@ -52,6 +52,41 @@ module.exports = { // Disallow the use of console.* to prevent the release of code producing // various debuging messages "no-console": "error", + // Enforce consistent spacing after the // or /* in a comment + "spaced-comment": ["error", "always"], + // Enforce consistent spacing before and after the arrow in arrow functions + "arrow-spacing": "error", + // Enforce spaces inside of blocks after opening block and + // before closing block + "block-spacing": "error", + // Enforce consistent spacing before and after commas + "comma-spacing": "error", + // Enforce consistent newlines before and after dots + "dot-location": ["error", "property"], + // Require newline at the end of files + "eol-last": "error", + // Disallow spacing between function identifiers and their invocations + "func-call-spacing": "error", + // Enforce consistent spacing between keys and values in object literal + // properties + "key-spacing": "error", + // Disallow trailing whitespace at the end of lines + "no-trailing-spaces": "error", + // Enforce consistent spacing inside braces + "object-curly-spacing": ["error", "always"], + // Enforce consistent spacing before and after semicolons + "semi-spacing": "error", + // Enforce location of semicolons + "semi-style": "error", + // Enforce spacing around colons of switch statements + "switch-colon-spacing": "error", + // Enforce consistent spacing before blocks + "space-before-blocks": "error", + // Enforce consistent spacing before function definition opening parenthesis + "space-before-function-paren": [ + "error", + {"anonymous": "always", "named": "never", "asyncArrow": "always"} + ], // --- Safety rules --- diff --git a/ivette/.gitignore b/ivette/.gitignore index 5137465dd358ebe9aa0f203fc100c0b4cae255b5..08b3cc95e60a655d4d140fb6f410ec9dbedb4ebc 100644 --- a/ivette/.gitignore +++ b/ivette/.gitignore @@ -9,7 +9,6 @@ .eslint-cache node_modules yarn-error.log -/bin /dist /doc/html /src/renderer/loader.ts diff --git a/ivette/Makefile b/ivette/Makefile index 84dc2b6ad5acadfdc84b34dcd8cd4d92a1f949b9..4ce870bd17cd216d2c1b257e1bc808f81ac78f8e 100644 --- a/ivette/Makefile +++ b/ivette/Makefile @@ -23,9 +23,9 @@ # -------------------------------------------------------------------------- APP=Ivette DOME=./src/dome -DOME_ARGS=--command $$(dirname $$0)/../../bin/frama-c +DOME_ARGS=--command $$(dirname $$0)/frama-c DOME_DEV=-server-debug 1 -DOME_CLI=./bin/ivette +DOME_CLI=../bin/ivette DOME_API=./src/frama-c DOME_CUSTOM_ENTRIES= yes COPYRIGHT=CEA LIST / LSL @@ -35,21 +35,34 @@ COPYRIGHT=CEA LIST / LSL # --- Ivette Compilation # -------------------------------------------------------------------------- -.PHONY: all app dev lint checkcase tsc +.PHONY: all app dev -all: pkg lint app +all: pkg check-lint app -app: dome-app -dev: dome-dev +app: api dome-app +dev: api dome-dev -lint: dome-pkg dome-templ checkcase +# -------------------------------------------------------------------------- +# --- Ivette Linting +# -------------------------------------------------------------------------- + +.PHONY: lint check-lint check-case + +# With autofix +lint: dome-pkg dome-templ check-case + @echo "[Ivette] running typechecker & linter (with cache & fix mode)" + yarn run typecheck + yarn run lint --fix --cache --cache-location .eslint-cache + +# Without autofix +check-lint: dome-pkg dome-templ check-case @echo "[Ivette] running typechecker & linter" yarn run typecheck yarn run lint # In case-insensitive filesystems (macOS/Windows), import statements and # filenames can have issues due to case differences -checkcase: +check-case: @echo "[Ivette] check case issues in imported filenames" @err=0 ; for f in `find src | sed -E 's/(.ts|.tsx|.js|.jsx|.css|.json)$$//' | sort -f | uniq -di` ;\ do \ @@ -58,11 +71,6 @@ checkcase: done ;\ exit $$err -tsc: dome-pkg dome-templ - @echo "[Ivette] running typechecker & linter (with cache & fix mode)" - yarn run typecheck - yarn run lint --fix --cache --cache-location .eslint-cache - # -------------------------------------------------------------------------- # --- Help # -------------------------------------------------------------------------- @@ -75,14 +83,15 @@ help:: # --- Ivette Distribution # -------------------------------------------------------------------------- -.PHONY: dist dist-dir +.PHONY: dist appimage dist-dir + +dist: dist-dir dome-dist +appimage: dist-dir dome-appimage dist-dir: @echo "Cleaning dist" @rm -fr dist -dist: dist-dir dome-dist - # -------------------------------------------------------------------------- # --- Ivette Package Loader # -------------------------------------------------------------------------- @@ -94,11 +103,11 @@ SANDBOX=src/renderer/sandbox.ts PACKAGES=$(shell find src -name "pkg.json") SANDBOXES=$(shell find src/sandbox -name "*.tsx") -lint: pkg dome-pkg: pkg dome-app: pkg dome-dev: pkg dome-dist: pkg +dome-appimage: pkg pkg: $(LOADER) $(SANDBOX) @@ -118,7 +127,7 @@ $(SANDBOX): $(SANDBOXES) ./sandboxer.js ./Makefile # --- Frama-C API # -------------------------------------------------------------------------- -.PHONY: api +.PHONY: api check-api api: @echo "[Ivette] Generating TypeScript API" diff --git a/ivette/electron-builder.json b/ivette/electron-builder.json index ff7514100edc044947d80466558bcb99ea87c78c..4c25993d65459fa61fc90f665c5fe0714788554f 100644 --- a/ivette/electron-builder.json +++ b/ivette/electron-builder.json @@ -1,5 +1,9 @@ { "productName": "Ivette", "mac": { "icon": "icon.icns" }, - "linux": { "icon": "icon.png" } + "linux": { + "icon": "icon.png", + "target": "appImage", + "category": "Developpement" + } } diff --git a/ivette/ivette-bootstrap.sh b/ivette/ivette-bootstrap.sh index 5ce9ba70657d986e5fcfde39fca87290fa614b23..7ab111cffcb3cb46eefcd2b8a65c5b04648bc2ad 100755 --- a/ivette/ivette-bootstrap.sh +++ b/ivette/ivette-bootstrap.sh @@ -87,15 +87,15 @@ fi echo "[2/3] Compiling Ivette" # -------------------------------------------------------------------------- -TMPDIR=`mktemp -d` -cd $TMPDIR +IVETTE_TMP_DIR=`mktemp -d` +cd $IVETTE_TMP_DIR tar zxf $PREFIX/lib/frama-c/ivette.tgz cd ivette make dist if [ "$?" != "0" ] then echo "Compilation Failed" - rm -fr $TMPDIR + rm -fr $IVETTE_TMP_DIR exit 2 fi @@ -107,11 +107,11 @@ make PREFIX=$PREFIX install if [ "$?" != "0" ] then echo "Installation Failed" - rm -fr $TMPDIR + rm -fr $IVETTE_TMP_DIR exit 3 fi cd $USERCWD -rm -fr $TMPDIR +rm -fr $IVETTE_TMP_DIR rm -f $PREFIX/lib/frama-c/ivette.tgz # -------------------------------------------------------------------------- diff --git a/ivette/package.json b/ivette/package.json index 665132667063b1add37e44d44a1309a4b11c2ab2..a5f9526ccad99ede1383d421c93c9a10281b8d4d 100644 --- a/ivette/package.json +++ b/ivette/package.json @@ -5,6 +5,7 @@ "repository": "git@git.frama-c.com:frama-c/Ivette.git", "author": "Loïc Correnson <loic.correnson@cea.fr>", "license": "MIT", + "description": "Frama-C GUI", "scripts": { "lint": "eslint --ext .ts,.tsx --format=compact ./src", "typecheck": "tsc --noEmit", diff --git a/ivette/src/dome/main/dome.ts b/ivette/src/dome/main/dome.ts index d32c37a3f9c3c371a5705628c5dd8acb56865dab..993f45c5bdd104cb3bbe59bad0220b97631643ca 100644 --- a/ivette/src/dome/main/dome.ts +++ b/ivette/src/dome/main/dome.ts @@ -477,10 +477,22 @@ function createBrowserWindow( }); // Emitted when the window want's to close. - theWindow.on('close', () => { + const closeHandler = function (event: Event): void { + // Do not call this handler in a cycle; the next close event will forcibly + // close the window + theWindow.off('close', closeHandler); + // Do not close the window yet + event.preventDefault(); + handle.frame = theWindow.getBounds(); handle.devtools = webContents.isDevToolsOpened(); webContents.send('dome.ipc.closing'); + }; + + theWindow.on('close', closeHandler); + + ipcMain.on('dome.ipc.closing.done', () => { + theWindow.close(); }); // Keep track of frame positions (in DEVEL) @@ -501,8 +513,15 @@ function createBrowserWindow( // --- Application Window(s) & Command Line // -------------------------------------------------------------------------- -function stripElectronArgv(argv: string[]): string[] { - return argv.slice(DEVEL ? 3 : (LOCAL ? 2 : 1)).filter((p) => !!p); +interface Cmd { wdir: string; argv: string[] } + +function stripElectronArgv(cmd: Cmd): Cmd +{ + const wdir = DEVEL ? cmd.argv[3] : cmd.wdir; + const argv = cmd.argv + .slice(DEVEL ? 4 : (LOCAL ? 2 : 1)) + .filter((p) => !!p && p !== "--no-sandbox"); + return { wdir, argv }; } function createPrimaryWindow(): void { @@ -516,14 +535,14 @@ function createPrimaryWindow(): void { }); const cwd = process.cwd(); const wdir = cwd === '/' ? app.getPath('home') : cwd; - const argv = stripElectronArgv(process.argv); + const cmd = stripElectronArgv({ wdir, argv: process.argv }); // Initialize Theme const globals = obtainGlobalSettings(); applyThemeSettings(globals); // Create Window - createBrowserWindow(true, { title: appName }, argv, wdir); + createBrowserWindow(true, { title: appName }, cmd.argv, cmd.wdir); } let appCount = 1; @@ -538,9 +557,9 @@ function createSecondaryWindow( if (argString) { argString = argString.substring(argStart.length); const electronArgv = JSON.parse(argString); - const argv = stripElectronArgv(electronArgv); + const cmd = stripElectronArgv({ wdir, argv: electronArgv }); const title = `${appName} #${++appCount}`; - createBrowserWindow(false, { title }, argv, wdir); + createBrowserWindow(false, { title }, cmd.argv, cmd.wdir); } } @@ -624,6 +643,8 @@ ipcMain.on('dome.app.paths', (event) => { // --- Main Application Starter // -------------------------------------------------------------------------- +let isQuitting = false; + /** Starts the main process. */ export function start(): void { @@ -643,6 +664,11 @@ export function start(): void { app.on('activate', activateWindows); // Mac OSX response to dock app.on('second-instance', createSecondaryWindow); + // Configuring macOS for exiting + app.on('before-quit', () => { + isQuitting = true; + }); + // At-exit callbacks app.on('will-quit', () => { saveGlobalSettings(); @@ -654,7 +680,7 @@ export function start(): void { // Warning: when no event handler is registered, the app automatically // quit when all windows are closed. app.on('window-all-closed', () => { - if (System.platform !== 'macos') app.quit(); + if (isQuitting || System.platform !== 'macos') app.quit(); }); } diff --git a/ivette/src/dome/misc/system.ts b/ivette/src/dome/misc/system.ts index f97d6e7760df5f02ba7cc2a1860290ec7b03bcea..d3c6f8e5a7f6c01cfae4946ba67ec25d644d47d4 100644 --- a/ivette/src/dome/misc/system.ts +++ b/ivette/src/dome/misc/system.ts @@ -114,7 +114,7 @@ emitter.setMaxListeners(250); // --- At Exit // -------------------------------------------------------------------------- -export type Callback = () => void; +export type Callback = () => (void | Promise<void>); const exitJobs: Callback[] = []; @@ -128,11 +128,14 @@ export function atExit(callback: Callback): void { } /** Execute all pending exit jobs (and flush the list). */ -export function doExit(): void { - exitJobs.forEach((fn) => { - try { fn(); } +export async function doExit(): Promise<void> { + await Promise.all(exitJobs.map(async (fn) => { + try { + const promise = fn(); + promise && await promise; + } catch (err) { D.error('atExit:', err); } - }); + })); exitJobs.length = 0; } @@ -144,6 +147,7 @@ let COMMAND_WDIR = '.'; let COMMAND_ARGV: string[] = []; function setCommandLine(argv: string[], wdir: string): void { + process.chdir(wdir); COMMAND_ARGV = argv; COMMAND_WDIR = wdir; } @@ -464,13 +468,16 @@ export function rename(oldPath: string, newPath: string): Promise<void> { const childprocess = new Map<number, Exec.ChildProcess>(); -atExit(() => { - childprocess.forEach((process, pid) => { - try { process.kill(); } +atExit(async () => { + await Promise.all(Array.from(childprocess.values()).map(async (process) => { + try { + process.kill(); + await new Promise(resolve => process.on('exit', resolve)); + } catch (err) { - D.warn('killing process', pid, err); + D.warn('killing process', process.pid, err); } - }); + })); }); export type StdPipe = { path?: string | undefined; mode?: number; pipe?: boolean }; diff --git a/ivette/src/dome/renderer/controls/buttons.tsx b/ivette/src/dome/renderer/controls/buttons.tsx index e15fd0dbf4ef2131ed0f3103942862b8b1fae1c7..461524e30851a5c20e8b4812f4602e8bc3558f90 100644 --- a/ivette/src/dome/renderer/controls/buttons.tsx +++ b/ivette/src/dome/renderer/controls/buttons.tsx @@ -555,10 +555,9 @@ export interface FieldProps { Text Field. */ export const Field = (props: FieldProps): JSX.Element => { - const [current, setCurrent] = React.useState<string>(); const { className = '', onChange, onEdited, value = '' } = props; + const [current, setCurrent] = React.useState<string>(value); const disabled = onChange ? DISABLED(props) : true; - const theValue = current ?? value; const ONCHANGE = (evt: React.ChangeEvent<HTMLInputElement>): void => { const text = evt.target.value || ''; setCurrent(text); @@ -567,11 +566,11 @@ export const Field = (props: FieldProps): JSX.Element => { const ONKEYPRESS = (evt: React.KeyboardEvent): void => { switch (evt.key) { case 'Enter': - setCurrent(undefined); - if (onChange && current) onChange(current); + if (onChange) onChange(current); break; case 'Escape': - setCurrent(undefined); + setCurrent(value); + if (onChange) onChange(value); break; default: break; @@ -582,12 +581,12 @@ export const Field = (props: FieldProps): JSX.Element => { id={props.id} type="text" autoFocus={!disabled && props.autoFocus} - value={theValue} + value={current} className={`dome - xField ${className} `} style={props.style} disabled={disabled} placeholder={props.placeholder} - onKeyPress={ONKEYPRESS} + onKeyDown={ONKEYPRESS} onChange={ONCHANGE} /> ); diff --git a/ivette/src/dome/renderer/controls/labels.tsx b/ivette/src/dome/renderer/controls/labels.tsx index 382828a4f5c78b4f33db1ee8f59ec57516807a4d..9bf33338966698005165edb522aa0d29f9b38c42 100644 --- a/ivette/src/dome/renderer/controls/labels.tsx +++ b/ivette/src/dome/renderer/controls/labels.tsx @@ -63,8 +63,7 @@ export interface LabelProps { } const makeLabel = (className: string) => - function Label - ( + function Label( props: LabelProps, ref: LegacyRef<HTMLLabelElement> | undefined ): JSX.Element { diff --git a/ivette/src/dome/renderer/dark.css b/ivette/src/dome/renderer/dark.css index 0660868825afc53f7e051a476f593e2d9c4d15f6..cbe9a2b73b54eb26904eb96adbb7a80fef9c2000 100644 --- a/ivette/src/dome/renderer/dark.css +++ b/ivette/src/dome/renderer/dark.css @@ -10,8 +10,8 @@ --code-hover: #005137; --code-select: #4f3d24; --code-select-hover: #5f4d34; - --dead-code: #444; - --non-terminating: #444; + --dead-code: #777; + --non-terminating: #d84954; --highlighted-marker: #778822; --code-bullet: #0a2234; diff --git a/ivette/src/dome/renderer/data/arrays.ts b/ivette/src/dome/renderer/data/arrays.ts index a0db9f45a15e5b2df7fd218b48f7f5087d9b1d0a..994b261ac7006840e7e7fb2126447648799ab3a7 100644 --- a/ivette/src/dome/renderer/data/arrays.ts +++ b/ivette/src/dome/renderer/data/arrays.ts @@ -59,7 +59,7 @@ export function merge<K, A extends K, B extends K>( f: (x : K) => unknown, ): (A & (object | B))[] { const dict = new Map(a2.map(x2 => [f(x2), x2])); // maps f(x2) to x2 - return a1.map(x1 => ({...x1, ...(dict.get(f(x1)))})); + return a1.map(x1 => ({ ...x1, ...(dict.get(f(x1))) })); } /** Maps a function through an array and returns the first computed value that diff --git a/ivette/src/dome/renderer/data/json.ts b/ivette/src/dome/renderer/data/json.ts index 11f7a039384b5a76bcf6a106b9b096adc4c44825..f323711d086a5d0eeb077441ebaba7b95f9951d1 100644 --- a/ivette/src/dome/renderer/data/json.ts +++ b/ivette/src/dome/renderer/data/json.ts @@ -200,7 +200,7 @@ export const jInt: Decoder<number> = (js: json) => { return js; } else { - throw new JsonTypeError("integer", js); + throw new JsonTypeError("integer", js); } }; @@ -215,7 +215,7 @@ export const jBoolean: Decoder<boolean> = (js: json) => { return js; } else { - throw new JsonTypeError("boolean", js); + throw new JsonTypeError("boolean", js); } }; @@ -235,10 +235,10 @@ export const jString: Decoder<string> = (js: json) => { return js; } else { - throw new JsonTypeError("string", js); + throw new JsonTypeError("string", js); } }; - + /** JSON constant. Capture the tag or throw JsonError. @@ -251,7 +251,7 @@ export function jTag<A>(tg: A): Decoder<A> { return tg; } else { - throw new JsonTypeError(`"${tg}"`, js); + throw new JsonTypeError(`"${tg}"`, js); } }; } @@ -589,7 +589,7 @@ export function jKey<K>(kd: K): Decoder<key<K>> { return forge(kd, js); } else { - throw new JsonTypeError(`key<${kd}>`, js); + throw new JsonTypeError(`key<${kd}>`, js); } }; } @@ -601,7 +601,7 @@ export function jIndex<K>(kd: K): Decoder<index<K>> { return forge(kd, js); } else { - throw new JsonTypeError(`index<${kd}>`, js); + throw new JsonTypeError(`index<${kd}>`, js); } }; } diff --git a/ivette/src/dome/renderer/dnd.tsx b/ivette/src/dome/renderer/dnd.tsx index d1ad128c736e3b4cb70ecaa5f78b8b717b6e012b..7a7643036414ad413d4390591b88866760a92535 100644 --- a/ivette/src/dome/renderer/dnd.tsx +++ b/ivette/src/dome/renderer/dnd.tsx @@ -352,14 +352,14 @@ export interface DragSourceProps extends DragHandler, DropHandler { as a Drop Target into the DnD controller. */ export function DragSource(props: DragSourceProps): JSX.Element { - //--- Props + // --- Props const { dnd, disabled = false, handle, children } = props; const { onStart, onDrag, onStop } = props; - //--- Dragging State + // --- Dragging State const [dragging, setDragging] = React.useState<Dragging | undefined>(); - //--- Dropping Ref + // --- Dropping Ref const nodeRef = useDropTarget(dnd, disabled ? undefined : props); - //--- onStart + // --- onStart const handleStart: DraggableEventHandler = React.useCallback( (_, { x, y, node }) => { if (dnd && nodeRef.current) @@ -371,7 +371,7 @@ export function DragSource(props: DragSourceProps): JSX.Element { }); if (onStart) onStart(); }, [dnd, nodeRef, onStart]); - //--- onDrag + // --- onDrag const handleDrag: DraggableEventHandler = React.useCallback( (e, { x, y }) => { if (e && dnd) dnd.handleEvent(e); @@ -381,14 +381,14 @@ export function DragSource(props: DragSourceProps): JSX.Element { if (onDrag) onDrag(newDragging); } }, [dnd, dragging, onDrag]); - //--- onStop + // --- onStop const handleStop: DraggableEventHandler = React.useCallback( () => { if (dnd) dnd.handleDrop(); setDragging(undefined); if (onStop) onStop(); }, [dnd, onStop]); - //--- Renderer + // --- Renderer const render = RenderOverlay(props, dragging); return ( <DraggableCore @@ -447,25 +447,25 @@ export interface ItemProps { item contents is rendered inside a `<DragSource/>` component automatically connected to the englobing `<List/>` DnD controller. */ export function Item(props: ItemProps): JSX.Element { - //--- Ordering + // --- Ordering const { dnd, items, setSource, setTarget, onStop } = React.useContext(CurrentList); const { id, className, children } = props; const order = getItem(items, id); - //--- D&D Events + // --- D&D Events const onStart = React.useCallback(() => { if (setSource) setSource(id); }, [setSource, id]); const onDropIn = React.useCallback(() => { if (setTarget) setTarget(id); }, [setTarget, id]); - //--- Styling + // --- Styling const style = styles( props.style, order < 0 && { display: 'none' }, 0 <= order && { order }, ); - //--- Rendering + // --- Rendering return ( <DragSource className={className} diff --git a/ivette/src/dome/renderer/dome.tsx b/ivette/src/dome/renderer/dome.tsx index 2a19d1ec505a951e43a8e91d7537234c94b6146d..d05bbd025647811411d424b51848735991eb3992 100644 --- a/ivette/src/dome/renderer/dome.tsx +++ b/ivette/src/dome/renderer/dome.tsx @@ -251,10 +251,13 @@ export const globalSettings = new Event(Settings.global); // --- Closing // -------------------------------------------------------------------------- -ipcRenderer.on('dome.ipc.closing', System.doExit); +ipcRenderer.on('dome.ipc.closing', async () => { + await System.doExit(); + ipcRenderer.send('dome.ipc.closing.done'); + }); /** Register a callback to be executed when the window is closing. */ -export function atExit(callback: () => void): void { +export function atExit(callback: () => (void | Promise<void>)): void { System.atExit(callback); } @@ -603,7 +606,7 @@ export function usePromise<A>(job: Promise<A>): PromiseHook<A> { let c = false; const set = (x?: A, e?: Error): void => { setResult(x); setError(e); }; const doCancel = (): boolean => { if (!c) setLoading(false); return c; }; - const onResult = (x: A): void => { if (!doCancel()) set(x, undefined);}; + const onResult = (x: A): void => { if (!doCancel()) set(x, undefined); }; const onError = (e: Error): void => { if (!doCancel()) set(undefined, e); }; job.then(onResult, onError); return () => { c = true; }; diff --git a/ivette/src/dome/renderer/frame/sidebars.tsx b/ivette/src/dome/renderer/frame/sidebars.tsx index f0bab90f7187001cfcc7513e79538a2ad1dd82d2..f7b332affdf2e55298907c528465e9bbbf934171 100644 --- a/ivette/src/dome/renderer/frame/sidebars.tsx +++ b/ivette/src/dome/renderer/frame/sidebars.tsx @@ -34,7 +34,7 @@ import { useFlipSettings } from 'dome'; import { Badge } from 'dome/controls/icons'; import { Label } from 'dome/controls/labels'; import { classes } from 'dome/misc/utils'; -import { Hbox, Hfill } from 'dome/layout/boxes'; +import { Hbox } from 'dome/layout/boxes'; import { IconButton, IconButtonProps } from 'dome/controls/buttons'; import './style.css'; @@ -110,6 +110,8 @@ export interface SectionProps { disabled?: boolean; /** Badge summary (only visible when folded). */ summary?: Badges; + /** Additional label, right-aligned. */ + infos?: string; /** Additional controls, (only visible when unfolded). */ rightButtonProps?: IconButtonProps; /** Section contents. */ @@ -129,7 +131,7 @@ export interface SectionProps { Sections with no items are not displayed. */ export function Section(props: SectionProps): JSX.Element | null { - const { settings, defaultUnfold, unfold } = props; + const { settings, defaultUnfold, infos, unfold } = props; const [state, flipState] = useFlipSettings(settings, defaultUnfold); const icon = state ? 'TRIANGLE.DOWN' : 'TRIANGLE.RIGHT'; @@ -145,15 +147,14 @@ export function Section(props: SectionProps): JSX.Element | null { return ( <div className={`dome-xSideBarSection ${props.className}`}> - <Hbox> + <Hbox className='dome-xSideBarSection-title' > <Label - className='dome-xSideBarSection-title dome-color-frame' title={props.title} label={props.label} icon={icon} onClick={flipState} /> - <Hfill /> + {infos && <div className='dome-xSideBarSection-infos'>{infos}</div>} {visible ? rightButton : makeBadge(props.summary)} </Hbox> <div className='dome-xSideBarSection-content' style={{ maxHeight }}> diff --git a/ivette/src/dome/renderer/frame/style.css b/ivette/src/dome/renderer/frame/style.css index ed917a3189b1e5a241f3c41a399c2b7c7b439ecb..6ee566c0a2684df21fb5c9704a0d216e157a29f9 100644 --- a/ivette/src/dome/renderer/frame/style.css +++ b/ivette/src/dome/renderer/frame/style.css @@ -90,8 +90,7 @@ padding: 0px ; } -.dome-xSideBar.dome-color-frame, -.dome-xSideBarSection-title.dome-color-frame +.dome-xSideBar.dome-color-frame { background: var(--background-sidebar) ; } @@ -116,6 +115,7 @@ display: flex ; flex-flow: row nowrap ; align-items: center ; + background: var(--background-sidebar) ; } .dome-xSideBarSection-title > .dome-xLabel { @@ -129,9 +129,17 @@ flex: 0 0 ; } +.dome-xSideBarSection-infos { + font-size: smaller; + color: var(--info-text-discrete); + padding-left: 4px; + padding-right: 4px; + display: block; +} + .dome-xSideBarSection-filterButton { margin: 0px; - padding: 0px; + padding: 3px; } .dome-xSideBarSection-hideshow { @@ -162,14 +170,6 @@ display: flex; } -.dome-xSideBarSection-info { - color: var(--info-text-discrete); - font-style: italic; - padding-left: 20px; - padding-right: 10px; - display: block; -} - /* -------------------------------------------------------------------------- */ /* --- SideBar Items --- */ /* -------------------------------------------------------------------------- */ @@ -443,16 +443,12 @@ padding: 0; overflow: hidden; font-size: 13px; - width: 28px; + width: 228px; border-radius: 12px; transition: width 0.4s ease-in-out; z-Index: +1; } -.dome-xToolBar-actionField:hover { - width: 228px; -} - .dome-xToolBar-actionField:focus-within { width: 228px !important; box-shadow: 0 0 2px var(--border-discrete); diff --git a/ivette/src/dome/renderer/layout/qsplit.tsx b/ivette/src/dome/renderer/layout/qsplit.tsx index ec10dd95311972c827d0b25a2e85de807cc0124c..5241ef0a3ae373ec5e8de5e02f9506b30f940079 100644 --- a/ivette/src/dome/renderer/layout/qsplit.tsx +++ b/ivette/src/dome/renderer/layout/qsplit.tsx @@ -307,31 +307,31 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element { const BD = sameOf(B, D); const CD = sameOf(C, D); const ABCD = fullOf(A, B, C, D); - //---------------------------------------- + // ---------------------------------------- // [ A ] - //--------------------------------------- + // --------------------------------------- if (ABCD) { DISPLAY(layout, ABCD, 0, width, 0, height); } - //---------------------------------------- + // ---------------------------------------- // [ A - C ] - //--------------------------------------- + // --------------------------------------- else if (AB && CD) { vsplit = VSPLIT(0, Y, width); DISPLAY(layout, AB, 0, width, 0, Y); DISPLAY(layout, CD, 0, width, Y + 1, RY); } - //---------------------------------------- + // ---------------------------------------- // [ A | B ] - //--------------------------------------- + // --------------------------------------- else if (AC && BD) { hsplit = HSPLIT(X, 0, height); DISPLAY(layout, AC, 0, X, 0, height); DISPLAY(layout, BD, X + 1, RX, 0, height); } - //---------------------------------------- + // ---------------------------------------- // [ A – C|D ] - //---------------------------------------- + // ---------------------------------------- else if (AB) { hsplit = HSPLIT(X, Y, RY); vsplit = VSPLIT(0, Y, width); @@ -339,9 +339,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element { DISPLAY(layout, C, 0, X, Y + 1, RY); DISPLAY(layout, D, X + 1, RX, Y + 1, RY); } - //---------------------------------------- + // ---------------------------------------- // [ A | B-D ] - //---------------------------------------- + // ---------------------------------------- else if (AC) { hsplit = HSPLIT(X, 0, height); vsplit = VSPLIT(X, Y, RY); @@ -349,9 +349,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element { DISPLAY(layout, B, X + 1, RX, 0, Y); DISPLAY(layout, D, X + 1, RX, Y + 1, RY); } - //---------------------------------------- + // ---------------------------------------- // [ A-C | B ] - //---------------------------------------- + // ---------------------------------------- else if (BD) { hsplit = HSPLIT(X, 0, height); vsplit = VSPLIT(0, Y, X); @@ -359,9 +359,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element { DISPLAY(layout, BD, X + 1, RX, 0, height); DISPLAY(layout, C, 0, X, Y + 1, RY); } - //---------------------------------------- + // ---------------------------------------- // [ A|B - C ] - //---------------------------------------- + // ---------------------------------------- else if (CD) { hsplit = HSPLIT(X, 0, Y); vsplit = VSPLIT(0, Y, width); @@ -369,9 +369,9 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element { DISPLAY(layout, B, X + 1, RX, 0, Y); DISPLAY(layout, CD, 0, width, Y + 1, RY); } - //---------------------------------------- + // ---------------------------------------- // [ A, B, C, D ] - //---------------------------------------- + // ---------------------------------------- else { hsplit = HSPLIT(X, 0, height); vsplit = VSPLIT(0, Y, width); @@ -380,12 +380,12 @@ function QSplitEngine(props: QSplitEngineProps): JSX.Element { DISPLAY(layout, C, 0, X, Y + 1, RY); DISPLAY(layout, D, X + 1, RX, Y + 1, RY); } - //---------------------------------------- + // ---------------------------------------- if (hsplit !== NODISPLAY && vsplit !== NODISPLAY) hvsplit = { display: 'block', left: X, top: Y }; - //---------------------------------------- + // ---------------------------------------- // Rendering - //---------------------------------------- + // ---------------------------------------- return ( <QSplitContext.Provider value={layout}> <BSplitter diff --git a/ivette/src/dome/renderer/light.css b/ivette/src/dome/renderer/light.css index 0caf3fb0e549257228f9e19d34c17a8b73f51b34..135bd1ef348473c56143123b5e73d2b6cd9e5c82 100644 --- a/ivette/src/dome/renderer/light.css +++ b/ivette/src/dome/renderer/light.css @@ -10,8 +10,8 @@ --code-hover: lightgreen; --code-select: #ffda95; --code-select-hover: orange; - --dead-code: #bbb; - --non-terminating: #bbb; + --dead-code: #999; + --non-terminating: #fb4e4a; --highlighted-marker: #ffff66; --code-bullet: #ddd; diff --git a/ivette/src/dome/renderer/table/arrays.ts b/ivette/src/dome/renderer/table/arrays.ts index 45d3d48bb99709d39c26556b3c684a7f7473d24f..16d1e29ba1fab4d11c435201113488eb2ed505c2 100644 --- a/ivette/src/dome/renderer/table/arrays.ts +++ b/ivette/src/dome/renderer/table/arrays.ts @@ -454,6 +454,11 @@ export class ArrayModel<Key, Row> this.index.forEach((p) => { fn(p.row); }); } + /** Number of non-filtered entries. */ + length(): number { + return this.index.size; + } + } // -------------------------------------------------------------------------- diff --git a/ivette/src/dome/renderer/text/editor.tsx b/ivette/src/dome/renderer/text/editor.tsx index 7ca40b680eba78057fdd0ce13b21e378afbb86b0..ea59f699394de28ca868c041c3b6b47f03100437 100644 --- a/ivette/src/dome/renderer/text/editor.tsx +++ b/ivette/src/dome/renderer/text/editor.tsx @@ -310,13 +310,13 @@ const Highlight = Language.syntaxHighlighting(Language.HighlightStyle.define([ { tag: tags.typeName, class: 'cm-type' }, { tag: tags.number, class: 'cm-number' }, { tag: tags.controlKeyword, class: 'cm-keyword' }, - { tag: tags.definition(tags.variableName) , class: 'cm-def' }, + { tag: tags.definition(tags.variableName), class: 'cm-def' }, ])); // A language provider based on the [Lezer C++ parser], extended with // highlighting and folding information. Only comments can be folded. // (Source: https://github.com/lezer-parser/cpp) -const comment = (t: SyntaxNode): Range => ({ from: t.from + 2, to: t.to - 2}); +const comment = (t: SyntaxNode): Range => ({ from: t.from + 2, to: t.to - 2 }); const folder = Language.foldNodeProp.add({ BlockComment: comment }); const stringPrefixes = [ "L", "u", "U", "u8", "LR", "UR", "uR", "u8R", "R" ]; const cppLanguage = Language.LRLanguage.define({ @@ -432,6 +432,18 @@ export function unfoldAll(view: View): void { if (view !== null) Language.unfoldAll(view); } +function isVisible(view: View, line: number): boolean { + if (!view || view.state.doc.lines < line) return false; + const doc = view.state.doc; + const top = view.documentTop; + const rect = view.dom.getBoundingClientRect(); + const topVisibleBlock = view.lineBlockAtHeight(rect.top - top); + const topVisibleLine = doc.lineAt(topVisibleBlock.to).number; + const bottomVisibleBlock = view.lineBlockAtHeight(rect.bottom - top); + const bottomVisibleLine = doc.lineAt(bottomVisibleBlock.from).number; + return (topVisibleLine < line && line < bottomVisibleLine); +} + // Move to the given line. The indexation starts at 1. export function selectLine(view: View, line: number, atTop: boolean): void { if (!view || view.state.doc.lines < line) return; @@ -439,9 +451,10 @@ export function selectLine(view: View, line: number, atTop: boolean): void { const { from: here } = doc.lineAt(view.state.selection.main.from); const { from: goto } = doc.line(Math.max(line, 1)); if (here === goto) return; - view.dispatch({ selection: { anchor: goto }, scrollIntoView: true }); - if (!atTop) return; - const effects = EditorView.scrollIntoView(goto, { y: 'start', yMargin: 0 }); + view.dispatch({ selection: { anchor: goto } }); + if (isVisible(view, line)) return; + const verticalScroll = atTop ? 'start' : 'center'; + const effects = EditorView.scrollIntoView(goto, { y: verticalScroll }); view.dispatch({ effects }); } diff --git a/ivette/src/dome/renderer/text/style.css b/ivette/src/dome/renderer/text/style.css index a299cc047c2f86f9defd7ed5d4fd6bce27577fa3..3b26fd8a537d41bdaa6ec097adc1eb648e4ce690 100644 --- a/ivette/src/dome/renderer/text/style.css +++ b/ivette/src/dome/renderer/text/style.css @@ -183,6 +183,12 @@ background: var(--code-bullet); } +.cm-deadcode-gutter { + width: 4px; + background: var(--code-bullet); + color: var(--dead-code); +} + .cm-hovered-code { background-color: var(--code-hover); } @@ -199,14 +205,12 @@ background-color: var(--highlighted-marker); } -.cm-dead-code { +:not(.cm-dead-code) > .cm-dead-code { font-style: italic; - filter: opacity(0.7); + filter: opacity(0.5); } .cm-non-term-code { - font-style: italic; - filter: opacity(0.7); } .cm-tainted { diff --git a/ivette/src/dome/renderer/themes.tsx b/ivette/src/dome/renderer/themes.tsx index 9cbccae6908332a555c7033b1eb80a518c57d604..5a21d6b45c1b56c24bbd283d7d658e3f797489c6 100644 --- a/ivette/src/dome/renderer/themes.tsx +++ b/ivette/src/dome/renderer/themes.tsx @@ -29,7 +29,7 @@ @module dome/themes */ -//import React from 'react'; +// import React from 'react'; import * as Dome from 'dome'; import * as Settings from 'dome/data/settings'; import { State } from 'dome/data/states'; diff --git a/ivette/src/dome/template/makefile b/ivette/src/dome/template/makefile index b79a6e427570a59875966f7b19825a5aa5039b02..f2545cfde15901a9b3e00086a1e28bc6bb58f398 100644 --- a/ivette/src/dome/template/makefile +++ b/ivette/src/dome/template/makefile @@ -25,6 +25,7 @@ # -------------------------------------------------------------------------- # DOMEMK_ reserved for makefile derived variables +# CURDIR is a Makefile builtin variable APP?=$(shell basename $(CURDIR)) COPYRIGHT?=CEA Tech @@ -220,10 +221,11 @@ dome-dev: dome-pkg dome-templ @echo "#!/bin/sh" >> $(DOME_CLI) @echo "export DOME='$(DOME)'" >> $(DOME_CLI) @echo "export DOME_ENV='dev'" >> $(DOME_CLI) - @echo 'exec $(DOME_MK_BIN)/electron-webpack dev $(DOME_ARGS) $(DOME_DEV) "$$@"' >> $(DOME_CLI) + @echo 'WDIR=$$PWD' >> $(DOME_CLI) + @echo 'ARGV="$(DOME_ARGS) $(DOME_DEV) $$@"' >> $(DOME_CLI) + @echo "cd $(CURDIR)" >> $(DOME_CLI) + @echo 'exec $(DOME_MK_BIN)/electron-webpack dev $$WDIR $$ARGV' >> $(DOME_CLI) @chmod 555 $(DOME_CLI) - @echo "[Dome] running application (development)" - @$(DOME_CLI) # -------------------------------------------------------------------------- # --- Application Building @@ -246,13 +248,20 @@ dome-app: dome-pkg dome-templ # --- Application Packaging # -------------------------------------------------------------------------- -.PHONY: dome-dist +.PHONY: dome-dist dome-appimage +# Compatible with all OS for installation from source dome-dist: dome-app - @echo "[Dome] packaging application (production)" + @echo "[Dome] packaging application (binary)" DOME=$(DOME) yarn run electron-builder --dir -c.compression=store -c.mac.identity=null @echo "[Dome] application packaged in ./dist" +# Build Linux AppImage for binary distribution +dome-appimage: dome-app + @echo "[Dome] packaging application (AppImage)" + DOME=$(DOME) yarn run electron-builder --linux -c.compression=store -c.mac.identity=null + @echo "[Dome] application packaged in ./dist" + # -------------------------------------------------------------------------- # --- Icon gallery # -------------------------------------------------------------------------- diff --git a/ivette/src/frama-c/kernel/ASTview.tsx b/ivette/src/frama-c/kernel/ASTview.tsx index c02f1b2fcf9b96ca3f33f2e400cee4112fe707c0..35a124c9ea372b193fc00bb233abbbce9d303283 100644 --- a/ivette/src/frama-c/kernel/ASTview.tsx +++ b/ivette/src/frama-c/kernel/ASTview.tsx @@ -49,7 +49,9 @@ import * as Preferences from 'ivette/prefs'; // An alias type for functions and locations. type Fct = string | undefined; -type Marker = string | undefined; +type Marker = Ast.marker | undefined; + +const noMarker = Ast.jMarker(''); // A range is just a pair of position in the code. type Range = Editor.Range; @@ -74,12 +76,12 @@ function mapFilter<A, B>(xs: readonly A[], fn: (x: A) => B | undefined): B[] { // without information on the ranges of each element. It will be converted in a // good old tree that carry those information. interface Leaf extends Range { text: string } -interface Node extends Range { id: string, children: Tree[] } +interface Node extends Range { marker: Ast.marker, children: Tree[] } type Tree = Leaf | Node; // Utility functions on trees. -function isLeaf (t: Tree): t is Leaf { return 'text' in t; } -function isNode (t: Tree): t is Node { return 'id' in t && 'children' in t; } +function isLeaf(t: Tree): t is Leaf { return 'text' in t; } +function isNode(t: Tree): t is Node { return 'marker' in t && 'children' in t; } const empty: Tree = { text: '', from: 0, to: 0 }; // Convert an Ivette text (i.e a function's code) into a Tree, adding range @@ -98,7 +100,7 @@ function textToTree(t: text): Tree | undefined { if (node) children.push(node); acc = to; } - return [{ id: t[0], from, to: acc, children }, acc]; + return [{ marker: Ast.jMarker(t[0]), from, to: acc, children }, acc]; } const [res] = aux(t, 0); return res; @@ -116,13 +118,13 @@ function textToString(text: text): string { // Computes, for each markers of a tree, its range. Returns the map containing // all those bindings. -function markersRanges(tree: Tree): Map<string, Range[]>{ +function markersRanges(tree: Tree): Map<string, Range[]> { const ranges: Map<string, Range[]> = new Map(); const toRanges = (tree: Tree): void => { if (!isNode(tree)) return; - const trees = ranges.get(tree.id) ?? []; + const trees = ranges.get(tree.marker) ?? []; trees.push(tree); - ranges.set(tree.id, trees); + ranges.set(tree.marker, trees); for (const child of tree.children) toRanges(child); }; toRanges(tree); @@ -159,7 +161,7 @@ const Text = Editor.createTextField<text>(null, textToString); // This aspect computes the tree representing the currently displayed function's // code, represented by the <Text> field. -const Tree = Editor.createAspect({ t: Text }, ({t}) => rootText(t)); +const Tree = Editor.createAspect({ t: Text }, ({ t }) => rootText(t)); // This aspect computes the markers ranges of the currently displayed function's // tree, represented by the <Tree> aspect. @@ -198,8 +200,8 @@ function createMarkerUpdater(): Editor.Extension { return Editor.createEventHandler(deps, { mouseup: ({ fct, tree, update }, view, event) => { const main = view.state.selection.main; - const id = coveringNode(tree, main.from)?.id; - const location = { fct, marker: Ast.jMarker(id) }; + const marker = coveringNode(tree, main.from)?.marker; + const location = { fct, marker }; update({ location }); if (event.altKey) States.MetaSelection.emit(location); } @@ -217,7 +219,8 @@ function createMarkerScroller(): Editor.Extension { const markerRanges = ranges.get(marker) ?? []; if (markerRanges.length !== 1) return; const { from: anchor } = markerRanges[0]; - view.dispatch({ selection: { anchor }, scrollIntoView: true }); + const line = view.state.doc.lineAt(anchor).number; + Editor.selectLine(view, line, false); }); } @@ -235,7 +238,7 @@ const Hovered = Editor.createField<Marker>(undefined); // The Ivette hovered element must be updated by CodeMirror plugins. This // field add the callback in the CodeMirror internal state. type UpdateHovered = (h: States.Hovered) => void; -const UpdateHovered = Editor.createField<UpdateHovered>(() => { return ; }); +const UpdateHovered = Editor.createField<UpdateHovered>(() => { return; }); // The Hovered field is updated each time the mouse moves through the CodeMirror // document. The handlers updates the Ivette hovered information, which is then @@ -263,7 +266,7 @@ function createHoveredUpdater(): Editor.Extension { const horizontallyOk = left <= coords.x && coords.x <= right; const verticallyOk = top <= coords.y && coords.y <= bottom; if (!horizontallyOk || !verticallyOk) { reset(); return; } - const marker = Ast.jMarker(hov.id); + const marker = hov.marker; updateHovered(marker ? { fct, marker } : undefined); } }); @@ -322,18 +325,68 @@ function createMultipleDecorator(): Editor.Extension { const emptyDeadCode = { unreachable: [], nonTerminating: [] }; const Dead = Editor.createField<Eva.deadCode>(emptyDeadCode); +const UnreachableRanges = createUnreachableRanges(); +function createUnreachableRanges(): Editor.Aspect<Editor.Range[]> { + const deps = { dead: Dead, ranges: Ranges }; + return Editor.createAspect(deps, ({ dead, ranges }) => { + return mapFilter(dead.unreachable, m => ranges.get(m)).flat(); + }); +} + +const NonTerminatingRanges = createNonTerminatingRanges(); +function createNonTerminatingRanges(): Editor.Aspect<Editor.Range[]> { + const deps = { dead: Dead, ranges: Ranges }; + return Editor.createAspect(deps, ({ dead, ranges }) => { + return mapFilter(dead.nonTerminating, m => ranges.get(m)).flat(); + }); +} + const DeadCodeDecorator = createDeadCodeDecorator(); function createDeadCodeDecorator(): Editor.Extension { - const uClass = Editor.Decoration.mark({ class: 'cm-dead-code' }); - const tClass = Editor.Decoration.mark({ class: 'cm-non-term-code' }); - const deps = { dead: Dead, ranges: Ranges }; - return Editor.createDecorator(deps, ({ dead, ranges }) => { - const range = (m: string): Range[] | undefined => ranges.get(m); - const unreachableRanges = mapFilter(dead.unreachable, range).flat(); - const unreachable = unreachableRanges.map(r => uClass.range(r.from, r.to)); - const nonTermRanges = mapFilter(dead.nonTerminating, range).flat(); - const nonTerm = nonTermRanges.map(r => tClass.range(r.from, r.to)); - return Editor.RangeSet.of(unreachable.concat(nonTerm), true); + const uCls = Editor.Decoration.mark({ class: 'cm-dead-code' }); + const tCls = Editor.Decoration.mark({ class: 'cm-non-term-code' }); + const deps = { unreach: UnreachableRanges, nonTerm: NonTerminatingRanges }; + return Editor.createDecorator(deps, ({ unreach, nonTerm }) => { + const unreachable = unreach.map(r => uCls.range(r.from, r.to)); + const nonTerminating = nonTerm.map(r => tCls.range(r.from, r.to)); + return Editor.RangeSet.of(unreachable.concat(nonTerminating), true); + }); +} + +type DeadCodeKind = 'unreachable' | 'non terminating'; +class DeadCodeGutterMarker extends Editor.GutterMarker { + readonly element: HTMLDivElement; + toDOM(): HTMLDivElement { return this.element; } + constructor(kind: DeadCodeKind) { + super(); + const color = kind === 'unreachable' ? 'dead-code' : 'non-terminating'; + this.element = document.createElement('div'); + this.element.innerHTML = 'a'; + this.element.title = `This code is ${kind}`; + this.element.style.width = '4px'; + this.element.style.color = `var(--${color})`; + this.element.style.borderRight = `4px solid var(--${color})`; + } +} + +const DeadCodeGutter = createDeadCodeGutter(); +function createDeadCodeGutter(): Editor.Extension { + const deps = { unreach: UnreachableRanges, nonTerm: NonTerminatingRanges }; + const cls = 'cm-deadcode-gutter'; + return Editor.createGutter(deps, cls, (props, block, view) => { + const doc = view.state.doc; + const line = doc.lineAt(block.from); + const unreachable = props.unreach + .filter(r => r.from <= doc.length) + .map(r => ({ from: doc.lineAt(r.from).from, to: doc.lineAt(r.to).to })) + .find(r => r.from <= line.from && line.to <= r.to); + if (unreachable) return new DeadCodeGutterMarker('unreachable'); + const nonTerm = props.nonTerm + .filter(r => r.from <= doc.length) + .map(r => ({ from: doc.lineAt(r.from).from, to: doc.lineAt(r.to).to })) + .find(r => r.from <= line.from && line.to <= r.to); + if (nonTerm) return new DeadCodeGutterMarker('non terminating'); + return null; }); } @@ -357,7 +410,7 @@ function getPropertiesNodes(tree: Tree): Node[] { if (isLeaf(tree)) return []; /* Must be consistent with the id chosen by the Frama-C server for property markers. Ideally, this test should not depend on markers id syntax. */ - if (tree.id.startsWith('#p')) return [tree]; + if (tree.marker.startsWith('#p')) return [tree]; return tree.children.map(getPropertiesNodes).flat(); } @@ -369,7 +422,7 @@ function createPropertiesNodes() : Editor.Aspect<Property[]> { return Editor.createAspect(deps, ({ tree, tags, statuses }) => { const nodes = getPropertiesNodes(tree); return mapFilter(nodes, (n) => { - const s = statuses.find((s) => s.key === n.id); + const s = statuses.find((s) => s.key === n.marker); if (!s) return undefined; const tag = tags.get(s.status); if (!tag) return undefined; @@ -480,23 +533,27 @@ async function studia(props: StudiaProps): Promise<StudiaInfos> { // This field contains all the current function's callers, as inferred by Eva. const Callers = Editor.createField<Eva.CallSite[]>([]); +// This field contains the function pointed to by the current hovered marker, +// as inferred by Eva. +const Callees = Editor.createField<Fct[]>([]); + // This field contains information on markers. -type GetMarkerData = (key: string) => Ast.markerAttributesData | undefined; +type GetMarkerData = (key: Ast.marker) => Ast.markerAttributesData | undefined; const GetMarkerData = Editor.createField<GetMarkerData>(() => undefined); const ContextMenuHandler = createContextMenuHandler(); function createContextMenuHandler(): Editor.Extension { - const data = { tree: Tree, callers: Callers }; + const data = { tree: Tree, callers: Callers, callees: Callees }; const deps = { ...data, update: UpdateSelection, getData: GetMarkerData }; return Editor.createEventHandler(deps, { contextmenu: (inputs, view, event) => { - const { tree, callers, update, getData } = inputs; + const { tree, callers, callees, update, getData } = inputs; const coords = { x: event.clientX, y: event.clientY }; const position = view.posAtCoords(coords); if (!position) return; const node = coveringNode(tree, position); - if (!node || !node.id) return; + if (!node || !node.marker) return; const items: Dome.PopupMenuItem[] = []; - const attrs = getData(node.id); + const attrs = getData(node.marker); if (attrs?.isFunDecl) { const groupedCallers = Lodash.groupBy(callers, (cs) => cs.kf); const locations = @@ -519,15 +576,27 @@ function createContextMenuHandler(): Editor.Extension { const label = `Go to definition of ${attrs.name}`; items.push({ label, onClick }); } + else if (attrs?.isFunctionPointer) { + Lodash.forEach(callees, (fct) => { + const onClick = (): void => update({ location: { fct } }); + const label = `Go to definition of ${fct} (indirect)`; + items.push({ label, onClick }); + }); + } const enabled = attrs?.isLval; const onClick = (kind: access): void => { - if (attrs && node.id) - studia({ marker: node.id, attrs, kind }).then(update); + if (attrs && node.marker) + studia({ marker: node.marker, attrs, kind }).then(update); }; const reads = 'Studia: select reads'; const writes = 'Studia: select writes'; items.push({ label: reads, enabled, onClick: () => onClick('Reads') }); items.push({ label: writes, enabled, onClick: () => onClick('Writes') }); + const copy = (): void => { + const text = view.state.sliceDoc(node.from, node.to); + if (text !== '') navigator.clipboard.writeText(text); + }; + items.push({ label: 'Copy to clipboard', onClick: copy }); if (items.length > 0) Dome.popupMenu(items); return; } @@ -617,6 +686,11 @@ function useFctCallers(fct: Fct): Eva.CallSite[] { return States.useRequest(Eva.getCallers, fct) ?? []; } +// Server request handler returning the given function's callers. +function useCallees(marker: Marker): Fct[] { + return States.useRequest(Eva.getCallees, marker || undefined) ?? []; +} + // Server request handler returning the tainted lvalues. function useFctTaints(fct: Fct): Eva.LvalueTaints[] { return States.useRequest(Eva.taintedLvalues, fct, { onError: [] }) ?? []; @@ -641,6 +715,7 @@ const extensions: Editor.Extension[] = [ DeadCodeDecorator, ContextMenuHandler, PropertiesGutter, + DeadCodeGutter, TaintedLvaluesDecorator, TaintTooltip, Editor.ReadOnly, @@ -665,11 +740,12 @@ export default function ASTview(): JSX.Element { // Updating CodeMirror when the <updateHovered> callback is changed. const [hov, setHov] = States.useHovered(); + const hovered = hov?.marker ?? noMarker; React.useEffect(() => UpdateHovered.set(view, setHov), [view, setHov]); - React.useEffect(() => Hovered.set(view, hov?.marker ?? ''), [view, hov]); + React.useEffect(() => Hovered.set(view, hovered), [view, hovered]); // Updating CodeMirror when the <properties> synchronized array is changed. - const props = States.useSyncArray(Properties.status).getArray(); + const props = States.useSyncArrayData(Properties.status); React.useEffect(() => PropertiesStatuses.set(view, props), [view, props]); // Updating CodeMirror when the <propStatusTags> map is changed. @@ -677,8 +753,7 @@ export default function ASTview(): JSX.Element { React.useEffect(() => Tags.set(view, tags), [view, tags]); // Updating CodeMirror when the <markersInfo> synchronized array is changed. - const info = States.useSyncArray(Ast.markerAttributes); - const getData = React.useCallback((key) => info.getData(key), [info]); + const getData = States.useSyncArrayGetter(Ast.markerAttributes); React.useEffect(() => GetMarkerData.set(view, getData), [view, getData]); // Retrieving data on currently selected function and updating CodeMirror when @@ -692,6 +767,10 @@ export default function ASTview(): JSX.Element { const taints = useFctTaints(fct); React.useEffect(() => TaintedLvalues.set(view, taints), [view, taints]); + // Retrieving data on currently hovered marker. + const callees = useCallees(hovered); + React.useEffect(() => Callees.set(view, callees), [view, callees]); + return ( <> <TitleBar> @@ -712,7 +791,7 @@ export default function ASTview(): JSX.Element { /> <Inset /> </TitleBar> - <Component style={{ fontSize: `${fontSize}px`}} /> + <Component style={{ fontSize: `${fontSize}px` }} /> </> ); } diff --git a/ivette/src/frama-c/kernel/Globals.tsx b/ivette/src/frama-c/kernel/Globals.tsx index 78d4ed4189b20acb235ceade6a25abcee4018bdd..827957171c9f59670571422193e636da8544c890 100644 --- a/ivette/src/frama-c/kernel/Globals.tsx +++ b/ivette/src/frama-c/kernel/Globals.tsx @@ -32,8 +32,6 @@ import { alpha } from 'dome/data/compare'; import { Section, Item } from 'dome/frame/sidebars'; import { Button } from 'dome/controls/buttons'; import * as Toolbars from 'dome/frame/toolbars'; -import * as Models from 'dome/table/models'; -import * as Arrays from 'dome/table/arrays'; import * as States from 'frama-c/states'; import * as Kernel from 'frama-c/kernel/api/ast'; @@ -106,15 +104,13 @@ type functionsData = type FctKey = Json.key<'#functions'>; function computeFcts( - ker: Arrays.CompactModel<FctKey,Kernel.functionsData>, - eva: Arrays.CompactModel<FctKey,Eva.functionsData>, - _kstamp: number, - _estamp: number, + ker: States.ArrayProxy<FctKey, Kernel.functionsData>, + eva: States.ArrayProxy<FctKey, Eva.functionsData>, ): functionsData[] { const arr: functionsData[] = []; ker.forEach((kf) => { const ef = eva.getData(kf.key); - arr.push({...ef,...kf}); + arr.push({ ...ef, ...kf }); }); return arr.sort((f, g) => alpha(f.name, g.name)); } @@ -123,25 +119,28 @@ export default function Globals(): JSX.Element { // Hooks const [selection, updateSelection] = States.useSelection(); - const kerFcts = States.useSyncArray(Kernel.functions); - const evaFcts = States.useSyncArray(Eva.functions); - const kerStamp = Models.useModel(kerFcts); - const evaStamp = Models.useModel(evaFcts); - const fcts = React.useMemo( - () => computeFcts(kerFcts,evaFcts,kerStamp,evaStamp), - [kerFcts,evaFcts,kerStamp,evaStamp] - ); + const ker = States.useSyncArrayProxy(Kernel.functions); + const eva = States.useSyncArrayProxy(Eva.functions); + const fcts = React.useMemo(() => computeFcts(ker, eva), [ker, eva]); const { useFlipSettings } = Dome; const [stdlib, flipStdlib] = useFlipSettings('ivette.globals.stdlib', false); const [builtin, flipBuiltin] = useFlipSettings('ivette.globals.builtin', false); + const [def, flipDef] = + useFlipSettings('ivette.globals.def', true); const [undef, flipUndef] = useFlipSettings('ivette.globals.undef', true); - const [selected, flipSelected] = - useFlipSettings('ivette.globals.selected', false); - const [evaOnly, flipEvaOnly] = - useFlipSettings('ivette.globals.evaonly', false); + const [intern, flipIntern] = + useFlipSettings('ivette.globals.intern', true); + const [extern, flipExtern] = + useFlipSettings('ivette.globals.extern', true); + const [evaAnalyzed, flipEvaAnalyzed] = + useFlipSettings('ivette.globals.eva-analyzed', true); + const [evaUnreached, flipEvaUnreached] = + useFlipSettings('ivette.globals.eva-unreached', true); + const [selected, flipSelected] = + useFlipSettings('ivette.globals.selected', false); const multipleSelection = selection?.multiple; const multipleSelectionActive = multipleSelection?.allSelections.length > 0; const evaComputed = States.useSyncValue(computationState) === 'computed'; @@ -159,11 +158,16 @@ export default function Globals(): JSX.Element { const visible = (stdlib || !fct.stdlib) && (builtin || !fct.builtin) + && (def || !fct.defined) && (undef || fct.defined) - && (!evaOnly || !evaComputed || + && (intern || fct.extern) + && (extern || !fct.extern) + && (evaAnalyzed || !evaComputed || + !('eva_analyzed' in fct && fct.eva_analyzed === true)) + && (evaUnreached || !evaComputed || ('eva_analyzed' in fct && fct.eva_analyzed === true)) && (!selected || !multipleSelectionActive || isSelected(fct)); - return visible || (!!current && fct.name === current); + return !!visible; } function onSelection(name: string): void { @@ -182,24 +186,48 @@ export default function Globals(): JSX.Element { checked: stdlib, onClick: flipStdlib, }, + 'separator', + { + label: 'Show defined functions', + checked: def, + onClick: flipDef, + }, { label: 'Show undefined functions', checked: undef, onClick: flipUndef, }, 'separator', + { + label: 'Show non-extern functions', + checked: intern, + onClick: flipIntern, + }, + { + label: 'Show extern functions', + checked: extern, + onClick: flipExtern, + }, + 'separator', + { + label: 'Show functions analyzed by Eva', + enabled: evaComputed, + checked: evaAnalyzed, + onClick: flipEvaAnalyzed, + }, + { + label: 'Show functions unreached by Eva', + enabled: evaComputed, + checked: evaUnreached, + onClick: flipEvaUnreached, + }, + 'separator', { label: 'Selected only', enabled: multipleSelectionActive, checked: selected, onClick: flipSelected, }, - { - label: 'Analyzed by Eva only', - enabled: evaComputed, - checked: evaOnly, - onClick: flipEvaOnly, - }, ]; Dome.popupMenu(items); } @@ -229,15 +257,15 @@ export default function Globals(): JSX.Element { const noFunction = <div className='dome-xSideBarSection-content'> - <label className='dome-xSideBarSection-info'> - {'There is no function to display.'} + <label className='globals-info'> + There is no function to display. </label> </div>; const allFiltered = <div className='dome-xSideBarSection-content'> - <label className='dome-xSideBarSection-info'> - {'All functions are filtered. Try adjusting function filters.'} + <label className='globals-info'> + All functions are filtered. Try adjusting function filters. </label> <Button {...filterButtonProps} label='Functions filters' /> </div>; diff --git a/ivette/src/frama-c/kernel/Messages.tsx b/ivette/src/frama-c/kernel/Messages.tsx index b1b64a290679d8398443d117bc6ec6ad3ba4a857..d635b8fa23449d2a3661fc008177daf3b796ff1c 100644 --- a/ivette/src/frama-c/kernel/Messages.tsx +++ b/ivette/src/frama-c/kernel/Messages.tsx @@ -81,6 +81,7 @@ const kindFilter: KindFilter = { messages. They are all shown by default. */ const pluginFilter: PluginFilter = { 'aorai': true, + 'cg': true, 'dive': true, 'e-acsl': true, 'eva': true, @@ -426,7 +427,7 @@ export default function RenderMessages(): JSX.Element { return m; }); - const data = States.useSyncArray(Kernel.message).getArray(); + const data = States.useSyncArrayData(Kernel.message); React.useEffect(() => { model.removeAllData(); @@ -455,7 +456,7 @@ export default function RenderMessages(): JSX.Element { selectMsg(msg); setText(msg.message); if (msg.fct && msg.marker) { - const location = { fct:msg.fct, marker:msg.marker }; + const location = { fct: msg.fct, marker: msg.marker }; updateSelection({ location }); } }, [updateSelection], diff --git a/ivette/src/frama-c/kernel/Properties.tsx b/ivette/src/frama-c/kernel/Properties.tsx index 81d95fd79304c40ea31f29e735797659ca125438..1e32d93af70b1e7c10f85fd7a94e6b938d906064 100644 --- a/ivette/src/frama-c/kernel/Properties.tsx +++ b/ivette/src/frama-c/kernel/Properties.tsx @@ -38,7 +38,8 @@ import * as Models from 'dome/table/models'; import * as Arrays from 'dome/table/arrays'; import { Table, Column, ColumnProps, Renderer } from 'dome/table/views'; import { TitleBar } from 'ivette'; -import { Scroll, Folder } from 'dome/layout/boxes'; +import { Scroll } from 'dome/layout/boxes'; +import { Section } from 'dome/frame/sidebars'; import { RSplit } from 'dome/layout/splitters'; @@ -81,8 +82,8 @@ const DEFAULTS: { [key: string]: boolean } = { 'kind.axiomatic': true, 'kind.pragma': true, 'kind.others': true, - 'alarms.alarms': true, // show properties that are alarms - 'alarms.others': true, // show properties that are not alarms + 'source.alarms': true, // show properties that are alarms + 'source.others': true, // show properties that are not alarms 'alarms.overflow': true, 'alarms.division_by_zero': true, 'alarms.mem_access': true, @@ -121,6 +122,31 @@ function useFilter(path: string): [boolean, () => void] { ); } +function resetFilters(prefix: string, b?: boolean) : void { + for (const key in DEFAULTS) { + if (key.startsWith(prefix)) { + const target = b ?? DEFAULTS[key]; + const path = `ivette.properties.filter.${key}`; + Settings.setWindowSettings(path, target); + } + } + Reload.emit(); +} + +function filterSummary(prefix: string) : string { + let total = 0; + let enabled = 0; + for (const key in DEFAULTS) { + if (key.startsWith(prefix)) { + total ++; + if (filter(key)) enabled++; + } + } + if (enabled === 0) return 'none'; + if (enabled === total) return 'all'; + return `${enabled} / ${total}`; +} + function filterStatus( status: Properties.propStatus, ): boolean { @@ -174,7 +200,7 @@ function filterKind( function filterAlarm(alarm: string | undefined): boolean { if (alarm) { - if (!filter('alarms.alarms')) return false; + if (!filter('source.alarms')) return false; switch (alarm) { case 'overflow': return filter('alarms.overflow'); case 'division_by_zero': return filter('alarms.division_by_zero'); @@ -196,7 +222,7 @@ function filterAlarm(alarm: string | undefined): boolean { default: return false; } } - return filter('alarms.others'); + return filter('source.others'); } function filterEva(p: Property): boolean { @@ -367,20 +393,51 @@ const Reload = new Dome.Event('ivette.properties.reload'); interface SectionProps { label: string; + prefix?: string; unfold?: boolean; children: React.ReactNode; } -function Section(props: SectionProps): JSX.Element { +async function onContextMenu(prefix:string): Promise<void> { + const items: Dome.PopupMenuItem[] = [ + { + label: 'Reset to default', + onClick: () => resetFilters(prefix), + }, + { + label: 'Select all', + onClick: () => resetFilters(prefix, true), + }, + { + label: 'Deselect all', + onClick: () => resetFilters(prefix, false), + }, + ]; + Dome.popupMenu(items); +} + +function FilterSection(props: SectionProps): JSX.Element { const settings = `properties-section-${props.label}`; + const { label, prefix } = props; + const filterButtonProps = + prefix ? { + icon: 'TUNINGS', + title: `Configure filters`, + onClick: () => onContextMenu(prefix), + } : undefined; + const update = Dome.useForceUpdate(); + Settings.useWindowSettingsEvent(update); + const summary = prefix ? filterSummary(prefix) : undefined; return ( - <Folder - label={props.label} + <Section + label={label} settings={settings} defaultUnfold={props.unfold} + infos={summary} + rightButtonProps={filterButtonProps} > {props.children} - </Folder> + </Section> ); } @@ -414,7 +471,7 @@ function PropertyFilter(): JSX.Element { return ( <Scroll> <CheckField label="Current function" path="currentFunction" /> - <Section label="Status" unfold> + <FilterSection label="Status" prefix="status" unfold> <CheckField label="Valid" path="status.valid" /> <CheckField label="Valid under hyp." path="status.valid_hyp" /> <CheckField label="Unknown" path="status.unknown" /> @@ -424,8 +481,8 @@ function PropertyFilter(): JSX.Element { <CheckField label="Untried" path="status.untried" /> <CheckField label="Dead" path="status.dead" /> <CheckField label="Inconsistent" path="status.inconsistent" /> - </Section> - <Section label="Property kind"> + </FilterSection> + <FilterSection label="Property kind" prefix="kind"> <CheckField label="Assertions" path="kind.assert" /> <CheckField label="Invariants" path="kind.invariant" /> <CheckField label="Variants" path="kind.variant" /> @@ -441,12 +498,12 @@ function PropertyFilter(): JSX.Element { <CheckField label="Pragma" path="kind.pragma" /> <CheckField label="Assumes" path="kind.assumes" /> <CheckField label="Others" path="kind.others" /> - </Section> - <Section label="Alarms"> - <CheckField label="Alarms" path="alarms.alarms" /> - <CheckField label="Others" path="alarms.others" /> - </Section> - <Section label="Alarms kind"> + </FilterSection> + <FilterSection label="Source" prefix="source"> + <CheckField label="Alarms" path="source.alarms" /> + <CheckField label="Others" path="source.others" /> + </FilterSection> + <FilterSection label="Alarms kind" prefix="alarms"> <CheckField label="Overflows" path="alarms.overflow" /> <CheckField label="Divisions by zero" path="alarms.division_by_zero" /> <CheckField label="Shifts" path="alarms.shift" /> @@ -463,8 +520,8 @@ function PropertyFilter(): JSX.Element { <CheckField label="Differing blocks" path="alarms.differing_blocks" /> <CheckField label="Separations" path="alarms.separation" /> <CheckField label="Overlaps" path="alarms.overlap" /> - </Section> - <Section label="Eva"> + </FilterSection> + <FilterSection label="Eva"> <CheckField label="High-priority only" path="eva.priority_only" @@ -480,7 +537,7 @@ function PropertyFilter(): JSX.Element { path="eva.ctrl_tainted_only" title="Show only control-tainted properties according to the Eva taint domain" /> - </Section> + </FilterSection> </Scroll> ); } @@ -597,8 +654,8 @@ function FilterRatio({ model }: { model: PropertyModel }): JSX.Element { // --- Properties Table // ------------------------------------------------------------------------- -type PropsModel = Arrays.CompactModel<PropKey,Properties.statusData>; -type EvapsModel = Arrays.CompactModel<PropKey,Eva.propertiesData>; +type PropsModel = States.ArrayProxy<PropKey, Properties.statusData>; +type EvapsModel = States.ArrayProxy<PropKey, Eva.propertiesData>; function populateModel( model: PropertyModel, @@ -609,7 +666,7 @@ function populateModel( props.forEach((prop) => { const { key } = prop; const eva = evaps.getData(key); - model.setData(key,{ ...eva, ...prop }); + model.setData(key, { ...eva, ...prop }); }); model.reload(); } @@ -618,13 +675,11 @@ export default function RenderProperties(): JSX.Element { // Hooks const model = React.useMemo(() => new PropertyModel(), []); - const props = States.useSyncArray(Properties.status); - const evaps = States.useSyncArray(Eva.properties); - const pstamp = Models.useModel(props); - const estamp = Models.useModel(evaps); + const props = States.useSyncArrayProxy(Properties.status); + const evaps = States.useSyncArrayProxy(Eva.properties); React.useEffect(() => { - populateModel(model,props,evaps); - },[model,props,evaps,pstamp,estamp]); + populateModel(model, props, evaps); + }, [model, props, evaps]); const [selection, updateSelection] = States.useSelection(); diff --git a/ivette/src/frama-c/kernel/SourceCode.tsx b/ivette/src/frama-c/kernel/SourceCode.tsx index 0d143b7fa6d808b58014f22c90ca235e5e448fac..69f9cc5cdc0e1b7b07397049571d33e00b54473c 100644 --- a/ivette/src/frama-c/kernel/SourceCode.tsx +++ b/ivette/src/frama-c/kernel/SourceCode.tsx @@ -211,15 +211,14 @@ function useFctSource(file: string): string { // Build a callback that retrieves a location's source information. function useSourceGetter(): GetSource { - const attributes = States.useSyncArray(Ast.markerAttributes); - const functionsData = States.useSyncArray(Ast.functions).getArray(); + const getAttr = States.useSyncArrayGetter(Ast.markerAttributes); + const functionsData = States.useSyncArrayData(Ast.functions); return React.useCallback(({ fct, marker }) => { - const markerSloc = (marker !== undefined && marker !== '') ? - attributes.getData(marker)?.sloc : undefined; + const markerSloc = getAttr(marker)?.sloc; const fctSloc = (fct !== undefined && fct !== '') ? functionsData.find((e) => e.name === fct)?.sloc : undefined; return markerSloc ?? fctSloc; - }, [attributes, functionsData]); + }, [getAttr, functionsData]); } // ----------------------------------------------------------------------------- @@ -277,7 +276,7 @@ export default function SourceCode(): JSX.Element { async function displayShortcuts(): Promise<void> { await Dialogs.showMessageBox({ - buttons: [{label:"Ok"}], + buttons: [{ label: "Ok" }], details: shortcuts, message: 'Useful shortcuts' }); diff --git a/ivette/src/frama-c/kernel/api/ast/index.ts b/ivette/src/frama-c/kernel/api/ast/index.ts index 77a01063a03366eba90da24751579561a27a0df9..c4748c158dba36d3d436d3d9b26f33489c284f56 100644 --- a/ivette/src/frama-c/kernel/api/ast/index.ts +++ b/ivette/src/frama-c/kernel/api/ast/index.ts @@ -147,12 +147,14 @@ export interface markerAttributesData { isLval: boolean; /** Whether it is a function symbol */ isFunction: boolean; + /** Whether it is a function pointer */ + isFunctionPointer: boolean; /** Whether it is a function declaration */ isFunDecl: boolean; /** Function scope of the marker, if applicable */ scope?: string; /** Source location */ - sloc: source; + sloc?: source; } /** Decoder for `markerAttributesData` */ @@ -165,9 +167,10 @@ export const jMarkerAttributesData: Json.Decoder<markerAttributesData> = descr: Json.jString, isLval: Json.jBoolean, isFunction: Json.jBoolean, + isFunctionPointer: Json.jBoolean, isFunDecl: Json.jBoolean, scope: Json.jOption(Json.jString), - sloc: jSource, + sloc: Json.jOption(jSource), }); /** Natural order for `markerAttributesData` */ @@ -175,7 +178,8 @@ export const byMarkerAttributesData: Compare.Order<markerAttributesData> = Compare.byFields <{ marker: marker, labelKind: string, titleKind: string, name: string, descr: string, isLval: boolean, isFunction: boolean, - isFunDecl: boolean, scope?: string, sloc: source }>({ + isFunctionPointer: boolean, isFunDecl: boolean, scope?: string, + sloc?: source }>({ marker: byMarker, labelKind: Compare.alpha, titleKind: Compare.alpha, @@ -183,9 +187,10 @@ export const byMarkerAttributesData: Compare.Order<markerAttributesData> = descr: Compare.string, isLval: Compare.boolean, isFunction: Compare.boolean, + isFunctionPointer: Compare.boolean, isFunDecl: Compare.boolean, scope: Compare.defined(Compare.string), - sloc: bySource, + sloc: Compare.defined(bySource), }); /** Signal for array [`markerAttributes`](#markerattributes) */ @@ -240,8 +245,8 @@ export const markerAttributes: State.Array<marker,markerAttributesData> = marker /** Default value for `markerAttributesData` */ export const markerAttributesDataDefault: markerAttributesData = { marker: markerDefault, labelKind: '', titleKind: '', name: '', descr: '', - isLval: false, isFunction: false, isFunDecl: false, scope: undefined, - sloc: sourceDefault }; + isLval: false, isFunction: false, isFunctionPointer: false, + isFunDecl: false, scope: undefined, sloc: undefined }; const getMainFunction_internal: Server.GetRequest<null,fct | undefined> = { kind: Server.RqKind.GET, @@ -268,7 +273,7 @@ const printFunction_internal: Server.GetRequest<fct,text> = { name: 'kernel.ast.printFunction', input: jFct, output: jText, - signals: [], + signals: [ { name: 'kernel.ast.changed' } ], }; /** Print the AST of a function */ export const printFunction: Server.GetRequest<fct,text>= printFunction_internal; @@ -289,6 +294,8 @@ export interface functionsData { stdlib?: boolean; /** Is the function a Frama-C builtin? */ builtin?: boolean; + /** Is the function extern? */ + extern?: boolean; /** Source location */ sloc: source; } @@ -303,6 +310,7 @@ export const jFunctionsData: Json.Decoder<functionsData> = defined: Json.jOption(Json.jBoolean), stdlib: Json.jOption(Json.jBoolean), builtin: Json.jOption(Json.jBoolean), + extern: Json.jOption(Json.jBoolean), sloc: jSource, }); @@ -311,7 +319,7 @@ export const byFunctionsData: Compare.Order<functionsData> = Compare.byFields <{ key: Json.key<'#functions'>, name: string, signature: string, main?: boolean, defined?: boolean, stdlib?: boolean, - builtin?: boolean, sloc: source }>({ + builtin?: boolean, extern?: boolean, sloc: source }>({ key: Compare.string, name: Compare.alpha, signature: Compare.string, @@ -319,6 +327,7 @@ export const byFunctionsData: Compare.Order<functionsData> = defined: Compare.defined(Compare.boolean), stdlib: Compare.defined(Compare.boolean), builtin: Compare.defined(Compare.boolean), + extern: Compare.defined(Compare.boolean), sloc: bySource, }); @@ -375,7 +384,7 @@ export const functions: State.Array<Json.key<'#functions'>,functionsData> = func export const functionsDataDefault: functionsData = { key: Json.jKey<'#functions'>('#functions')(''), name: '', signature: '', main: undefined, defined: undefined, stdlib: undefined, - builtin: undefined, sloc: sourceDefault }; + builtin: undefined, extern: undefined, sloc: sourceDefault }; /** Updated AST information */ export const getInformationUpdate: Server.Signal = { diff --git a/ivette/src/frama-c/kernel/style.css b/ivette/src/frama-c/kernel/style.css index 6a7da3a4b4270b277a699419ba5c908199d278a2..d0bb884d976534c1b7e815186ad50d8c66f3d603 100644 --- a/ivette/src/frama-c/kernel/style.css +++ b/ivette/src/frama-c/kernel/style.css @@ -56,6 +56,14 @@ /* --- Globals --- */ /* -------------------------------------------------------------------------- */ +.globals-info { + color: var(--info-text-discrete); + font-style: italic; + padding-left: 20px; + padding-right: 10px; + display: block; +} + .globals-main label { text-decoration: underline; } diff --git a/ivette/src/frama-c/plugins/callgraph/api/index.ts b/ivette/src/frama-c/plugins/callgraph/api/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..e231a66fbbae3bb315cd9a85a06f47096f0311db --- /dev/null +++ b/ivette/src/frama-c/plugins/callgraph/api/index.ts @@ -0,0 +1,217 @@ +/* ************************************************************************ */ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/* ************************************************************************ */ + +/* --- Generated Frama-C Server API --- */ + +/** + Callgraph + @packageDocumentation + @module frama-c/plugins/callgraph/api +*/ + +//@ts-ignore +import * as Json from 'dome/data/json'; +//@ts-ignore +import * as Compare from 'dome/data/compare'; +//@ts-ignore +import * as Server from 'frama-c/server'; +//@ts-ignore +import * as State from 'frama-c/states'; + +//@ts-ignore +import { byFct } from 'frama-c/kernel/api/ast'; +//@ts-ignore +import { fct } from 'frama-c/kernel/api/ast'; +//@ts-ignore +import { fctDefault } from 'frama-c/kernel/api/ast'; +//@ts-ignore +import { jFct } from 'frama-c/kernel/api/ast'; +//@ts-ignore +import { byTag } from 'frama-c/kernel/api/data'; +//@ts-ignore +import { jTag } from 'frama-c/kernel/api/data'; +//@ts-ignore +import { tag } from 'frama-c/kernel/api/data'; +//@ts-ignore +import { tagDefault } from 'frama-c/kernel/api/data'; + +export interface vertex { + /** The function represented by the node */ + kf: fct; + /** whether this node is the root of a service */ + is_root: boolean; + /** the root of this node's service */ + root: fct; +} + +/** Decoder for `vertex` */ +export const jVertex: Json.Decoder<vertex> = + Json.jObject({ kf: jFct, is_root: Json.jBoolean, root: jFct,}); + +/** Natural order for `vertex` */ +export const byVertex: Compare.Order<vertex> = + Compare.byFields + <{ kf: fct, is_root: boolean, root: fct }>({ + kf: byFct, + is_root: Compare.boolean, + root: byFct, + }); + +/** Default value for `vertex` */ +export const vertexDefault: vertex = + { kf: fctDefault, is_root: false, root: fctDefault }; + +/** Whether the call goes through services or not */ +export enum edgeKind { + /** a call between two services */ + inter_services = 'inter_services', + /** a call inside a service */ + inter_functions = 'inter_functions', + /** both cases above */ + both = 'both', +} + +/** Decoder for `edgeKind` */ +export const jEdgeKind: Json.Decoder<edgeKind> = Json.jEnum(edgeKind); + +/** Natural order for `edgeKind` */ +export const byEdgeKind: Compare.Order<edgeKind> = Compare.byEnum(edgeKind); + +/** Default value for `edgeKind` */ +export const edgeKindDefault: edgeKind = edgeKind.inter_services; + +const edgeKindTags_internal: Server.GetRequest<null,tag[]> = { + kind: Server.RqKind.GET, + name: 'plugins.callgraph.edgeKindTags', + input: Json.jNull, + output: Json.jArray(jTag), + signals: [], +}; +/** Registered tags for the above type. */ +export const edgeKindTags: Server.GetRequest<null,tag[]>= edgeKindTags_internal; + +export interface edge { + /** src */ + src: fct; + /** dst */ + dst: fct; + /** kind */ + kind: edgeKind; +} + +/** Decoder for `edge` */ +export const jEdge: Json.Decoder<edge> = + Json.jObject({ src: jFct, dst: jFct, kind: jEdgeKind,}); + +/** Natural order for `edge` */ +export const byEdge: Compare.Order<edge> = + Compare.byFields + <{ src: fct, dst: fct, kind: edgeKind }>({ + src: byFct, + dst: byFct, + kind: byEdgeKind, + }); + +/** Default value for `edge` */ +export const edgeDefault: edge = + { src: fctDefault, dst: fctDefault, kind: edgeKindDefault }; + +/** The callgraph of the current project */ +export interface graph { + /** vertices */ + vertices: vertex[]; + /** edges */ + edges: edge[]; +} + +/** Decoder for `graph` */ +export const jGraph: Json.Decoder<graph> = + Json.jObject({ vertices: Json.jArray(jVertex), edges: Json.jArray(jEdge),}); + +/** Natural order for `graph` */ +export const byGraph: Compare.Order<graph> = + Compare.byFields + <{ vertices: vertex[], edges: edge[] }>({ + vertices: Compare.array(byVertex), + edges: Compare.array(byEdge), + }); + +/** Default value for `graph` */ +export const graphDefault: graph = { vertices: [], edges: [] }; + +/** Signal for state [`callgraph`](#callgraph) */ +export const signalCallgraph: Server.Signal = { + name: 'plugins.callgraph.signalCallgraph', +}; + +const getCallgraph_internal: Server.GetRequest<null,graph | undefined> = { + kind: Server.RqKind.GET, + name: 'plugins.callgraph.getCallgraph', + input: Json.jNull, + output: Json.jOption(jGraph), + signals: [], +}; +/** Getter for state [`callgraph`](#callgraph) */ +export const getCallgraph: Server.GetRequest<null,graph | undefined>= getCallgraph_internal; + +const callgraph_internal: State.Value<graph | undefined> = { + name: 'plugins.callgraph.callgraph', + signal: signalCallgraph, + getter: getCallgraph, +}; +/** The current callgraph or an empty graph if it has not been computed yet */ +export const callgraph: State.Value<graph | undefined> = callgraph_internal; + +/** Signal for state [`isComputed`](#iscomputed) */ +export const signalIsComputed: Server.Signal = { + name: 'plugins.callgraph.signalIsComputed', +}; + +const getIsComputed_internal: Server.GetRequest<null,boolean> = { + kind: Server.RqKind.GET, + name: 'plugins.callgraph.getIsComputed', + input: Json.jNull, + output: Json.jBoolean, + signals: [], +}; +/** Getter for state [`isComputed`](#iscomputed) */ +export const getIsComputed: Server.GetRequest<null,boolean>= getIsComputed_internal; + +const isComputed_internal: State.Value<boolean> = { + name: 'plugins.callgraph.isComputed', + signal: signalIsComputed, + getter: getIsComputed, +}; +/** This boolean is true if the graph has been computed */ +export const isComputed: State.Value<boolean> = isComputed_internal; + +const compute_internal: Server.ExecRequest<null,null> = { + kind: Server.RqKind.EXEC, + name: 'plugins.callgraph.compute', + input: Json.jNull, + output: Json.jNull, + signals: [], +}; +/** Compute the callgraph for the current project */ +export const compute: Server.ExecRequest<null,null>= compute_internal; + +/* ------------------------------------- */ diff --git a/ivette/src/frama-c/plugins/callgraph/callgraph.css b/ivette/src/frama-c/plugins/callgraph/callgraph.css new file mode 100644 index 0000000000000000000000000000000000000000..4360e1461c2db03e11e4e3d205ce09e17ea74809 --- /dev/null +++ b/ivette/src/frama-c/plugins/callgraph/callgraph.css @@ -0,0 +1,6 @@ +.callgraph-computing { + max-width: 90%; + max-height: 200px; + fill: var(--info-text-discrete); + margin: auto; +} diff --git a/ivette/src/frama-c/plugins/callgraph/graph-style.json b/ivette/src/frama-c/plugins/callgraph/graph-style.json new file mode 100644 index 0000000000000000000000000000000000000000..e1aff869e939ed8a04bbc64618ede99ce4e19db3 --- /dev/null +++ b/ivette/src/frama-c/plugins/callgraph/graph-style.json @@ -0,0 +1,42 @@ +[ + { + "selector": "node", + "style": { + "shape": "round-rectangle", + "background-color": "#666", + "label": "data(id)", + "color": "white", + "text-outline-width": 2, + "text-outline-color": "#666", + "text-valign" : "center", + "padding" : "6px", + "border-width": 1, + "text-wrap" : "wrap" + } + }, + { + "selector": "node[?is_root]", + "style": { + "border-width": "2px" + } + }, + { + "selector": "edge", + "style": { + "width": 2, + "line-color": "#888", + "curve-style": "bezier", + "target-arrow-shape": "vee", + "target-arrow-color": "#888", + "arrow-scale": 2.0 + } + }, + { + "selector": ".callstack-selected", + "style": { + "overlay-color": "#8bf", + "overlay-padding": "8px", + "overlay-opacity": 0.4 + } + } +] diff --git a/ivette/src/frama-c/plugins/callgraph/index.tsx b/ivette/src/frama-c/plugins/callgraph/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e0b1861ef05335fefc5bed6d61b246789f732162 --- /dev/null +++ b/ivette/src/frama-c/plugins/callgraph/index.tsx @@ -0,0 +1,210 @@ +/* ************************************************************************ */ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/* ************************************************************************ */ + +import React, { useEffect, useState } from 'react'; +import _ from 'lodash'; +import * as Ivette from 'ivette'; +import * as Server from 'frama-c/server'; + +import * as AstAPI from 'frama-c/kernel/api/ast'; +import * as CgAPI from './api'; +import * as ValuesAPI from 'frama-c/plugins/eva/api/values'; + +import Cy from 'cytoscape'; +import CytoscapeComponent from 'react-cytoscapejs'; +import 'frama-c/plugins/dive/cytoscape_libs'; +import 'cytoscape-panzoom/cytoscape.js-panzoom.css'; +import style from './graph-style.json'; + +import { useGlobalState } from 'dome/data/states'; +import { useRequest, useSelection, useSyncValue } from 'frama-c/states'; + +import gearsIcon from 'frama-c/plugins/eva/images/gears.svg'; +import { CallstackState } from 'frama-c/plugins/eva/valuetable'; + +import './callgraph.css'; + + +// -------------------------------------------------------------------------- +// --- Nodes label measurement +// -------------------------------------------------------------------------- + +/* eslint-disable @typescript-eslint/no-explicit-any */ +function getWidth(node: any): string { + const padding = 10; + const min = 50; + const canvas = document.querySelector('canvas[data-id="layer2-node"]'); + if (canvas instanceof HTMLCanvasElement) { + const context = canvas.getContext('2d'); + if (context) { + const fStyle = node.pstyle('font-style').strValue; + const weight = node.pstyle('font-weight').strValue; + const size = node.pstyle('font-size').pfValue; + const family = node.pstyle('font-family').strValue; + context.font = `${fStyle} ${weight} ${size}px ${family}`; + const width = context.measureText(node.data('id')).width; + return `${Math.max(min, width + padding)}px`; + } + } + return `${min}px`; +} +/* eslint-enable @typescript-eslint/no-explicit-any */ + +(style as unknown[]).push({ + selector: 'node', + style: { width: getWidth } + }); + + +// -------------------------------------------------------------------------- +// --- Graph +// -------------------------------------------------------------------------- + +function edgeId(source: AstAPI.fct, target: AstAPI.fct): string { + return `${source}-${target}`; +} + +function convertGraph(graph: CgAPI.graph): object[] { + const elements = []; + for (const v of graph.vertices) { + elements.push({ data: { ...v, id: v.kf } }); + } + for (const e of graph.edges) { + const id = edgeId(e.src, e.dst); + elements.push({ data: { ...e, id, source: e.src, target: e.dst } }); + } + return elements; +} + +type callstack = { + callee: AstAPI.fct, + caller?: AstAPI.fct, + stmt?: AstAPI.marker, + rank?: number +}[] + +function selectFct(cy: Cy.Core, fct: string | undefined): void { + const className = 'marker-selected'; + cy.$(`.${className}`).removeClass(className); + if (fct) { + cy.$(`node[id='${fct}']`).addClass(className); + } +} + +function selectCallstack(cy: Cy.Core, callstack: callstack | undefined): void { + const className = 'callstack-selected'; + cy.$(`.${className}`).removeClass(className); + callstack?.forEach((call) => { + cy.$(`node[id='${call.callee}']`).addClass(className); + if (call.caller) { + const id = edgeId(call.caller, call.callee); + cy.$(`edge[id='${id}']`).addClass(className); + } + }); +} + +function Callgraph() : JSX.Element { + const isComputed = useSyncValue(CgAPI.isComputed); + const graph = useSyncValue(CgAPI.callgraph); + const [cy, setCy] = useState<Cy.Core>(); + const [cs] = useGlobalState(CallstackState); + const [selection, setSelection] = useSelection(); + const callstack = useRequest(ValuesAPI.getCallstackInfo, cs); + + const layout = { name: 'cola', nodeSpacing: 32 }; + const computedStyle = getComputedStyle(document.documentElement); + const styleVariables = + { ['code-select']: computedStyle.getPropertyValue("--code-select") }; + + const completeStyle = [ + ...style, + { + "selector": ".marker-selected", + "style": { "background-color": styleVariables['code-select'] } + } + ]; + + // Marker selection + useEffect(() => { + cy && selectFct(cy, selection.current?.fct); + }, [cy, selection]); + + // Callstack selection + useEffect(() => { + cy && selectCallstack(cy, callstack); + }, [cy, callstack]); + + // Click on graph + useEffect(() => { + if (cy) { + cy.off('click'); + cy.on('click', 'node', (event) => { + const fct = event.target.id() as string; + setSelection({ location: { fct } }); + }); + } + }, [cy, setSelection]); + + + if (isComputed === false) { + Server.send(CgAPI.compute, null); + return (<img src={gearsIcon} className="callgraph-computing" />); + } + else if (graph !== undefined) { + return ( + <CytoscapeComponent + elements={convertGraph(graph)} + stylesheet={completeStyle} + cy={setCy} + layout={layout} + style={{ width: '100%', height: '100%' }} + />); + } + else { + return (<></>); + } +} + + +// -------------------------------------------------------------------------- +// --- Ivette Component +// -------------------------------------------------------------------------- + +function CallgraphComponent(): JSX.Element { + // Component + return ( + <> + <Callgraph /> + </> + ); +} + + +Ivette.registerComponent({ + id: 'frama-c.plugins.callgraph', + label: 'Call Graph', + group: 'frama-c.plugins', + rank: 3, + title: + 'Display a graph showing calls between functions.', + children: <CallgraphComponent />, +}); diff --git a/ivette/src/frama-c/plugins/callgraph/pkg.json b/ivette/src/frama-c/plugins/callgraph/pkg.json new file mode 100644 index 0000000000000000000000000000000000000000..01be594c9eea276d40d1967201e4675ea3cdc1f8 --- /dev/null +++ b/ivette/src/frama-c/plugins/callgraph/pkg.json @@ -0,0 +1,3 @@ +{ + "name": "Frama-C/Callgraph" +} diff --git a/ivette/src/frama-c/plugins/dive/api/index.ts b/ivette/src/frama-c/plugins/dive/api/index.ts index cd47a1579e051faaecd79ad5c1b95b0f7f8bed4f..62dc2171f78d04ff87fbd13ac76c68a9aa6631a3 100644 --- a/ivette/src/frama-c/plugins/dive/api/index.ts +++ b/ivette/src/frama-c/plugins/dive/api/index.ts @@ -53,6 +53,14 @@ import { locationDefault } from 'frama-c/kernel/api/ast'; import { marker } from 'frama-c/kernel/api/ast'; //@ts-ignore import { markerDefault } from 'frama-c/kernel/api/ast'; +//@ts-ignore +import { byTag } from 'frama-c/kernel/api/data'; +//@ts-ignore +import { jTag } from 'frama-c/kernel/api/data'; +//@ts-ignore +import { tag } from 'frama-c/kernel/api/data'; +//@ts-ignore +import { tagDefault } from 'frama-c/kernel/api/data'; /** Parametrization of the exploration range. */ export interface range { @@ -117,20 +125,21 @@ export const byNodeId: Compare.Order<nodeId> = Compare.number; /** Default value for `nodeId` */ export const nodeIdDefault: nodeId = 0; -/** A callsite */ -export type callsite = { fun: string, instr: number | string }; +/** callsite */ +export type callsite = { fun: string, instr: number | "global" }; /** Decoder for `callsite` */ export const jCallsite: Json.Decoder<callsite> = Json.jObject({ fun: Json.jString, - instr: Json.jUnion<number | string>( Json.jNumber, Json.jString,), + instr: Json.jUnion<number | "global">( Json.jNumber, Json.jTag("global"), + ), }); /** Natural order for `callsite` */ export const byCallsite: Compare.Order<callsite> = Compare.byFields - <{ fun: string, instr: number | string }>({ + <{ fun: string, instr: number | "global" }>({ fun: Compare.string, instr: Compare.structural, }); @@ -152,7 +161,12 @@ export const byCallstack: Compare.Order<callstack> = export const callstackDefault: callstack = []; /** The description of a node locality */ -export type nodeLocality = { file: string, callstack?: callstack }; +export interface nodeLocality { + /** file */ + file: string; + /** callstack */ + callstack?: callstack; +} /** Decoder for `nodeLocality` */ export const jNodeLocality: Json.Decoder<nodeLocality> = @@ -170,65 +184,238 @@ export const byNodeLocality: Compare.Order<nodeLocality> = export const nodeLocalityDefault: nodeLocality = { file: '', callstack: undefined }; -/** A graph node */ -export type node = - { id: nodeId, label: string, kind: string, locality: nodeLocality, - is_root: boolean, backward_explored: string, forward_explored: string, - writes: location[], values?: string, range: number | string, - type?: string, taint?: "direct" | "indirect" | "untainted" }; +/** The nature of a node */ +export enum nodeKind { + /** a single memory cell */ + scalar = 'scalar', + /** a memory bloc containing cells */ + composite = 'composite', + /** a set of memory locations designated by an lvalue */ + scattered = 'scattered', + /** an unresolved memory location */ + unknown = 'unknown', + /** an alarm emitted by Frama-C */ + alarm = 'alarm', + /** a memory location designated by a range of adresses */ + absolute = 'absolute', + /** a string literal */ + string = 'string', + /** a placeholder node when an error prevented the generation process */ + error = 'error', + /** a numeric constant literal */ + const = 'const', +} + +/** Decoder for `nodeKind` */ +export const jNodeKind: Json.Decoder<nodeKind> = Json.jEnum(nodeKind); + +/** Natural order for `nodeKind` */ +export const byNodeKind: Compare.Order<nodeKind> = Compare.byEnum(nodeKind); + +/** Default value for `nodeKind` */ +export const nodeKindDefault: nodeKind = nodeKind.scalar; + +const nodeKindTags_internal: Server.GetRequest<null,tag[]> = { + kind: Server.RqKind.GET, + name: 'plugins.dive.nodeKindTags', + input: Json.jNull, + output: Json.jArray(jTag), + signals: [], +}; +/** Registered tags for the above type. */ +export const nodeKindTags: Server.GetRequest<null,tag[]>= nodeKindTags_internal; + +/** Taint of a memory location */ +export enum taint { + /** not tainted by anything */ + untainted = 'untainted', + /** tainted by control */ + indirect = 'indirect', + /** tainted by data */ + direct = 'direct', +} + +/** Decoder for `taint` */ +export const jTaint: Json.Decoder<taint> = Json.jEnum(taint); + +/** Natural order for `taint` */ +export const byTaint: Compare.Order<taint> = Compare.byEnum(taint); + +/** Default value for `taint` */ +export const taintDefault: taint = taint.untainted; + +const taintTags_internal: Server.GetRequest<null,tag[]> = { + kind: Server.RqKind.GET, + name: 'plugins.dive.taintTags', + input: Json.jNull, + output: Json.jArray(jTag), + signals: [], +}; +/** Registered tags for the above type. */ +export const taintTags: Server.GetRequest<null,tag[]>= taintTags_internal; + +/** The computation state of a node read or write dependencies */ +export enum exploration { + /** all dependencies have been computed */ + yes = 'yes', + /** some dependencies have been explored */ + partial = 'partial', + /** dependencies have not been computed */ + no = 'no', +} + +/** Decoder for `exploration` */ +export const jExploration: Json.Decoder<exploration> = + Json.jEnum(exploration); + +/** Natural order for `exploration` */ +export const byExploration: Compare.Order<exploration> = + Compare.byEnum(exploration); + +/** Default value for `exploration` */ +export const explorationDefault: exploration = exploration.yes; + +const explorationTags_internal: Server.GetRequest<null,tag[]> = { + kind: Server.RqKind.GET, + name: 'plugins.dive.explorationTags', + input: Json.jNull, + output: Json.jArray(jTag), + signals: [], +}; +/** Registered tags for the above type. */ +export const explorationTags: Server.GetRequest<null,tag[]>= explorationTags_internal; + +/** A qualitative description of the range of values that this node can take. */ +export enum nodeSpecialRange { + /** no value ever computed for this node */ + empty = 'empty', + /** this node can only have one value */ + singleton = 'singleton', + /** this node can take almost all values of its type */ + wide = 'wide', +} + +/** Decoder for `nodeSpecialRange` */ +export const jNodeSpecialRange: Json.Decoder<nodeSpecialRange> = + Json.jEnum(nodeSpecialRange); + +/** Natural order for `nodeSpecialRange` */ +export const byNodeSpecialRange: Compare.Order<nodeSpecialRange> = + Compare.byEnum(nodeSpecialRange); + +/** Default value for `nodeSpecialRange` */ +export const nodeSpecialRangeDefault: nodeSpecialRange = + nodeSpecialRange.empty; + +const nodeSpecialRangeTags_internal: Server.GetRequest<null,tag[]> = { + kind: Server.RqKind.GET, + name: 'plugins.dive.nodeSpecialRangeTags', + input: Json.jNull, + output: Json.jArray(jTag), + signals: [], +}; +/** Registered tags for the above type. */ +export const nodeSpecialRangeTags: Server.GetRequest<null,tag[]>= nodeSpecialRangeTags_internal; + +/** A qualitative or quantitative description of the range of values that this node can take. */ +export type nodeRange = number | nodeSpecialRange; + +/** Decoder for `nodeRange` */ +export const jNodeRange: Json.Decoder<nodeRange> = + Json.jUnion<number | nodeSpecialRange>( Json.jNumber, jNodeSpecialRange,); + +/** Natural order for `nodeRange` */ +export const byNodeRange: Compare.Order<nodeRange> = Compare.structural; + +/** Default value for `nodeRange` */ +export const nodeRangeDefault: nodeRange = 0; + +export interface node { + /** id */ + id: nodeId; + /** label */ + label: string; + /** nkind */ + nkind: nodeKind; + /** locality */ + locality: nodeLocality; + /** is_root */ + is_root: boolean; + /** backward_explored */ + backward_explored: exploration; + /** forward_explored */ + forward_explored: exploration; + /** writes */ + writes: location[]; + /** values */ + values?: string; + /** range */ + range: nodeRange; + /** type */ + type?: string; + /** taint */ + taint?: taint; +} /** Decoder for `node` */ export const jNode: Json.Decoder<node> = Json.jObject({ id: jNodeId, label: Json.jString, - kind: Json.jString, + nkind: jNodeKind, locality: jNodeLocality, is_root: Json.jBoolean, - backward_explored: Json.jString, - forward_explored: Json.jString, + backward_explored: jExploration, + forward_explored: jExploration, writes: Json.jArray(jLocation), values: Json.jOption(Json.jString), - range: Json.jUnion<number | string>( Json.jNumber, Json.jString,), + range: jNodeRange, type: Json.jOption(Json.jString), - taint: Json.jOption( - Json.jUnion<"direct" | "indirect" | "untainted">( - Json.jTag("direct"), - Json.jTag("indirect"), - Json.jTag("untainted"), - )), + taint: Json.jOption(jTaint), }); /** Natural order for `node` */ export const byNode: Compare.Order<node> = Compare.byFields - <{ id: nodeId, label: string, kind: string, locality: nodeLocality, - is_root: boolean, backward_explored: string, forward_explored: string, - writes: location[], values?: string, range: number | string, - type?: string, taint?: "direct" | "indirect" | "untainted" }>({ + <{ id: nodeId, label: string, nkind: nodeKind, locality: nodeLocality, + is_root: boolean, backward_explored: exploration, + forward_explored: exploration, writes: location[], values?: string, + range: nodeRange, type?: string, taint?: taint }>({ id: byNodeId, label: Compare.string, - kind: Compare.string, + nkind: byNodeKind, locality: byNodeLocality, is_root: Compare.boolean, - backward_explored: Compare.string, - forward_explored: Compare.string, + backward_explored: byExploration, + forward_explored: byExploration, writes: Compare.array(byLocation), values: Compare.defined(Compare.string), - range: Compare.structural, + range: byNodeRange, type: Compare.defined(Compare.string), - taint: Compare.defined(Compare.structural), + taint: Compare.defined(byTaint), }); /** Default value for `node` */ export const nodeDefault: node = - { id: nodeIdDefault, label: '', kind: '', locality: nodeLocalityDefault, - is_root: false, backward_explored: '', forward_explored: '', writes: [], - values: undefined, range: 0, type: undefined, taint: undefined }; + { id: nodeIdDefault, label: '', nkind: nodeKindDefault, + locality: nodeLocalityDefault, is_root: false, + backward_explored: explorationDefault, + forward_explored: explorationDefault, writes: [], values: undefined, + range: nodeRangeDefault, type: undefined, taint: undefined }; /** The dependency between two nodes */ -export type dependency = - { id: number, src: nodeId, dst: nodeId, kind: string, origins: location[] }; +export interface dependency { + /** id */ + id: number; + /** src */ + src: nodeId; + /** dst */ + dst: nodeId; + /** dkind */ + dkind: string; + /** origins */ + origins: location[]; +} /** Decoder for `dependency` */ export const jDependency: Json.Decoder<dependency> = @@ -236,77 +423,111 @@ export const jDependency: Json.Decoder<dependency> = id: Json.jNumber, src: jNodeId, dst: jNodeId, - kind: Json.jString, + dkind: Json.jString, origins: Json.jArray(jLocation), }); /** Natural order for `dependency` */ export const byDependency: Compare.Order<dependency> = Compare.byFields - <{ id: number, src: nodeId, dst: nodeId, kind: string, + <{ id: number, src: nodeId, dst: nodeId, dkind: string, origins: location[] }>({ id: Compare.number, src: byNodeId, dst: byNodeId, - kind: Compare.string, + dkind: Compare.string, origins: Compare.array(byLocation), }); /** Default value for `dependency` */ export const dependencyDefault: dependency = - { id: 0, src: nodeIdDefault, dst: nodeIdDefault, kind: '', origins: [] }; + { id: 0, src: nodeIdDefault, dst: nodeIdDefault, dkind: '', origins: [] }; + +/** A graph element, either a node or a dependency */ +export type element = node | dependency; + +/** Decoder for `element` */ +export const jElement: Json.Decoder<element> = + Json.jUnion<node | dependency>( jNode, jDependency,); -/** The whole graph being built */ -export type graphData = { nodes: node[], deps: dependency[] }; +/** Natural order for `element` */ +export const byElement: Compare.Order<element> = Compare.structural; + +/** Default value for `element` */ +export const elementDefault: element = nodeDefault; + +/** Data for array rows [`graph`](#graph) */ +export interface graphData { + /** Entry identifier. */ + key: Json.key<'#graph'>; + /** a graph element */ + element: element; +} /** Decoder for `graphData` */ export const jGraphData: Json.Decoder<graphData> = - Json.jObject({ nodes: Json.jArray(jNode), deps: Json.jArray(jDependency),}); + Json.jObject({ key: Json.jKey<'#graph'>('#graph'), element: jElement,}); /** Natural order for `graphData` */ export const byGraphData: Compare.Order<graphData> = Compare.byFields - <{ nodes: node[], deps: dependency[] }>({ - nodes: Compare.array(byNode), - deps: Compare.array(byDependency), + <{ key: Json.key<'#graph'>, element: element }>({ + key: Compare.string, + element: byElement, }); -/** Default value for `graphData` */ -export const graphDataDefault: graphData = { nodes: [], deps: [] }; - -/** Graph differences from the last action. */ -export type diffData = - { root?: nodeId, add: { nodes: node[], deps: dependency[] }, sub: nodeId[] - }; - -/** Decoder for `diffData` */ -export const jDiffData: Json.Decoder<diffData> = - Json.jObject({ - root: Json.jOption(jNodeId), - add: Json.jObject({ - nodes: Json.jArray(jNode), - deps: Json.jArray(jDependency), - }), - sub: Json.jArray(jNodeId), - }); +/** Signal for array [`graph`](#graph) */ +export const signalGraph: Server.Signal = { + name: 'plugins.dive.signalGraph', +}; -/** Natural order for `diffData` */ -export const byDiffData: Compare.Order<diffData> = - Compare.byFields - <{ root?: nodeId, add: { nodes: node[], deps: dependency[] }, - sub: nodeId[] }>({ - root: Compare.defined(byNodeId), - add: Compare.byFields - <{ nodes: node[], deps: dependency[] }>({ - nodes: Compare.array(byNode), - deps: Compare.array(byDependency), - }), - sub: Compare.array(byNodeId), - }); +const reloadGraph_internal: Server.GetRequest<null,null> = { + kind: Server.RqKind.GET, + name: 'plugins.dive.reloadGraph', + input: Json.jNull, + output: Json.jNull, + signals: [], +}; +/** Force full reload for array [`graph`](#graph) */ +export const reloadGraph: Server.GetRequest<null,null>= reloadGraph_internal; + +const fetchGraph_internal: Server.GetRequest< + number, + { reload: boolean, removed: Json.key<'#graph'>[], updated: graphData[], + pending: number } + > = { + kind: Server.RqKind.GET, + name: 'plugins.dive.fetchGraph', + input: Json.jNumber, + output: Json.jObject({ + reload: Json.jBoolean, + removed: Json.jArray(Json.jKey<'#graph'>('#graph')), + updated: Json.jArray(jGraphData), + pending: Json.jNumber, + }), + signals: [], +}; +/** Data fetcher for array [`graph`](#graph) */ +export const fetchGraph: Server.GetRequest< + number, + { reload: boolean, removed: Json.key<'#graph'>[], updated: graphData[], + pending: number } + >= fetchGraph_internal; + +const graph_internal: State.Array<Json.key<'#graph'>,graphData> = { + name: 'plugins.dive.graph', + getkey: ((d:graphData) => d.key), + signal: signalGraph, + fetch: fetchGraph, + reload: reloadGraph, + order: byGraphData, +}; +/** The graph being built as a set of vertices and edges */ +export const graph: State.Array<Json.key<'#graph'>,graphData> = graph_internal; -/** Default value for `diffData` */ -export const diffDataDefault: diffData = - { root: undefined, add: { nodes: [], deps: [] }, sub: [] }; +/** Default value for `graphData` */ +export const graphDataDefault: graphData = + { key: Json.jKey<'#graph'>('#graph')(''), element: elementDefault }; const window_internal: Server.SetRequest<explorationWindow,null> = { kind: Server.RqKind.SET, @@ -318,16 +539,6 @@ const window_internal: Server.SetRequest<explorationWindow,null> = { /** Set the exploration window */ export const window: Server.SetRequest<explorationWindow,null>= window_internal; -const graph_internal: Server.GetRequest<null,graphData> = { - kind: Server.RqKind.GET, - name: 'plugins.dive.graph', - input: Json.jNull, - output: jGraphData, - signals: [], -}; -/** Retrieve the whole graph */ -export const graph: Server.GetRequest<null,graphData>= graph_internal; - const clear_internal: Server.ExecRequest<null,null> = { kind: Server.RqKind.EXEC, name: 'plugins.dive.clear', @@ -338,44 +549,44 @@ const clear_internal: Server.ExecRequest<null,null> = { /** Erase the graph and start over with an empty one */ export const clear: Server.ExecRequest<null,null>= clear_internal; -const add_internal: Server.ExecRequest<marker,diffData> = { +const add_internal: Server.ExecRequest<marker,nodeId | undefined> = { kind: Server.RqKind.EXEC, name: 'plugins.dive.add', input: jMarker, - output: jDiffData, + output: Json.jOption(jNodeId), signals: [], }; /** Add a node to the graph */ -export const add: Server.ExecRequest<marker,diffData>= add_internal; +export const add: Server.ExecRequest<marker,nodeId | undefined>= add_internal; -const explore_internal: Server.ExecRequest<nodeId,diffData> = { +const explore_internal: Server.ExecRequest<nodeId,null> = { kind: Server.RqKind.EXEC, name: 'plugins.dive.explore', input: jNodeId, - output: jDiffData, + output: Json.jNull, signals: [], }; /** Explore the graph starting from an existing vertex */ -export const explore: Server.ExecRequest<nodeId,diffData>= explore_internal; +export const explore: Server.ExecRequest<nodeId,null>= explore_internal; -const show_internal: Server.ExecRequest<nodeId,diffData> = { +const show_internal: Server.ExecRequest<nodeId,null> = { kind: Server.RqKind.EXEC, name: 'plugins.dive.show', input: jNodeId, - output: jDiffData, + output: Json.jNull, signals: [], }; /** Show the dependencies of an existing vertex */ -export const show: Server.ExecRequest<nodeId,diffData>= show_internal; +export const show: Server.ExecRequest<nodeId,null>= show_internal; -const hide_internal: Server.ExecRequest<nodeId,diffData> = { +const hide_internal: Server.ExecRequest<nodeId,null> = { kind: Server.RqKind.EXEC, name: 'plugins.dive.hide', input: jNodeId, - output: jDiffData, + output: Json.jNull, signals: [], }; /** Hide the dependencies of an existing vertex */ -export const hide: Server.ExecRequest<nodeId,diffData>= hide_internal; +export const hide: Server.ExecRequest<nodeId,null>= hide_internal; /* ------------------------------------- */ diff --git a/ivette/src/frama-c/plugins/dive/index.tsx b/ivette/src/frama-c/plugins/dive/index.tsx index ea93fa70f1497e6ae20e69dc94264318f3db3f1f..77dd2a9f9aa1316c467648d7493450d287645c96 100644 --- a/ivette/src/frama-c/plugins/dive/index.tsx +++ b/ivette/src/frama-c/plugins/dive/index.tsx @@ -28,7 +28,7 @@ import * as Ivette from 'ivette'; import * as Server from 'frama-c/server'; import * as States from 'frama-c/states'; -import * as API from 'frama-c/plugins/dive/api'; +import * as API from './api'; import Cytoscape from 'cytoscape'; import CytoscapeComponent from 'react-cytoscapejs'; @@ -63,6 +63,11 @@ interface CytoscapeExtended extends Cytoscape.Core { panzoom(options: unknown): void; } +type Identified = { id: string } +type NodeData = Cytoscape.NodeDataDefinition & Identified +type EdgeData = { id: string;[key: string]: unknown } +type NodeOrId = string | Cytoscape.NodeSingular + function callstackToString(callstack: API.callstack): string { return callstack.map((cs) => `${cs.fun}:${cs.instr}`).join('/'); } @@ -167,20 +172,18 @@ class Dive { if (context) { (this.cy.style() as any).selector('node').style('width', (node: any) => { - const fStyle = node.pstyle('font-style').strValue; - const weight = node.pstyle('font-weight').strValue; - const size = node.pstyle('font-size').pfValue; - const family = node.pstyle('font-family').strValue; - context.font = `${fStyle} ${weight} ${size}px ${family}`; - const width = context.measureText(node.data('label')).width; - return `${Math.max(min, width + padding)}px`; - }); + const fStyle = node.pstyle('font-style').strValue; + const weight = node.pstyle('font-weight').strValue; + const size = node.pstyle('font-size').pfValue; + const family = node.pstyle('font-family').strValue; + context.font = `${fStyle} ${weight} ${size}px ${family}`; + const width = context.measureText(node.data('label')).width; + return `${Math.max(min, width + padding)}px`; + }); } } } /* eslint-enable @typescript-eslint/no-explicit-any */ - - this.refresh(); } onCxtMenu(node: Cytoscape.NodeSingular): Cxtcommand[] { @@ -189,7 +192,7 @@ class Dive { buildCxtMenu(commands, <><div className="fas fa-binoculars fa-2x" />Explore</>, () => { this.explore(node); }); - if (data.kind === 'composite') + if (data.nkind === 'composite') buildCxtMenu(commands, <><div className="fa fa-expand-arrows-alt fa-2x" />Unfold</>); else @@ -304,84 +307,100 @@ class Dive { timeout = setTimeout(() => { tips?.forEach((tip) => tip.hide()); tips = null; // Force rebuilding tips in case they changed - }, 1000); + }, 0); }); } - receiveGraph(data: API.graphData): Cytoscape.CollectionReturnValue { - let newNodes = this.cy.collection(); + updateElement(group: Cytoscape.ElementGroup, data: NodeData | EdgeData): + Cytoscape.CollectionReturnValue { + let element = this.cy.$id(data.id); + if (element.nonempty()) { + element.removeData(); + element.data(data); + } + else { + element = this.cy.add({ group, data }); + element.addClass("new"); + } + element.removeClass("stale"); + return element; + } - for (const node of data.nodes) { - const data : { [k: string]: unknown } = { ...node}; - if (typeof node.range === 'number') - data.stops = `0% ${node.range}% ${node.range}% 100%`; + updateNode(data: NodeData): + Cytoscape.NodeSingular { + const element = this.updateElement("nodes", data); + element.addClass('node'); + return element; + } - let ele = this.cy.$id(node.id.toString()); - if (ele.nonempty()) { - ele.removeData(); - ele.data(data); - ele.neighborhood('edge').remove(); - } - else { - if (node.locality.callstack) - data.parent = this.referenceCallstack(node.locality.callstack)?.id(); - else - data.parent = this.referenceFile(node.locality.file).id(); - - ele = this.cy.add({group: 'nodes', data, classes: 'new'}); - this.addTips(ele); - newNodes = ele.union(newNodes); - } + updateEdge(src: NodeOrId, dst: NodeOrId, data: EdgeData): + Cytoscape.EdgeSingular { + const source = typeof src === "string" ? src : src.id(); + const target = typeof dst === "string" ? dst : dst.id(); + data = { ...data, source, target }; + const element = this.updateElement("edges", data); + element.addClass('dependency'); + return element; + } - // Add a node for the user to ask for more dependencies - const idmore = `${node.id}-more`; - this.cy.$id(idmore).remove(); - if (node.backward_explored === 'partial') { - const elemore = this.cy.add({ - group: 'nodes', - data: { id: idmore, parent: ele.data('parent') }, - classes: 'new more', - }); - newNodes = elemore.union(newNodes); - this.cy.add({ - group: 'edges', - data: { source: idmore, target: node.id }, - classes: 'new', - }); - } - } + updateNodeData(node: API.node): void { + const data = { ...node, id: `${node.id}` } as NodeData; - for (const dep of data.deps) { - const src = this.cy.$id(dep.src.toString()); - const dst = this.cy.$id(dep.dst.toString()); - this.cy.add({ - data: { - ...(dep as { [k: string]: unknown }), - source: dep.src, - target: dep.dst - }, - group: 'edges', - classes: src?.hasClass('new') || dst?.hasClass('new') ? 'new' : '', - }); + // Interval range visualization (see cytoscape stops style property) + if (typeof node.range === 'number') + data.stops = `0% ${node.range}% ${node.range}% 100%`; + + // Build clusters for this node if needed + if (node.locality.callstack) + data.parent = this.referenceCallstack(node.locality.callstack)?.id(); + else + data.parent = this.referenceFile(node.locality.file).id(); + + // Add new node or update existing node + const ele = this.updateNode(data); + if (ele.hasClass("new")) + this.addTips(ele); + + // Add a node for the user to ask for more dependencies + const idmore = `${node.id}-more`; + if (node.backward_explored === 'partial') { + const elemore = this.updateNode({ id: idmore, parent: data.parent }); + elemore.addClass("more"); + this.updateEdge(elemore, ele, { id: `e${node.id}-more` }); } + else { + this.cy.$id(idmore).remove(); + } + } - return newNodes; + updateEdgeData(edge: API.dependency): void { + const data = { ...edge, id: `e${edge.id}` } as EdgeData; + this.updateEdge(`${edge.src}`, `${edge.dst}`, data); } - receiveData(data: API.diffData): Cytoscape.NodeSingular | undefined { + updateGraph(data: API.graphData[]): void { this.cy.startBatch(); + this.cy.$('.node, .dependency').addClass('stale'); - for (const id of data.sub) - this.remove(this.cy.$id(id.toString())); + // Update vertices + for (const d of data) { + if ('nkind' in d.element) // Node + this.updateNodeData(d.element); + } - const newNodes = this.receiveGraph(data.add); + // Edges must be updated after vertices since their sources and destination + // must have been created beforhand + for (const d of data) { + if ('dkind' in d.element) // Dependency + this.updateEdgeData(d.element); + } - this.cy.endBatch(); + // Remove nodes that are not present anymore + this.cy.$('.stale').forEach(n => this.remove(n)); - this.recomputeLayout(newNodes); + this.cy.endBatch(); - const root = data.root; - return root ? this.cy.$id(root.toString()) : undefined; + this.recomputeLayout(this.cy.$('node.new')); } get layout(): string { @@ -423,14 +442,15 @@ class Dive { } async exec<In>( - request: Server.ExecRequest<In, API.diffData | null>, + request: Server.ExecRequest<In, number | undefined | null>, param: In): Promise<Cytoscape.NodeSingular | undefined> { try { if (Server.isRunning()) { await this.setMode(); - const data = await Server.send(request, param); - if (data) - return this.receiveData(data); + const r = await Server.send(request, param); + if (r) { + return undefined; + } } } catch (err) { @@ -440,21 +460,6 @@ class Dive { return undefined; } - async refresh(): Promise<void> { - try { - if (Server.isRunning()) { - const data = await Server.send(API.graph, {}); - this.cy.startBatch(); - const newNodes = this.receiveGraph(data); - this.cy.endBatch(); - this.recomputeLayout(newNodes); - } - } - catch (err) { - Debug.error(err); - } - } - static async setWindow(window: API.explorationWindow): Promise<void> { if (Server.isRunning()) await Server.send(API.window, window); @@ -573,10 +578,11 @@ type GraphViewRef = { const GraphView = React.forwardRef<GraphViewRef | undefined, GraphViewProps>( (props: GraphViewProps, ref) => { - const {lock, layout, selectionMode} = props; + const { lock, layout, selectionMode } = props; const [dive, setDive] = useState(() => new Dive()); const [selection, updateSelection] = States.useSelection(); + const graph = States.useSyncArrayData(API.graph); function setCy(cy: Cytoscape.Core): void { if (cy !== dive.cy) @@ -586,12 +592,16 @@ const GraphView = React.forwardRef<GraphViewRef | undefined, GraphViewProps>( useImperativeHandle(ref, () => ({ clear: () => dive.clear() })); useEffect(() => { - setDive(new Dive(dive.cy)); + setDive(new Dive(dive.cy)); // On hot reload, setup a new instance }, [Dive]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { dive.layout = layout; - }, [dive, layout]); // eslint-disable-line react-hooks/exhaustive-deps + }, [dive, layout]); + + useEffect(() => { + dive.updateGraph(graph); + }, [dive, graph]); // Follow mode useEffect(() => { diff --git a/ivette/src/frama-c/plugins/dive/style.json b/ivette/src/frama-c/plugins/dive/style.json index ff9498762f52fa09bf66fe501ee44c427029e7a6..79a9907c1e06fd4d0f2841f0d5a4e2fd8e17f16a 100644 --- a/ivette/src/frama-c/plugins/dive/style.json +++ b/ivette/src/frama-c/plugins/dive/style.json @@ -143,7 +143,7 @@ } }, { - "selector": "node[kind='const']", + "selector": "node[nkind='const']", "style": { "shape": "ellipse", "background-color": "#bbb", @@ -152,7 +152,7 @@ } }, { - "selector": "node[kind='alarm']", + "selector": "node[nkind='alarm']", "style": { "shape": "octagon", "background-color": "#f00", @@ -160,13 +160,13 @@ } }, { - "selector": "node[kind='scattered']", + "selector": "node[nkind='scattered']", "style": { "shape": "rhomboid" } }, { - "selector": "node[kind='composite']", + "selector": "node[nkind='composite']", "style": { "ghost": "yes", "ghost-offset-x": "6px", @@ -191,7 +191,7 @@ } }, { - "selector": "edge[kind='callee']", + "selector": "edge[nkind='callee']", "style": { "line-color": "#8f8", "target-arrow-color": "#8f8" diff --git a/ivette/src/frama-c/plugins/eva/Coverage.tsx b/ivette/src/frama-c/plugins/eva/Coverage.tsx index cad3b95c3560ed073255ce6986df945123b196e8..0a048970850663ee84404e3c369409b220e97509 100644 --- a/ivette/src/frama-c/plugins/eva/Coverage.tsx +++ b/ivette/src/frama-c/plugins/eva/Coverage.tsx @@ -22,14 +22,12 @@ import React from 'react'; import { Table, Column } from 'dome/table/views'; -import { CompactModel } from 'dome/table/arrays'; import * as Arrays from 'dome/table/arrays'; import * as Compare from 'dome/data/compare'; import * as Ivette from 'ivette'; import * as States from 'frama-c/states'; - -import * as Ast from 'frama-c/kernel/api/ast'; import * as Eva from 'frama-c/plugins/eva/api/general'; + import CoverageMeter, { percent } from './CoverageMeter'; type stats = Eva.functionStatsData; @@ -70,21 +68,15 @@ const ordering: Arrays.ByColumns<stats> = { ), }; -class Model extends CompactModel<Ast.fct, stats> { - constructor() { - super(Eva.functionStats.getkey); - this.setColumnOrder(ordering); - this.setSorting({ sortBy: 'coverage', sortDirection: 'ASC' }); - } -} - export function CoverageTable(): JSX.Element { - const data = States.useSyncArray(Eva.functionStats).getArray(); - const [selection, updateSelection] = States.useSelection(); - const model = React.useMemo(() => new Model(), []); - React.useEffect(() => model.replaceAllDataWith(data), [model, data]); + const model = States.useSyncArrayModel(Eva.functionStats); + React.useEffect(() => { + model.setColumnOrder(ordering); + model.setSorting({ sortBy: 'coverage', sortDirection: 'ASC' }); + }, [model]); + const [selection, updateSelection] = States.useSelection(); const onSelection = ({ key }: stats): void => { updateSelection({ location: { fct: key } }); }; diff --git a/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx b/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx index aacc53e93e910eb182f1e3713ffdd9e02d4c82b2..026a9e3396ddcd55ef300027690ac99a7a86b691 100644 --- a/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx +++ b/ivette/src/frama-c/plugins/eva/EvaReady/index.tsx @@ -20,16 +20,40 @@ /* */ /* ************************************************************************ */ -import React from 'react'; +import React, { useEffect } from 'react'; +import { GlobalState, useGlobalState } from 'dome/data/states'; import * as States from 'frama-c/states'; +import { Button } from 'dome/controls/buttons'; import * as Eva from 'frama-c/plugins/eva/api/general'; import Gallery from 'dome/controls/gallery.json'; import gearsIcon from '../images/gears.svg'; import './style.css'; +import { onSignal } from 'frama-c/server'; -const EvaReady: React.FC = ({children}) => { +class AckAbortedState extends GlobalState<boolean> { + #signalHookSet = false; + + constructor(initValue: boolean) { + super(initValue); + } + + setupSignalHooks(): void { + if (!this.#signalHookSet) { + onSignal(Eva.signalComputationState, + () => this.setValue(false)); + this.#signalHookSet = true; + } + } +} + +const ackAbortedState = new AckAbortedState(false); + +const EvaReady: React.FC = ({ children }) => { const state = States.useSyncValue(Eva.computationState); + const [ackAborted, setAckAborted] = useGlobalState(ackAbortedState); + + useEffect(() => ackAbortedState.setupSignalHooks()); switch (state) { case undefined: @@ -55,6 +79,27 @@ const EvaReady: React.FC = ({children}) => { case 'computed': return <>{children}</>; + + case 'aborted': + if (ackAborted) { + return <>{children}</>; + } + else { + return ( + <div className="eva-status"> + <span> + The Eva analysis has been prematurely aborted by an internal error + or a user interruption: + the displayed results will be incomplete. + </span> + <Button + label="Ok" + style={{ width: "2cm" }} + onClick={() => setAckAborted(true)} + /> + </div> + ); + } } }; diff --git a/ivette/src/frama-c/plugins/eva/EvaReady/style.css b/ivette/src/frama-c/plugins/eva/EvaReady/style.css index fc2ae05a94d573ef039370d715a8d8f42a602ee9..6a68bead536b05aed50bd41f595f50aac2750057 100644 --- a/ivette/src/frama-c/plugins/eva/EvaReady/style.css +++ b/ivette/src/frama-c/plugins/eva/EvaReady/style.css @@ -3,7 +3,7 @@ flex-direction: column; gap: 20px; align-items: center; - margin:auto; + margin:10%; } .eva-status-icon { @@ -17,6 +17,10 @@ text-align: center; } +.eva-status button { + margin: auto; +} + .eva-status-computing { font-weight: bold; } diff --git a/ivette/src/frama-c/plugins/eva/api/general/index.ts b/ivette/src/frama-c/plugins/eva/api/general/index.ts index a603305fa2d62dae367492959ab5ebbb360583f5..681fa6de976e04dacd381a9b1626ae76cf8a8ee5 100644 --- a/ivette/src/frama-c/plugins/eva/api/general/index.ts +++ b/ivette/src/frama-c/plugins/eva/api/general/index.ts @@ -63,14 +63,16 @@ import { tag } from 'frama-c/kernel/api/data'; import { tagDefault } from 'frama-c/kernel/api/data'; /** State of the computation of Eva Analysis. */ -export type computationStateType = "not_computed" | "computing" | "computed"; +export type computationStateType = + "not_computed" | "computing" | "computed" | "aborted"; /** Decoder for `computationStateType` */ export const jComputationStateType: Json.Decoder<computationStateType> = - Json.jUnion<"not_computed" | "computing" | "computed">( + Json.jUnion<"not_computed" | "computing" | "computed" | "aborted">( Json.jTag("not_computed"), Json.jTag("computing"), Json.jTag("computed"), + Json.jTag("aborted"), ); /** Natural order for `computationStateType` */ @@ -130,11 +132,21 @@ const getCallers_internal: Server.GetRequest<fct,CallSite[]> = { name: 'plugins.eva.general.getCallers', input: jFct, output: Json.jArray(jCallSite), - signals: [], + signals: [ { name: 'plugins.eva.general.signalComputationState' } ], }; /** Get the list of call site of a function */ export const getCallers: Server.GetRequest<fct,CallSite[]>= getCallers_internal; +const getCallees_internal: Server.GetRequest<marker,fct[]> = { + kind: Server.RqKind.GET, + name: 'plugins.eva.general.getCallees', + input: jMarker, + output: Json.jArray(jFct), + signals: [ { name: 'plugins.eva.general.signalComputationState' } ], +}; +/** Return the functions pointed to by a function pointer */ +export const getCallees: Server.GetRequest<marker,fct[]>= getCallees_internal; + /** Data for array rows [`functions`](#functions) */ export interface functionsData { /** Entry identifier. */ @@ -243,7 +255,7 @@ const getDeadCode_internal: Server.GetRequest<fct,deadCode> = { name: 'plugins.eva.general.getDeadCode', input: jFct, output: jDeadCode, - signals: [], + signals: [ { name: 'plugins.eva.general.signalComputationState' } ], }; /** Get the lists of unreachable and of non terminating statements in a function */ export const getDeadCode: Server.GetRequest<fct,deadCode>= getDeadCode_internal; @@ -318,7 +330,7 @@ const taintedLvalues_internal: Server.GetRequest<fct,LvalueTaints[]> = { name: 'plugins.eva.general.taintedLvalues', input: jFct, output: Json.jArray(jLvalueTaints), - signals: [], + signals: [ { name: 'plugins.eva.general.signalComputationState' } ], }; /** Get the tainted lvalues of a given function */ export const taintedLvalues: Server.GetRequest<fct,LvalueTaints[]>= taintedLvalues_internal; @@ -690,7 +702,7 @@ const getStates_internal: Server.GetRequest< input: Json.jPair( jMarker, Json.jBoolean,), output: Json.jArray( Json.jTriple( Json.jString, Json.jString, Json.jString,)), - signals: [], + signals: [ { name: 'plugins.eva.general.signalComputationState' } ], }; /** Get the domain states about the given marker */ export const getStates: Server.GetRequest< diff --git a/ivette/src/frama-c/plugins/eva/api/values/index.ts b/ivette/src/frama-c/plugins/eva/api/values/index.ts index 5991da5fa400387532a0b749de91715a1bb82985..05e2360e485e0cef0436d720245b9877ff20b9b3 100644 --- a/ivette/src/frama-c/plugins/eva/api/values/index.ts +++ b/ivette/src/frama-c/plugins/eva/api/values/index.ts @@ -122,8 +122,8 @@ export const getStmtInfo: Server.GetRequest< const getProbeInfo_internal: Server.GetRequest< marker, - { evaluable: boolean, code?: string, stmt?: marker, rank: number, - effects: boolean, condition: boolean } + { evaluable: boolean, code?: string, stmt?: marker, effects: boolean, + condition: boolean } > = { kind: Server.RqKind.GET, name: 'plugins.eva.values.getProbeInfo', @@ -132,7 +132,6 @@ const getProbeInfo_internal: Server.GetRequest< evaluable: Json.jBoolean, code: Json.jOption(Json.jString), stmt: Json.jOption(jMarker), - rank: Json.jNumber, effects: Json.jBoolean, condition: Json.jBoolean, }), @@ -141,8 +140,8 @@ const getProbeInfo_internal: Server.GetRequest< /** Probe informations */ export const getProbeInfo: Server.GetRequest< marker, - { evaluable: boolean, code?: string, stmt?: marker, rank: number, - effects: boolean, condition: boolean } + { evaluable: boolean, code?: string, stmt?: marker, effects: boolean, + condition: boolean } >= getProbeInfo_internal; /** Evaluation of an expression or lvalue */ diff --git a/ivette/src/frama-c/plugins/eva/valuetable.tsx b/ivette/src/frama-c/plugins/eva/valuetable.tsx index 92da070f66b5096a41eff374af01f6dd8b8e829d..95a83acbc7044e37a0de10da29d3254b55f1f7ab 100644 --- a/ivette/src/frama-c/plugins/eva/valuetable.tsx +++ b/ivette/src/frama-c/plugins/eva/valuetable.tsx @@ -59,7 +59,7 @@ function getAlarmStatus(alarms: Alarm[] | undefined): string { } type MarkerTracked = [ 'Tracked', boolean ] -type MarkerPinned = [ 'Pinned' , boolean ] +type MarkerPinned = [ 'Pinned', boolean ] type MarkerStatus = MarkerTracked | MarkerPinned | 'JustFocused' function MarkerStatusClass(status: MarkerStatus): string { @@ -211,18 +211,22 @@ function useProbeCache(): Request<Location, Probe> { /* -------------------------------------------------------------------------- */ interface StmtProps { + fct?: string; stmt?: Ast.marker; marker?: Ast.marker; short?: boolean; } function Stmt(props: StmtProps): JSX.Element | null { - const { stmt, marker, short } = props; - const { descr, sloc: { base, line } } = States.useMarker(marker); - if (!stmt || !marker) return null; - const label = short ? `@L${line}` : `@${base}:${line}`; + const { fct, stmt, marker, short } = props; + const { descr } = States.useMarker(stmt); + const { sloc } = States.useMarker(marker); + if (!marker || !fct) return null; + // Location sloc should always be defined for statements. + const label = short ? `@L${sloc?.line}` : `@${sloc?.base}:${sloc?.line}`; + const title = stmt ? descr : "Start of function " + fct; const className = 'dome-text-cell eva-stmt'; - return <span className={className} title={descr}>{label}</span>; + return <span className={className} title={title}>{label}</span>; } /* -------------------------------------------------------------------------- */ @@ -289,7 +293,7 @@ async function StackInfos(props: StackInfosProps): Promise<JSX.Element> { onDoubleClick={onDoubleClick} > {caller} - <Stmt stmt={stmt} marker={stmt} /> + <Stmt fct={caller} stmt={stmt} marker={stmt} /> </Cell> ); }; @@ -343,7 +347,7 @@ function ProbeHeader(props: ProbeHeaderProps): JSX.Element { const isPinned = isPinnedMarker(status); const pinText = isPinned ? 'Unpin' : 'Pin'; - const loc: States.SelectionActions = { location: { fct, marker: target} }; + const loc: States.SelectionActions = { location: { fct, marker: target } }; const onClick = (): void => { setSelection(loc); selectProbe(); }; const onDoubleClick = (): void => pinProbe(!isPinned); const onContextMenu = (): void => { @@ -385,7 +389,7 @@ function ProbeHeader(props: ProbeHeaderProps): JSX.Element { <div className='eva-header-text-overflow'> <span className='dome-text-cell' title={code}>{code}</span> </div> - <Stmt stmt={stmt} marker={target} short={true}/> + <Stmt fct={fct} stmt={stmt} marker={target} short={true}/> </TableCell> </th> ); @@ -411,17 +415,22 @@ function ProbeDescr(props: ProbeDescrProps): JSX.Element[] { const valuesClass = classes('eva-table-values', 'eva-table-values-center'); const tableClass = classes('eva-table-descrs', 'eva-table-descr-sticky'); const cls = classes(valuesClass, tableClass); - const title = (s: string): string => `Values ${s} the statement evaluation`; const elements: JSX.Element[] = []; function push(title: string, children: JSX.Element | string): void { elements.push(<td className={cls} title={title}>{children}</td>); } - if (!probe.effects && !probe.condition) - push('Values at the statement', '-'); + if (!probe.effects && !probe.condition) { + if (probe.stmt) + push('Values at the statement', '-'); + else if (probe.fct) + push('Values at the start of function ' + probe.fct, '-'); + else + push('Values at the start of the analysis', '-'); + } if (probe.effects || probe.condition) - push(title('before'), 'Before'); + push('Values just before the statement', 'Before'); if (probe.effects) - push(title('after'), 'After'); + push('Values just after the statement', 'After'); if (probe.condition) { const pushCondition = (s: string): void => { const t = `Values after the condition, in the ${s.toLowerCase()} branch`; @@ -963,7 +972,7 @@ function useEvaluationMode(props: EvaluationModeProps): void { /* -------------------------------------------------------------------------- */ /* Table's state. It is global for when the user changes the view. */ -const CallstackState = new GlobalState<callstack>('Summary'); +export const CallstackState = new GlobalState<callstack>('Summary'); const FunctionsManagerState = new GlobalState(new FunctionsManager()); const FocusState = new GlobalState<Probe | undefined>(undefined); @@ -1032,7 +1041,7 @@ function EvaTable(): JSX.Element { /* On meta-selection, pin the selected location. */ React.useEffect(() => { const pin = (loc: States.Location): void => { - const {marker, fct} = loc; + const { marker, fct } = loc; if (marker && fct) setLocPin({ target: marker, fct }, true); }; States.MetaSelection.on(pin); diff --git a/ivette/src/frama-c/server.ts b/ivette/src/frama-c/server.ts index 2d404a244c3fa91dfacbc3135df8d727def34985..9d2ff03677098da45328e952a7af094b664b93b7 100644 --- a/ivette/src/frama-c/server.ts +++ b/ivette/src/frama-c/server.ts @@ -39,7 +39,7 @@ import * as Json from 'dome/data/json'; import { RichTextBuffer } from 'dome/text/buffers'; import { ChildProcess } from 'child_process'; import { client } from './client_socket'; -//import { client } from './client_zmq'; +// import { client } from './client_zmq'; // -------------------------------------------------------------------------- // --- Server Status @@ -284,6 +284,8 @@ export function stop(): void { } } +Dome.atExit(stop); + // -------------------------------------------------------------------------- // --- Server Control (Kill) // -------------------------------------------------------------------------- @@ -474,6 +476,9 @@ async function _launch(): Promise<void> { env, }; // Launch Process + System.atExit(() => { + sockaddr && System.remove(sockaddr); + }); process = await System.spawn(command, params, options); const logger = (text: string | string[]): void => { buffer.append(text); diff --git a/ivette/src/frama-c/states.ts b/ivette/src/frama-c/states.ts index ca134d60ac1894ab2e33ffc1218de8b3d7071da4..1ff4fadc9ba31801b70fd96a2519b316b43cbc93 100644 --- a/ivette/src/frama-c/states.ts +++ b/ivette/src/frama-c/states.ts @@ -38,6 +38,7 @@ import { Client, useModel } from 'dome/table/models'; import { CompactModel } from 'dome/table/arrays'; import * as Ast from 'frama-c/kernel/api/ast'; import * as Server from './server'; +import * as Status from 'frama-c/kernel/Status'; // -------------------------------------------------------------------------- // --- Pretty Printing (Browser Console) @@ -293,12 +294,14 @@ class SyncArray<K, A> { handler: Array<K, A>; upToDate: boolean; fetching: boolean; + signaled: boolean; // during fetching or offline model: CompactModel<K, A>; constructor(h: Array<K, A>) { this.handler = h; this.fetching = false; this.upToDate = false; + this.signaled = false; this.model = new CompactModel(h.getkey); this.model.setNaturalOrder(h.order); this.fetch = this.fetch.bind(this); @@ -316,12 +319,16 @@ class SyncArray<K, A> { } async fetch(): Promise<void> { - if (this.fetching || !Server.isRunning()) return; + if (this.fetching || !Server.isRunning()) { + this.signaled = true; + return; + } try { this.fetching = true; let pending; /* eslint-disable no-await-in-loop */ do { + this.signaled = false; const data = await Server.send(this.handler.fetch, 20000); const { reload = false, removed = [], updated = [] } = data; const { model } = this; @@ -331,7 +338,7 @@ class SyncArray<K, A> { if (reload || updated.length > 0 || removed.length > 0) model.reload(); pending = data.pending ?? 0; - } while (pending > 0); + } while (this.signaled || pending > 0); /* eslint-enable no-await-in-loop */ } catch (error) { D.error( @@ -339,6 +346,7 @@ class SyncArray<K, A> { error, ); } finally { + this.signaled = false; this.fetching = false; this.upToDate = true; } @@ -348,6 +356,7 @@ class SyncArray<K, A> { try { this.model.clear(); this.upToDate = false; + this.signaled = false; if (Server.isRunning()) { await Server.send(this.handler.reload, null); this.fetch(); @@ -393,27 +402,95 @@ export function reloadArray<K, A>(arr: Array<K, A>): void { currentSyncArray(arr).reload(); } +/** Access to Synchronized Array elements. */ +export interface ArrayProxy<K, A> { + length: number; + getData(elt: K | undefined): (A | undefined); + forEach(fn: (row: A, elt: K) => void): void; +} + +// --- Utility functions + +function arrayGet<K, A>( + model: CompactModel<K, A>, + elt: K | undefined, + _stamp: number, +): A | undefined { + return elt ? model.getData(elt) : undefined; +} + +function arrayProxy<K, A>( + model: CompactModel<K, A>, + _stamp: number, +): ArrayProxy<K, A> { + return { + length: model.length(), + getData: (elt) => elt ? model.getData(elt) : undefined, + forEach: (fn) => model.forEach((r) => fn(r, model.getkey(r))), + }; +} + +// ---- Hooks + /** - Use Synchronized Array (Custom React Hook). + Use Synchronized Array as a low level, ready to use, Table Compact Model. - Unless specified, the hook makes the component re-render on every - update. Disabling this automatic re-rendering can be an option when - using the model to make a table view, which automatically synchronizes on - model updates. - @param sync Whether the component re-renders on updates (default is `true`). + Warning: to be in sync with the array, one shall subscribe to model events, + eg. by using `useModel()` hook, like `<Table/>` element does. */ -export function useSyncArray<K, A>( - arr: Array<K, A>, - sync = true, +export function useSyncArrayModel<K, A>( + arr: Array<K, A> ): CompactModel<K, A> { Server.useStatus(); const st = currentSyncArray(arr); Server.useSignal(arr.signal, st.fetch); st.online(); - useModel(st.model, sync); return st.model; } +/** Use Synchronized Array as a data array. */ +export function useSyncArrayData<K, A>(arr: Array<K, A>): A[] +{ + return useSyncArrayModel(arr).getArray(); +} + +/** Use Synchronized Array element. */ +export function useSyncArrayElt<K, A>( + arr: Array<K, A>, + elt: K | undefined, +): A | undefined { + const model = useSyncArrayModel(arr); + const stamp = useModel(model); + return React.useMemo( + () => arrayGet(model, elt, stamp), + [model, elt, stamp] + ); +} + +/** Use Synchronized Array as an element data getter. */ +export function useSyncArrayGetter<K, A>( + arr: Array<K, A> +): (elt: K | undefined) => (A | undefined) { + const model = useSyncArrayModel(arr); + const stamp = useModel(model); + return React.useCallback( + (elt) => arrayGet(model, elt, stamp), + [model, stamp] + ); +} + +/** Use Synchronized Array as an array proxy. */ +export function useSyncArrayProxy<K, A>( + arr: Array<K, A> +): ArrayProxy<K, A> { + const model = useSyncArrayModel<K, A>(arr); + const stamp = useModel(model); + return React.useMemo( + () => arrayProxy(model, stamp), + [model, stamp] + ); +} + /** Return the associated array model. */ @@ -713,6 +790,14 @@ export function useSelection(): [Selection, (a: SelectionActions) => void] { const [current, setCurrent] = useGlobalState(GlobalSelection); const callback = React.useCallback((action) => { setCurrent(reducer(current, action)); + if (isMultipleSelect(action)) { + const l = action.locations.length; + const markers = + (l > 1) ? `${l} markers selected, listed in the 'Locations' panel` : + (l === 1) ? `1 marker selected` : `no markers selected`; + const text = `${action.name}: ${markers}`; + Status.setMessage({ text, title: action.title, kind: 'success' }); + } }, [current, setCurrent]); return [current, callback]; } @@ -741,11 +826,8 @@ export type attributes = Ast.markerAttributesData; /** Access the marker attributes from AST. */ export function useMarker(marker: Ast.marker | undefined): attributes { - const marks = useSyncArray(Ast.markerAttributes); - if (marker === undefined) return Ast.markerAttributesDataDefault; - const attrs = marks.getData(marker); - if (attrs === undefined) return Ast.markerAttributesDataDefault; - return attrs; + const marks = useSyncArrayElt(Ast.markerAttributes, marker); + return marks ?? Ast.markerAttributesDataDefault; } // -------------------------------------------------------------------------- diff --git a/ivette/src/renderer/Laboratory.tsx b/ivette/src/renderer/Laboratory.tsx index 238b5030ae608ab7cb22d4c0798faf07e9edb8a5..b65ef04c0f4884ce2c180770d3bbe17673f4e66f 100644 --- a/ivette/src/renderer/Laboratory.tsx +++ b/ivette/src/renderer/Laboratory.tsx @@ -253,34 +253,40 @@ const makeGridItem = (customize: unknown, onClose: (id: string) => void) => type Shape = Json.json // Until Grids has a type Shape, use this one instead interface CustomViewsProps { - settings?: string, + settings: string, shape: Shape, setShape: (shape: Shape) => void, views: React.PropsWithChildren<View>[] } -interface CustomViewsSettings { - current?: string; - shapes?: { [k: string]: Shape }; -} +type CustomShapes = { [id: string]: Shape }; +type CustomViews = { [id: string]: View }; function CustomViews(props: CustomViewsProps): JSX.Element { const { settings, shape, setShape, views: libViews } = props; - const [local, setLocal] = Settings.useWindowSettings<CustomViewsSettings>( - settings, - Json.identity as Json.Decoder<CustomViewsSettings & Json.json>, // Clearly abusive conversion, a real decoder is needed + const [current, setCurrent] = Settings.useWindowSettingsData<string>( + `${settings}.current`, + Json.jString, + Json.identity, + '' + ); + const [shapes, setShapes] = Settings.useWindowSettingsData<CustomShapes>( + `${settings}.shapes`, + Json.identity as Json.Decoder<CustomShapes>, + Json.identity as Json.Encoder<CustomShapes>, + // Clearly abusive conversion, real encoder/decoder are needed + {}, + ); + const [customs, setCustoms] = Settings.useLocalStorageData<CustomViews>( + 'frama-c.labview', + Json.identity as Json.Decoder<CustomViews>, + Json.identity as Json.Encoder<CustomViews>, + // Clearly abusive conversion, real encoder/decoder are needed {}, ); - const [customs, setCustoms] = - Settings.useLocalStorage<{ [id: string]: View }>( - 'frama-c.labview', - Json.identity as Json.Decoder<{ [id: string]: View } & Json.json>, // Clearly abusive conversion, a real decoder is needed - {}, - ); const [edited, setEdited] = React.useState<string>(); const triggerDefault = React.useRef<View>(); - const { current, shapes = {} } = local; - const theViews: { [id: string]: View } = {}; + const theViews: CustomViews = {}; _.forEach(libViews, (view) => { const { @@ -316,9 +322,12 @@ function CustomViews(props: CustomViewsProps): JSX.Element { const SELECT = (id: string): void => { if (id && current !== id) { - if (current) shapes[current] = shape; - setLocal({ current: id, shapes }); + if (current) { + const newShapes = { ...shapes, [current]: shape }; + setShapes(newShapes); + } setShape(shapes[id] || getDefaultShape(theViews[id])); + setCurrent(id); } }; @@ -329,8 +338,9 @@ function CustomViews(props: CustomViewsProps): JSX.Element { const isCustom = !view.builtin; const DEFAULT = (): void => { - shapes[id] = undefined; - setLocal({ current: id, shapes }); + const newShapes = { ...shapes }; + delete newShapes[id]; + setShapes(newShapes); setShape(getDefaultShape(view)); }; @@ -340,7 +350,7 @@ function CustomViews(props: CustomViewsProps): JSX.Element { const base = `custom.${view.origin}`; const stock = getStock(view.origin); let k = 1; - let newId = base; + let newId: string = base; while (theViews[newId]) { k += 1; newId = `${base}~${k}`; @@ -349,7 +359,7 @@ function CustomViews(props: CustomViewsProps): JSX.Element { if (newOrder && newOrder.concat) newOrder = newOrder.concat([k]); let newLabel = `Custom ${stock.label}`; if (k > 1) newLabel += `~${k}`; - customs[newId] = { + const customView = { id: newId, label: newLabel, order: newOrder, @@ -357,26 +367,46 @@ function CustomViews(props: CustomViewsProps): JSX.Element { origin: view.origin, builtin: false, }; - setCustoms(customs); - if (current) shapes[current] = shape; - setLocal({ current: newId, shapes }); + setCustoms({ ...customs, [newId]: customView }); + const newShape = + isCurrent ? shape : (shapes[id] ?? getDefaultShape(view)); + const newShapes = { ...shapes, [newId]: newShape }; + setShapes(newShapes); + setShape(newShape); + setCurrent(newId); setEdited(newId); }; const REMOVE = (): void => { - delete customs[id]; - delete shapes[id]; - setCustoms(customs); - const newCurrent = current === id ? undefined : current; - setLocal({ current: newCurrent, shapes }); + const newCustoms = { ... customs }; + const newShapes = { ... shapes }; + delete newCustoms[id]; + delete newShapes[id]; + setCustoms(newCustoms); + setShapes(newShapes); + if (isCurrent) { + const newView = + (view.origin && theViews[view.origin]) || + _.find(theViews, (v: View) => !!v.defaultView) || + _.find(theViews, (v: View) => v.id !== current) || + theViews[0]; + const newId = newView.id; + const newShape = shapes[newId] || getDefaultShape(newView); + setCurrent(newId); + setShape(newShape); + } }; + const onView = (action: string): string => + isCurrent ? `${action} View` : `${action} View (${view.label})`; + const hasRename = !edited && isCustom; + Dome.popupMenu([ - { label: 'Rename View', display: (!edited && isCustom), onClick: RENAME }, + { label: onView('Rename'), display: hasRename, onClick: RENAME }, { label: 'Restore Default', display: isCurrent, onClick: DEFAULT }, - { label: 'Duplicate View', onClick: DUPLICATE }, + { label: onView('Duplicate'), onClick: DUPLICATE }, 'separator', - { label: 'Remove View', display: isCustom, onClick: REMOVE }, + { label: onView('Remove'), display: isCustom, onClick: REMOVE }, ]); }; @@ -384,9 +414,8 @@ function CustomViews(props: CustomViewsProps): JSX.Element { if (edited === id) { const RENAMED = (newLabel: string): void => { if (newLabel) { - const custom = Json.jObj(customs[id] as Json.json) || {}; - if (custom) custom.label = newLabel; - setCustoms(customs); + const customView : View = customs[id]; + setCustoms({ ...customs, [id]: { ...customView, label: newLabel } }); } setEdited(undefined); }; @@ -508,7 +537,7 @@ function CustomGroup({ interface CustomPanelProps { dnd?: DnD; - settings?: string; + settings: string; shape?: Shape; setShape: (shape: Shape) => void; setDragging: (id?: string) => void; @@ -570,7 +599,7 @@ export interface LabViewProps { /** Show component panels. */ customize?: boolean; /** Base settings identifier. */ - settings?: string; + settings: string; } /** diff --git a/man/frama-c.1 b/man/frama-c.1 index c960811ac632c5d687cd1e99f48651132a74b183..1864494be989d5e78d8c40bf2dd218d49980e1c7 100644 --- a/man/frama-c.1 +++ b/man/frama-c.1 @@ -1,6 +1,6 @@ .\" Automatically generated by Pandoc 2.14.0.3 .\" -.TH "FRAMA-C" "1" "" "2023-02-13" "" +.TH "FRAMA-C" "1" "" "2023-05-12" "" .hy .\"------------------------------------------------------------------------ .\" @@ -15,13 +15,13 @@ .\" DO NOT EDIT THIS FILE! .\" This man file has been generated from a Markdown file (frama-c.1.md) -.\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file -.\" and run `make man/frama-c.1`. +.\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file, +.\" run `dune build @check-man` and then `dune promote`. .SH NAME .PP -frama-c[.byte] - a static analyzer for C programs +frama-c - a static analyzer for C programs .PP -frama-c-gui[.byte] - the graphical interface of frama-c +frama-c-gui - the graphical interface of frama-c .SH SYNOPSIS .PP \f[B]frama-c\f[R] [ \f[I]options\f[R] ] \f[I]files\f[R] @@ -45,9 +45,9 @@ will provide the full list of the plugins that are currently installed. \f[B]frama-c\f[R]. It features the same options as the command-line version. .PP -\f[B]frama-c.byte\f[R] and \f[B]frama-c-gui.byte\f[R] are the OCaml -bytecode versions of the command-line and graphical user interface -respectively. +\f[B]ivette\f[R] is a new, Electron-based graphical user interface for +\f[B]frama-c\f[R]. +It also features the same options as the command-line version. .PP By default, Frama-C recognizes \f[I].c\f[R] files as C files needing pre-processing and \f[I].i\f[R] files as C files having been already @@ -435,13 +435,11 @@ outputs the directory where the Frama-C kernel library is installed. alias of \f[B]-print-share-path\f[R]. .TP -print-plugin-path -outputs the directory where Frama-C searches its plugins (can be -overridden by the \f[B]FRAMAC_PLUGIN\f[R] variable and the -\f[B]-add-path\f[R] option). +outputs the directory where Frama-C searches its plugins. .TP -print-share-path -outputs the directory where Frama-C stores its data (can be overridden -by the \f[B]FRAMAC_SHARE\f[R] variable). +outputs the directory where Frama-C stores shareable files +(e.g.\ standard library, machdeps, shared Makefiles). .TP [-no]-remove-exn transforms throw and try/catch statements into normal C functions. diff --git a/man/frama-c.1.md b/man/frama-c.1.md index 5b61fc0b5ecc2413ec8f9a48e0af56fabf1ce0b4..9c1876b46f6a0d221c61afd3cbfae0f188a37ea0 100644 --- a/man/frama-c.1.md +++ b/man/frama-c.1.md @@ -1,5 +1,5 @@ --- -title: 'FRAMA-C(1) 2023-02-13' +title: 'FRAMA-C(1) 2023-05-12' header-includes: - | ```{=man} @@ -16,15 +16,15 @@ header-includes: .\" DO NOT EDIT THIS FILE! .\" This man file has been generated from a Markdown file (frama-c.1.md) - .\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file - .\" and run `make man/frama-c.1`. + .\" using pandoc 2.0 or newer. To modify this file, edit the Markdown file, + .\" run `dune build @check-man` and then `dune promote`. ``` ... # NAME -frama-c[.byte] - a static analyzer for C programs +frama-c - a static analyzer for C programs -frama-c-gui[.byte] - the graphical interface of frama-c +frama-c-gui - the graphical interface of frama-c # SYNOPSIS @@ -44,8 +44,8 @@ will provide the full list of the plugins that are currently installed. **frama-c-gui** is the graphical user interface of **frama-c**. It features the same options as the command-line version. -**frama-c.byte** and **frama-c-gui.byte** are the OCaml bytecode versions -of the command-line and graphical user interface respectively. +**ivette** is a new, Electron-based graphical user interface for **frama-c**. +It also features the same options as the command-line version. By default, Frama-C recognizes *.c* files as C files needing pre-processing and *.i* files as C files having been already pre-processed. @@ -368,12 +368,11 @@ the Frama-C standard library. Defaults to no. : alias of **-print-share-path**. -print-plugin-path -: outputs the directory where Frama-C searches its plugins (can be overridden -by the **FRAMAC_PLUGIN** variable and the **-add-path** option). +: outputs the directory where Frama-C searches its plugins. -print-share-path -: outputs the directory where Frama-C stores its data (can be overridden by the -**FRAMAC_SHARE** variable). +: outputs the directory where Frama-C stores shareable files +(e.g. standard library, machdeps, shared Makefiles). [-no]-remove-exn : transforms throw and try/catch statements into normal C functions. diff --git a/nix/alt-ergo.nix b/nix/alt-ergo.nix index 159534d5d6aa17a3e61d07fd862648c0d537607f..75288b5ff80bfb9a250f48bf2fd1964af1188222 100644 --- a/nix/alt-ergo.nix +++ b/nix/alt-ergo.nix @@ -1,50 +1,47 @@ -{ callPackage -, fetchzip -, lib -, stdenv -, ocaml -, findlib -, ocplib-simplex -, psmt2-frontend -, lablgtk -, zarith -, menhir -, camlzip -, num -, which -, autoreconfHook -}: - -stdenv.mkDerivation rec { - pname = "alt-ergo"; - version = "2.2.0-free"; - - src = fetchzip { - url = https://alt-ergo.ocamlpro.com/http/alt-ergo-free-2.2.0/alt-ergo-free-2.2.0.tar.gz; - sha256 = "11ffm87vsrii8nyhxhbc9gzjmqkspqv7hpjq7ll9xflll7gpnpkj"; - stripRoot=false; - }; - - nativeBuildInputs = [ - autoreconfHook - which - ]; +{ fetchFromGitHub, fetchpatch, lib, which, ocamlPackages }: - buildInputs = [ - ocaml - findlib - zarith - ocplib-simplex - psmt2-frontend - lablgtk - menhir - ]; - - propagatedBuildInputs = [ camlzip num ]; +let + pname = "alt-ergo"; + version = "2.4.2"; - enableParallelBuilding = true; + configureScript = "ocaml unix.cma configure.ml"; - configureFlags = [ "--enable-verbose-make" ]; + src = fetchFromGitHub { + owner = "OCamlPro"; + repo = pname; + rev = "refs/tags/${version}"; + hash = "sha256-8pJ/1UAbheQaLFs5Uubmmf5D0oFJiPxF6e2WTZgRyAc="; + }; +in + +let alt-ergo-lib = ocamlPackages.buildDunePackage rec { + pname = "alt-ergo-lib"; + inherit version src configureScript; + configureFlags = [ pname ]; + nativeBuildInputs = [ which ]; + buildInputs = with ocamlPackages; [ dune-configurator ]; + propagatedBuildInputs = with ocamlPackages; [ num ocplib-simplex seq stdlib-shims zarith ]; + preBuild = '' + substituteInPlace src/lib/util/version.ml --replace 'version="dev"' 'version="${version}"' + ''; +}; in + +let alt-ergo-parsers = ocamlPackages.buildDunePackage rec { + pname = "alt-ergo-parsers"; + inherit version src configureScript; + configureFlags = [ pname ]; + nativeBuildInputs = [ which ocamlPackages.menhir ]; + propagatedBuildInputs = [ alt-ergo-lib ] ++ (with ocamlPackages; [ camlzip psmt2-frontend ]); +}; in + +ocamlPackages.buildDunePackage { + + inherit pname version src configureScript; + + configureFlags = [ pname ]; + + nativeBuildInputs = [ which ocamlPackages.menhir ]; + buildInputs = [ alt-ergo-parsers ocamlPackages.cmdliner ]; meta = { description = "High-performance theorem prover and SMT solver"; diff --git a/nix/e-acsl-tests.nix b/nix/e-acsl-tests.nix index 79c82e91a45bce3690396b3a3883d6e4d01aa832..03e5cf1998b039f38b3b1e524252b0ea288ea66a 100644 --- a/nix/e-acsl-tests.nix +++ b/nix/e-acsl-tests.nix @@ -1,9 +1,12 @@ -{ mk_tests } : +{ mk_tests, config } : + +let e-acsl-tests = "e-acsl-tests" + (if config == "" then "" else "-" + config); in +let ptests = "ptests_config" + (if config == "" then "" else "_" + config) ; in +let tests = " @src/plugins/e-acsl/tests/" + ptests ; in mk_tests { - tests-name = "e-acsl-tests"; + tests-name = e-acsl-tests ; tests-command = '' dune exec -- frama-c-ptests -never-disabled tests src/plugins/e-acsl/tests - dune build -j1 --display short @src/plugins/e-acsl/tests/ptests - ''; + dune build -j1 --display short'' + tests + "\n" ; } diff --git a/nix/frama-c.nix b/nix/frama-c.nix index e24625d7c510383a88c556da57c1a6c6c50078ac..34beab7c25ad1b93e0890ec9831a9b19430a5d17 100644 --- a/nix/frama-c.nix +++ b/nix/frama-c.nix @@ -16,6 +16,7 @@ , dune_3 , dune-configurator , dune-site +, fpath , gcc9 , graphviz , lablgtk3 @@ -29,11 +30,14 @@ , ocamlgraph_gtk , ocp-indent , ppx_deriving +, ppx_deriving_yaml , ppx_deriving_yojson , ppx_import +, unionFind , yojson , which , why3 +, yaml , zarith , zmq # Frama-C extra (other targets do not reconfigure) @@ -71,6 +75,7 @@ stdenvNoCC.mkDerivation rec { dune-configurator dune-site findlib + fpath gcc9 graphviz lablgtk3 @@ -84,11 +89,14 @@ stdenvNoCC.mkDerivation rec { ocamlgraph_gtk ocp-indent ppx_deriving + ppx_deriving_yaml ppx_deriving_yojson ppx_import + unionFind yojson which why3 + yaml zarith zmq # For other CI targets diff --git a/nix/internal-tests.nix b/nix/internal-tests.nix index 1e144928c107a3fbffa355008c6e4057d5f29a29..34cf7a9b1e03adc0108942bad1ecc85fcd762175 100644 --- a/nix/internal-tests.nix +++ b/nix/internal-tests.nix @@ -30,11 +30,14 @@ , ocamlgraph , ocp-indent , ppx_deriving +, ppx_deriving_yaml , ppx_deriving_yojson , ppx_import +, unionFind , yojson , which , why3 +, yaml , zarith , zmq # Frama-C tests @@ -87,10 +90,13 @@ stdenvNoCC.mkDerivation rec { ocamlgraph ocp-indent ppx_deriving + ppx_deriving_yaml ppx_deriving_yojson ppx_import + unionFind yojson which + yaml why3 zarith zmq diff --git a/nix/internal-tests.sh b/nix/internal-tests.sh index 40617ea4ebbf35e21bb2f92746681141632c3239..d9dab79d7ebef11709bf75bc93a641518d4e7435 100755 --- a/nix/internal-tests.sh +++ b/nix/internal-tests.sh @@ -51,9 +51,6 @@ get_matching_branch () { fi } -# fc-dir nix-dir -fc_dir="$(dirname "$(dirname "$(readlink -f "$0")")")" - git_current_branch="$(git branch --show-current)" : "${git_current_branch:=${CI_COMMIT_BRANCH:-}}" echo "currently on branch $git_current_branch" @@ -62,17 +59,18 @@ temporary="$(mktemp -d)" callsite="$(pwd)" cleanup () { - cd $callsite + cd "$callsite" if [[ -n $temporary ]]; - then rm -rf $temporary + then rm -rf "$temporary" fi git worktree prune } trap cleanup EXIT -git worktree add $temporary $(git rev-parse HEAD) -cd $temporary +git worktree add "$temporary" "$(git rev-parse HEAD)" +cd "$temporary" +./nix/wp-cache.nix.sh declare -A plugins=( ) diff --git a/nix/lint.nix b/nix/lint.nix deleted file mode 100644 index 6f79ef2ff81350c5d295e72f36ac5ed7fc57b125..0000000000000000000000000000000000000000 --- a/nix/lint.nix +++ /dev/null @@ -1,41 +0,0 @@ -# TODO: -# - enable lint E-ACSL C files -# - enable check-headers - -{ lib -, stdenv -, bc -# , clang_10 -, frama-c -# , headache -, ocp-indent -} : - -stdenv.mkDerivation rec { - pname = "lint"; - version = frama-c.version; - slang = frama-c.slang; - - src = frama-c.src; - - nativeBuildInputs = frama-c.nativeBuildInputs; - - buildInputs = frama-c.buildInputs ++ [ - bc - # headache - ocp-indent - # clang_10 - ]; - - preConfigure = frama-c.preConfigure; - - buildPhase = '' - make lint - make stats-lint - # STRICT_HEADERS=yes make check-headers - ''; - - installPhase = '' - touch $out - ''; -} diff --git a/nix/menhirLib.nix b/nix/menhirLib.nix deleted file mode 100644 index 34d8e09e0e5f19ad499f5779cb6c7f4a03d92b34..0000000000000000000000000000000000000000 --- a/nix/menhirLib.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ lib, fetchFromGitLab, buildDunePackage }: - -buildDunePackage rec { - pname = "menhirLib"; - version = "20211128"; - - src = fetchFromGitLab { - domain = "gitlab.inria.fr"; - owner = "fpottier"; - repo = "menhir"; - rev = version; - sha256 = "0j7ba5z7rwf85zi56fd3zfp7dvhr6xlj9amambxx57szys6dzz1g"; - }; - - meta = with lib; { - homepage = "http://pauillac.inria.fr/~fpottier/menhir/"; - description = "Runtime support library for parsers generated by Menhir"; - longDescription = '' - Menhir is a LR(1) parser generator for the Objective Caml programming - language. That is, Menhir compiles LR(1) grammar specifications down - to OCaml code. Menhir was designed and implemented by François Pottier - and Yann Régis-Gianas. - ''; - license = with licenses; [ lgpl2Only ]; - maintainers = with maintainers; [ vbgl ]; - }; -} diff --git a/nix/pkgs.nix b/nix/pkgs.nix index eb2500b7752a118ac93120fde67ea16b9bee2db7..8626523577646a6e5dc34237700cfa2a2ab4dde4 100644 --- a/nix/pkgs.nix +++ b/nix/pkgs.nix @@ -5,10 +5,10 @@ let alt-ergo = oself.callPackage ./alt-ergo.nix {}; camlp5 = oself.callPackage ./camlp5.nix {}; headache = oself.callPackage ./headache.nix {}; - menhirLib = oself.callPackage ./menhirLib.nix {}; mlmpfr = oself.callPackage ./mlmpfr.nix {}; - psmt2-frontend = oself.callPackage ./psmt2-frontend.nix {}; why3 = oself.callPackage ./why3.nix {}; + yaml = oself.callPackage ./yaml.nix {}; + ppx_deriving_yaml = oself.callPackage ./ppx_deriving_yaml.nix {}; # Helpers mk_tests = oself.callPackage ./mk_tests.nix {}; @@ -26,11 +26,11 @@ let frama-c = oself.callPackage ./frama-c.nix {}; frama-c-hdrck = oself.callPackage ./frama-c-hdrck.nix {}; frama-c-lint = oself.callPackage ./frama-c-lint.nix {}; - lint = oself.callPackage ./lint.nix {}; # Tests default-config-tests = oself.callPackage ./default-config-tests.nix {}; - e-acsl-tests = oself.callPackage ./e-acsl-tests.nix {}; + e-acsl-tests = oself.callPackage ./e-acsl-tests.nix { config = ""; }; + e-acsl-dev-tests = oself.callPackage ./e-acsl-tests.nix { config = "dev"; }; eva-default-tests = oself.callPackage ./eva-tests.nix { config = ""; }; eva-apron-tests = oself.callPackage ./eva-tests.nix { config = "apron" ; }; eva-bitwise-tests = oself.callPackage ./eva-tests.nix { config = "bitwise" ; }; diff --git a/nix/plugins-tests.nix b/nix/plugins-tests.nix index cbbeb33d9d2fb3eb6dc8438d4cc9d0e746720061..a500d6d0ce11b44a18ed1f1690bd1ae250eb011a 100644 --- a/nix/plugins-tests.nix +++ b/nix/plugins-tests.nix @@ -17,6 +17,7 @@ mk_tests { @tests/scope/ptests \ @tests/sparecode/ptests \ @src/plugins/aorai/tests/ptests \ + @src/plugins/alias/tests/ptests \ @src/plugins/dive/tests/ptests \ @src/plugins/instantiate/tests/ptests \ @src/plugins/loop_analysis/tests/ptests \ diff --git a/nix/ppx_deriving_yaml.nix b/nix/ppx_deriving_yaml.nix new file mode 100644 index 0000000000000000000000000000000000000000..44b6e980ae69201b348aad19bba59a2b4b905e85 --- /dev/null +++ b/nix/ppx_deriving_yaml.nix @@ -0,0 +1,27 @@ +{ lib, buildDunePackage, fetchurl, ppxlib, alcotest, mdx +, ppx_deriving, yaml +}: + +buildDunePackage rec { + pname = "ppx_deriving_yaml"; + version = "0.2.1"; + + minimalOCamlVersion = "4.08"; + + src = fetchurl { + url = "https://github.com/patricoferris/ppx_deriving_yaml/releases/download/v${version}/ppx_deriving_yaml-${version}.tbz"; + sha256 = "sha256-3vmay8UY7d3j96VOQ+D3oYEotzVls91F51ebXWQ/9SQ="; + }; + + propagatedBuildInputs = [ ppxlib ppx_deriving yaml ]; + + doCheck = true; + checkInputs = [ alcotest mdx ]; + + meta = { + description = "A YAML codec generator for OCaml"; + homepage = "https://github.com/patricoferris/ppx_deriving_yaml"; + license = lib.licenses.isc; + maintainers = [ ]; + }; +} diff --git a/nix/psmt2-frontend.nix b/nix/psmt2-frontend.nix deleted file mode 100644 index 98836906d462ecce7f597e8e99df178b5c97fbe4..0000000000000000000000000000000000000000 --- a/nix/psmt2-frontend.nix +++ /dev/null @@ -1,48 +0,0 @@ -{ callPackage -, fetchFromGitHub -, lib -, stdenv -, ocaml -, findlib -, menhir -, autoreconfHook -, which -}: - -stdenv.mkDerivation rec { - pname = "psmt2-frontend"; - version = "0.1"; - - src = fetchFromGitHub { - owner = "Coquera"; - repo = pname; - rev = version; - sha256 = "0k7jlsbkdyg7hafmvynp0ik8xk7mfr00wz27vxn4ncnmp20yz4vn"; - }; - - nativeBuildInputs = [ - autoreconfHook - which - ]; - - buildInputs = [ - ocaml - findlib - menhir - ]; - - enableParallelBuilding = true; - - configureFlags = [ "--enable-verbose-make" ]; - - createFindlibDestdir = true; - - installFlags = "LIBDIR=$(OCAMLFIND_DESTDIR)"; - - meta = { - description = "A simple parser and type-checker for polomorphic extension of the SMT-LIB 2 language"; - license = lib.licenses.asl20; - maintainers = [ lib.maintainers.vbgl ]; - inherit (src.meta) homepage; - }; -} diff --git a/nix/yaml.nix b/nix/yaml.nix new file mode 100644 index 0000000000000000000000000000000000000000..bc8c7af164efc3768c615212b47da43ef5c8cfd5 --- /dev/null +++ b/nix/yaml.nix @@ -0,0 +1,32 @@ +{ lib, fetchurl, buildDunePackage +, dune-configurator +, bos, ctypes, fmt, logs +, mdx, alcotest, crowbar, junit_alcotest, ezjsonm +}: + +buildDunePackage rec { + pname = "yaml"; + version = "3.0.1"; + + src = fetchurl { + url = "https://github.com/avsm/ocaml-yaml/releases/download/v${version}/yaml-${version}.tbz"; + sha256 = "ku0bpClVmhS2tF4XDzSCGReR+ZrFGJpfIGEuFb+99pU="; + }; + + minimalOCamlVersion = "4.05.0"; + + buildInputs = [ dune-configurator ]; + propagatedBuildInputs = [ bos ctypes ]; + + doCheck = true; + nativeCheckInputs = [ mdx.bin ]; + checkInputs = [ fmt logs alcotest crowbar junit_alcotest ezjsonm ]; + + meta = { + description = "Parse and generate YAML 1.1 files"; + homepage = "https://github.com/avsm/ocaml-yaml"; + license = lib.licenses.isc; + maintainers = [ lib.maintainers.vbgl ]; + }; + +} diff --git a/opam b/opam index f221a563d28604d800206a45629726462bb97aff..1483c4466ca49ad7bafddc56f46be8f6ac65b27e 100644 --- a/opam +++ b/opam @@ -1,7 +1,7 @@ opam-version: "2.0" name: "frama-c" synopsis: "Platform dedicated to the analysis of source code written in C" -version: "26.1+dev" +version: "27.0+dev" description:""" Frama-C gathers several analysis techniques in a single collaborative framework, based on analyzers (called "plug-ins") that can build upon the @@ -17,7 +17,7 @@ Thanks to this approach, Frama-C provides sophisticated tools, including: These plug-ins communicate between each other via the Frama-C API and via ACSL (ANSI/ISO C Specification Language) properties. """ -maintainer: "francois.bobot@cea.fr" +maintainer: "frama-ci-bot@frama-c.com" authors: [ "Michele Alberti" "Thibaud Antignac" @@ -40,6 +40,7 @@ authors: [ "Philippe Herrmann" "Maxime Jacquemin" "Florent Kirchner" + "Alexander Kogtenkov" "Tristan Le Gall" "Jean-Christophe Léchenet" "Matthieu Lemerre" @@ -60,6 +61,7 @@ authors: [ "Armand Puccetti" "Félix Ridoux" "Virgile Robles" + "Jan Rochel" "Muriel Roger" "Julien Signoles" "Nicolas Stouls" @@ -69,7 +71,7 @@ authors: [ homepage: "https://frama-c.com/" license: "LGPL-2.1-only" dev-repo: "git+https://git.frama-c.com/pub/frama-c.git" -doc: "http://frama-c.com/download/user-manual-26.1-Iron.pdf" +doc: "http://frama-c.com/download/user-manual-27.0-Cobalt.pdf" bug-reports: "https://git.frama-c.com/pub/frama-c/issues" tags: [ "deductive" @@ -119,15 +121,17 @@ depends: [ "conf-time" { with-test } "menhir" { >= "20181006" & build } "ocaml" { >= "4.11.1" } - "ocamlfind" # needed beyond build stage, used by -load-module "ocamlgraph" { >= "1.8.8" } + "unionFind" { >= "20220107" } "why3" { >= "1.6.0" } + "yaml" { >= "3.0.0" } "yojson" {>= "1.6.0" & (>= "2.0.1" | !with-test)} "zarith" { >= "1.5" } # PPXs "ppx_deriving" "ppx_deriving_yojson" + "ppx_deriving_yaml" { >= "0.2.0" } "ppx_import" # GTK3 for non-macos only diff --git a/reference-configuration.md b/reference-configuration.md index 37e05fd560a14445ac2d844221436547f69d2e84..a42c129d996338d181509daec2e1e9a241980e1d 100644 --- a/reference-configuration.md +++ b/reference-configuration.md @@ -4,15 +4,20 @@ compiling Frama-C+dev. - OCaml 4.13.1 - alt-ergo-free.2.2.0 (for wp, optional) - apron.v0.9.13 (for eva, optional) -- dune.3.4.1 -- dune-site.3.4.1 +- dune.3.5.0 +- dune-configurator.3.5.0 +- dune-site.3.5.0 - lablgtk3.3.1.2 - lablgtk3-sourceview3.3.1.2 +- menhir.20211128 - mlmpfr.4.1.0+bugfix2 (for eva, optional) - ocamlfind.1.9.5 - ocamlgraph.2.0.0 +- ocp-indent.1.8.1 (for linting, optional) +- ppx_deriving_yaml.0.2.1 - ppx_deriving_yojson.3.7.0 - ppx_import.1.10.0 +- unionFind.20220122 - why3.1.6.0 - yojson.2.0.2 - zarith.1.12 diff --git a/releases/27.0.md b/releases/27.0.md new file mode 100644 index 0000000000000000000000000000000000000000..f650a45758482e749082bcab405bed4ba5158804 --- /dev/null +++ b/releases/27.0.md @@ -0,0 +1,27 @@ +# Kernel +- Supports C11 `_Generic` +- New machdep mechanism, based on YAML files +- New script for generating machdeps from a C11 compiler + +# Aoraï +- Supports specification about floating-point variables. + +# Eva +- The octagon domain can now infer relations between any lvalues of integer or + pointer types. +- Fixes the bitwise domain on big-endian architectures. + +# WP +- Why3 version bumped to 1.6.0. +- New options for controlling goal automatic splitting +- Default timeout is now 2s + +# GTK GUI +- Removed GTK2 support + +# Ivette +- The Eva table can show the values of function parameters, the logical status + of ACSL predicates, and the values of C lvalues in these predicates. + It also shows the status of uninitialized and escaping variables. +- Information about C types are shown in the Inspector. +- Many bug fixes and user experience improvements. diff --git a/share/analysis-scripts/clone.sh b/share/analysis-scripts/clone.sh index 1633382be282b2561c9ca593f090920a65f9efe5..1c5abe563fd6ec5f8796bdfa8c49e7a882dc343f 100755 --- a/share/analysis-scripts/clone.sh +++ b/share/analysis-scripts/clone.sh @@ -94,10 +94,8 @@ if [ ! -e "$target_path/build/bin/frama-c" ] then ( cd "$target_path"; - autoconf -f --warnings=none; - ./configure --quiet --prefix=$(pwd)/build > /dev/null; - make -j > /dev/null; - make install > /dev/null; + make -j --quiet > /dev/null; + make install PREFIX=$(pwd)/build > /dev/null; ) fi diff --git a/share/analysis-scripts/epilogue.mk b/share/analysis-scripts/epilogue.mk index 359a8fbf766bf381e3ed8a46b8498d0f79d5b620..7a2a542ee40ae718c6016deac7249efa49eca5b8 100644 --- a/share/analysis-scripts/epilogue.mk +++ b/share/analysis-scripts/epilogue.mk @@ -29,6 +29,7 @@ eva: $(TARGETS) parse: $(TARGETS:%.eva=%.parse) # Opening one GUI for each target is cumbersome; we open only the first target gui: $(firstword $(TARGETS)).gui +ivette: $(firstword $(TARGETS)).ivette # Default target all: eva diff --git a/share/analysis-scripts/summary.py b/share/analysis-scripts/summary.py index 6aa1ed705db3e72b6f8c15fa9ef4dee7d027435e..20e5fdeb0ce2022b5506c22226419026c3f99603 100755 --- a/share/analysis-scripts/summary.py +++ b/share/analysis-scripts/summary.py @@ -126,7 +126,6 @@ def smart_rename(target): target = re.sub("main\.eva$", "", target) target = re.sub("\.eva$", "", target) target = re.sub("\.frama-c/", "", target) - target = re.sub("qds/frama-c", "qds", target) return target diff --git a/share/dune b/share/dune index b086bb6380a1d256b252d1517de32548a1871a3e..77f771002d1b2e413dd411f13512b51fbf62f5b9 100644 --- a/share/dune +++ b/share/dune @@ -133,8 +133,6 @@ (libc/__fc_inet.h as libc/__fc_inet.h) (libc/__fc_integer.h as libc/__fc_integer.h) (libc/__fc_libc.h as libc/__fc_libc.h) -(libc/__fc_machdep.h as libc/__fc_machdep.h) -(libc/__fc_machdep_linux_shared.h as libc/__fc_machdep_linux_shared.h) (libc/__fc_runtime.c as libc/__fc_runtime.c) (libc/__fc_select.h as libc/__fc_select.h) (libc/__fc_string_axiomatic.h as libc/__fc_string_axiomatic.h) @@ -326,3 +324,64 @@ (analysis-scripts/template.mk as lib/analysis-scripts/template.mk) )) + +; machdeps +(install + (package frama-c) + (section share) + (files + (machdeps/machdep_avr_8.yaml as share/machdeps/machdep_avr_8.yaml) + (machdeps/machdep_avr_16.yaml as share/machdeps/machdep_avr_16.yaml) + (machdeps/machdep_x86_16.yaml as share/machdeps/machdep_x86_16.yaml) + (machdeps/machdep_x86_32.yaml as share/machdeps/machdep_x86_32.yaml) + (machdeps/machdep_x86_64.yaml as share/machdeps/machdep_x86_64.yaml) + (machdeps/machdep_gcc_x86_16.yaml as share/machdeps/machdep_gcc_x86_16.yaml) + (machdeps/machdep_gcc_x86_32.yaml as share/machdeps/machdep_gcc_x86_32.yaml) + (machdeps/machdep_gcc_x86_64.yaml as share/machdeps/machdep_gcc_x86_64.yaml) + (machdeps/machdep_msvc_x86_64.yaml as share/machdeps/machdep_msvc_x86_64.yaml) + (machdeps/machdep_ppc_32.yaml as share/machdeps/machdep_ppc_32.yaml)) +) + +; machdep generation script +(install + (package frama-c) + (section libexec) + (files + (machdeps/make_machdep/make_machdep.py as lib/make_machdep/make_machdep.py)) +) + +; machdep generation auxiliary files +(install + (package frama-c) + (section lib) + (files + (machdeps/make_machdep/alignof_aligned.c as lib/make_machdep/alignof_aligned.c) + (machdeps/make_machdep/alignof_double.c as lib/make_machdep/alignof_double.c) + (machdeps/make_machdep/alignof_float.c as lib/make_machdep/alignof_float.c) + (machdeps/make_machdep/alignof_fun.c as lib/make_machdep/alignof_fun.c) + (machdeps/make_machdep/alignof_int.c as lib/make_machdep/alignof_int.c) + (machdeps/make_machdep/alignof_long.c as lib/make_machdep/alignof_long.c) + (machdeps/make_machdep/alignof_longdouble.c as lib/make_machdep/alignof_longdouble.c) + (machdeps/make_machdep/alignof_longlong.c as lib/make_machdep/alignof_longlong.c) + (machdeps/make_machdep/alignof_ptr.c as lib/make_machdep/alignof_ptr.c) + (machdeps/make_machdep/alignof_short.c as lib/make_machdep/alignof_short.c) + (machdeps/make_machdep/alignof_str.c as lib/make_machdep/alignof_str.c) + (machdeps/make_machdep/char_is_unsigned.c as lib/make_machdep/char_is_unsigned.c) + (machdeps/make_machdep/const_string_literals.c as lib/make_machdep/const_string_literals.c) + (machdeps/make_machdep/has__builtin_va_list.c as lib/make_machdep/has__builtin_va_list.c) + (machdeps/make_machdep/little_endian.c as lib/make_machdep/little_endian.c) + (machdeps/make_machdep/ptrdiff_t.c as lib/make_machdep/ptrdiff_t.c) + (machdeps/make_machdep/sizeof_double.c as lib/make_machdep/sizeof_double.c) + (machdeps/make_machdep/sizeof_float.c as lib/make_machdep/sizeof_float.c) + (machdeps/make_machdep/sizeof_fun.c as lib/make_machdep/sizeof_fun.c) + (machdeps/make_machdep/sizeof_int.c as lib/make_machdep/sizeof_int.c) + (machdeps/make_machdep/sizeof_long.c as lib/make_machdep/sizeof_long.c) + (machdeps/make_machdep/sizeof_longdouble.c as lib/make_machdep/sizeof_longdouble.c) + (machdeps/make_machdep/sizeof_longlong.c as lib/make_machdep/sizeof_longlong.c) + (machdeps/make_machdep/sizeof_ptr.c as lib/make_machdep/sizeof_ptr.c) + (machdeps/make_machdep/sizeof_short.c as lib/make_machdep/sizeof_short.c) + (machdeps/make_machdep/sizeof_void.c as lib/make_machdep/sizeof_void.c) + (machdeps/make_machdep/size_t.c as lib/make_machdep/size_t.c) + (machdeps/make_machdep/wchar_t.c as lib/make_machdep/wchar_t.c) + (machdeps/make_machdep/make_machdep_common.h as lib/make_machdep/make_machdep_common.h) +)) diff --git a/share/libc/__fc_define_sigset_t.h b/share/libc/__fc_define_sigset_t.h index b5718423a3cebd450cc8c989b7b60b679697e789..30f99f6f804ea9d320d2aa3e1378608b79fa35c9 100644 --- a/share/libc/__fc_define_sigset_t.h +++ b/share/libc/__fc_define_sigset_t.h @@ -32,4 +32,3 @@ typedef unsigned long sigset_t; __END_DECLS __POP_FC_STDLIB #endif - diff --git a/share/libc/__fc_machdep_linux_shared.h b/share/libc/__fc_machdep_linux_shared.h index ac883d753c55b1c14b78296b0cabeb1577379135..3b0e48bc84dfbd98b0b4fb611e86d8f78445d073 100644 --- a/share/libc/__fc_machdep_linux_shared.h +++ b/share/libc/__fc_machdep_linux_shared.h @@ -117,9 +117,6 @@ #define __FC_INTMAX_MAX 9223372036854775807LL #define __FC_UINTMAX_MAX 18446744073709551615ULL -// Linux usually defines wchar_t as a signed int, but this is not required -#define __WCHAR_T int - /* stdio.h */ #define __FC_BUFSIZ 8192 #define __FC_EOF (-1) diff --git a/share/libc/__fc_machdep.h b/share/libc/__fc_machdep_old.c similarity index 99% rename from share/libc/__fc_machdep.h rename to share/libc/__fc_machdep_old.c index 14061cd4decadc773f9aed17f40ee7b2915b2a33..f2ae398c843a010cd0dbd1f2bfdd3c00b260c673 100644 --- a/share/libc/__fc_machdep.h +++ b/share/libc/__fc_machdep_old.c @@ -38,6 +38,7 @@ #define __CHAR_BIT 8 #define __PTRDIFF_T int #define __SIZE_T unsigned int +#define __WCHAR_T long #define __FC_INT_MIN (-2147483647 - 1) #define __FC_INT_MAX 2147483647 #define __FC_UINT_MAX 4294967295U @@ -130,6 +131,7 @@ #define __CHAR_BIT 8 #define __PTRDIFF_T long #define __SIZE_T unsigned long +#define __WCHAR_T int #define __FC_INT_MIN (-2147483647 - 1) #define __FC_INT_MAX 2147483647 #define __FC_UINT_MAX 4294967295U @@ -231,6 +233,7 @@ #define __CHAR_BIT 8 #define __PTRDIFF_T long #define __SIZE_T unsigned int +#define __WCHAR_T int #define __FC_INT_MIN (-32768) #define __FC_INT_MAX 32767 #define __FC_UINT_MAX 65535U @@ -335,6 +338,7 @@ #define __CHAR_BIT 8 #define __PTRDIFF_T int #define __SIZE_T unsigned int +#define __WCHAR_T int #define __FC_INT_MIN (-2147483647 - 1) #define __FC_INT_MAX 2147483647 #define __FC_UINT_MAX 4294967295U diff --git a/share/libc/errno.h b/share/libc/errno.h index ea398ffc8f14ed127dfc5bd7389a7415a3fef62b..2fa3792a89d6b39414b4610f2d3aaffbdf140bfc 100644 --- a/share/libc/errno.h +++ b/share/libc/errno.h @@ -117,6 +117,7 @@ __PUSH_FC_STDLIB #define ENOTCONN __FC_ENOTCONN #define ENOTDIR __FC_ENOTDIR #define ENOTEMPTY __FC_ENOTEMPTY +#define ENOTRECOVERABLE __FC_ENOTRECOVERABLE #define ENOTSOCK __FC_ENOTSOCK #define ENOTSUP __FC_ENOTSUP #define ENOTTY __FC_ENOTTY @@ -124,6 +125,7 @@ __PUSH_FC_STDLIB #define ENXIO __FC_ENXIO #define EOPNOTSUPP __FC_EOPNOTSUPP #define EOVERFLOW __FC_EOVERFLOW +#define EOWNER_DEAD __FC_EOWNER_DEAD #define EPERM __FC_EPERM #define EPFNOSUPPORT __FC_EPFNOSUPPORT #define EPIPE __FC_EPIPE diff --git a/share/libc/inttypes.h b/share/libc/inttypes.h index 1d685c0780b45fdeae13cb8d5af1619ecd911f08..1c64e01cff56a4abce9c0cfd9a8a7389113037a2 100644 --- a/share/libc/inttypes.h +++ b/share/libc/inttypes.h @@ -39,15 +39,15 @@ __PUSH_FC_STDLIB # define PRId32 __PRI32_PREFIX "d" # define PRId64 __PRI64_PREFIX "d" -# define PRIdLEAST8 __PRI8_PREFIX "d" -# define PRIdLEAST16 __PRI16_PREFIX "d" -# define PRIdLEAST32 __PRI32_PREFIX "d" -# define PRIdLEAST64 __PRI64_PREFIX "d" +# define PRIdLEAST8 __PRI_LEAST8_PREFIX "d" +# define PRIdLEAST16 __PRI_LEAST16_PREFIX "d" +# define PRIdLEAST32 __PRI_LEAST32_PREFIX "d" +# define PRIdLEAST64 __PRI_LEAST64_PREFIX "d" -# define PRIdFAST8 __PRI8_PREFIX "d" -# define PRIdFAST16 __PRIFAST16_PREFIX "d" -# define PRIdFAST32 __PRI32_PREFIX "d" -# define PRIdFAST64 __PRI64_PREFIX "d" +# define PRIdFAST8 __PRI_FAST8_PREFIX "d" +# define PRIdFAST16 __PRI_FAST16_PREFIX "d" +# define PRIdFAST32 __PRI_FAST32_PREFIX "d" +# define PRIdFAST64 __PRI_FAST64_PREFIX "d" # define PRIi8 __PRI8_PREFIX "i" @@ -55,15 +55,15 @@ __PUSH_FC_STDLIB # define PRIi32 __PRI32_PREFIX "i" # define PRIi64 __PRI64_PREFIX "i" -# define PRIiLEAST8 __PRI8_PREFIX "i" -# define PRIiLEAST16 __PRI16_PREFIX "i" -# define PRIiLEAST32 __PRI32_PREFIX "i" -# define PRIiLEAST64 __PRI64_PREFIX "i" +# define PRIiLEAST8 __PRI_LEAST8_PREFIX "i" +# define PRIiLEAST16 __PRI_LEAST16_PREFIX "i" +# define PRIiLEAST32 __PRI_LEAST32_PREFIX "i" +# define PRIiLEAST64 __PRI_LEAST64_PREFIX "i" -# define PRIiFAST8 __PRI8_PREFIX "i" -# define PRIiFAST16 __PRIFAST16_PREFIX "i" -# define PRIiFAST32 __PRI32_PREFIX "i" -# define PRIiFAST64 __PRI64_PREFIX "i" +# define PRIiFAST8 __PRI_FAST8_PREFIX "i" +# define PRIiFAST16 __PRI_FAST16_PREFIX "i" +# define PRIiFAST32 __PRI_FAST32_PREFIX "i" +# define PRIiFAST64 __PRI_FAST64_PREFIX "i" /* Octal notation. */ # define PRIo8 __PRI8_PREFIX "o" @@ -71,15 +71,15 @@ __PUSH_FC_STDLIB # define PRIo32 __PRI32_PREFIX "o" # define PRIo64 __PRI64_PREFIX "o" -# define PRIoLEAST8 __PRI8_PREFIX "o" -# define PRIoLEAST16 __PRI16_PREFIX "o" -# define PRIoLEAST32 __PRI32_PREFIX "o" -# define PRIoLEAST64 __PRI64_PREFIX "o" +# define PRIoLEAST8 __PRI_LEAST8_PREFIX "o" +# define PRIoLEAST16 __PRI_LEAST16_PREFIX "o" +# define PRIoLEAST32 __PRI_LEAST32_PREFIX "o" +# define PRIoLEAST64 __PRI_LEAST64_PREFIX "o" -# define PRIoFAST8 __PRI8_PREFIX "o" -# define PRIoFAST16 __PRIFAST16_PREFIX "o" -# define PRIoFAST32 __PRI32_PREFIX "o" - # define PRIoFAST64 __PRI64_PREFIX "o" +# define PRIoFAST8 __PRI_FAST8_PREFIX "o" +# define PRIoFAST16 __PRI_FAST16_PREFIX "o" +# define PRIoFAST32 __PRI_FAST32_PREFIX "o" + # define PRIoFAST64 __PRI_FAST64_PREFIX "o" /* Unsigned integers. */ # define PRIu8 __PRI8_PREFIX "u" @@ -87,15 +87,15 @@ __PUSH_FC_STDLIB # define PRIu32 __PRI32_PREFIX "u" # define PRIu64 __PRI64_PREFIX "u" -# define PRIuLEAST8 __PRI8_PREFIX "u" -# define PRIuLEAST16 __PRI16_PREFIX "u" -# define PRIuLEAST32 __PRI32_PREFIX "u" -# define PRIuLEAST64 __PRI64_PREFIX "u" +# define PRIuLEAST8 __PRI_LEAST8_PREFIX "u" +# define PRIuLEAST16 __PRI_LEAST16_PREFIX "u" +# define PRIuLEAST32 __PRI_LEAST32_PREFIX "u" +# define PRIuLEAST64 __PRI_LEAST64_PREFIX "u" -# define PRIuFAST8 __PRI8_PREFIX "u" -# define PRIuFAST16 __PRIFAST16_PREFIX "u" -# define PRIuFAST32 __PRI32_PREFIX "u" -# define PRIuFAST64 __PRI64_PREFIX "u" +# define PRIuFAST8 __PRI_FAST8_PREFIX "u" +# define PRIuFAST16 __PRI_FAST16_PREFIX "u" +# define PRIuFAST32 __PRI_FAST32_PREFIX "u" +# define PRIuFAST64 __PRI_FAST64_PREFIX "u" /* lowercase hexadecimal notation. */ # define PRIx8 __PRI8_PREFIX "x" @@ -103,15 +103,15 @@ __PUSH_FC_STDLIB # define PRIx32 __PRI32_PREFIX "x" # define PRIx64 __PRI64_PREFIX "x" -# define PRIxLEAST8 __PRI8_PREFIX "x" -# define PRIxLEAST16 __PRI16_PREFIX "x" -# define PRIxLEAST32 __PRI32_PREFIX "x" -# define PRIxLEAST64 __PRI64_PREFIX "x" +# define PRIxLEAST8 __PRI_LEAST8_PREFIX "x" +# define PRIxLEAST16 __PRI_LEAST16_PREFIX "x" +# define PRIxLEAST32 __PRI_LEAST32_PREFIX "x" +# define PRIxLEAST64 __PRI_LEAST64_PREFIX "x" -# define PRIxFAST8 __PRI8_PREFIX "x" -# define PRIxFAST16 __PRIFAST16_PREFIX "x" -# define PRIxFAST32 __PRI32_PREFIX "x" -# define PRIxFAST64 __PRI64_PREFIX "x" +# define PRIxFAST8 __PRI_FAST8_PREFIX "x" +# define PRIxFAST16 __PRI_FAST16_PREFIX "x" +# define PRIxFAST32 __PRI_FAST32_PREFIX "x" +# define PRIxFAST64 __PRI_FAST64_PREFIX "x" /* UPPERCASE hexadecimal notation. */ # define PRIX8 __PRI8_PREFIX "X" @@ -119,15 +119,15 @@ __PUSH_FC_STDLIB # define PRIX32 __PRI32_PREFIX "X" # define PRIX64 __PRI64_PREFIX "X" -# define PRIXLEAST8 __PRI8_PREFIX "X" -# define PRIXLEAST16 __PRI16_PREFIX "X" -# define PRIXLEAST32 __PRI32_PREFIX "X" -# define PRIXLEAST64 __PRI64_PREFIX "X" +# define PRIXLEAST8 __PRI_LEAST8_PREFIX "X" +# define PRIXLEAST16 __PRI_LEAST16_PREFIX "X" +# define PRIXLEAST32 __PRI_LEAST32_PREFIX "X" +# define PRIXLEAST64 __PRI_LEAST64_PREFIX "X" -# define PRIXFAST8 __PRI8_PREFIX "X" -# define PRIXFAST16 __PRIFAST16_PREFIX "X" -# define PRIXFAST32 __PRI32_PREFIX "X" -# define PRIXFAST64 __PRI64_PREFIX "X" +# define PRIXFAST8 __PRI_FAST8_PREFIX "X" +# define PRIXFAST16 __PRI_FAST16_PREFIX "X" +# define PRIXFAST32 __PRI_FAST32_PREFIX "X" +# define PRIXFAST64 __PRI_FAST64_PREFIX "X" /* Macros for printing `intmax_t' and `uintmax_t'. */ @@ -155,15 +155,15 @@ __PUSH_FC_STDLIB # define SCNd32 __PRI32_PREFIX "d" # define SCNd64 __PRI64_PREFIX "d" -# define SCNdLEAST8 __PRI8_PREFIX "d" -# define SCNdLEAST16 __PRI16_PREFIX "d" -# define SCNdLEAST32 __PRI32_PREFIX "d" -# define SCNdLEAST64 __PRI64_PREFIX "d" +# define SCNdLEAST8 __PRI_LEAST8_PREFIX "d" +# define SCNdLEAST16 __PRI_LEAST16_PREFIX "d" +# define SCNdLEAST32 __PRI_LEAST32_PREFIX "d" +# define SCNdLEAST64 __PRI_LEAST64_PREFIX "d" -# define SCNdFAST8 __PRI8_PREFIX "d" -# define SCNdFAST16 __PRIFAST16_PREFIX "d" -# define SCNdFAST32 __PRI32_PREFIX "d" -# define SCNdFAST64 __PRI64_PREFIX "d" +# define SCNdFAST8 __PRI_FAST8_PREFIX "d" +# define SCNdFAST16 __PRI_FAST16_PREFIX "d" +# define SCNdFAST32 __PRI_FAST32_PREFIX "d" +# define SCNdFAST64 __PRI_FAST64_PREFIX "d" /* Signed decimal notation. */ # define SCNi8 __PRI8_PREFIX "i" @@ -171,15 +171,15 @@ __PUSH_FC_STDLIB # define SCNi32 __PRI32_PREFIX "i" # define SCNi64 __PRI64_PREFIX "i" -# define SCNiLEAST8 __PRI8_PREFIX "i" -# define SCNiLEAST16 __PRI16_PREFIX "i" -# define SCNiLEAST32 __PRI32_PREFIX "i" -# define SCNiLEAST64 __PRI64_PREFIX "i" +# define SCNiLEAST8 __PRI_LEAST8_PREFIX "i" +# define SCNiLEAST16 __PRI_LEAST16_PREFIX "i" +# define SCNiLEAST32 __PRI_LEAST32_PREFIX "i" +# define SCNiLEAST64 __PRI_LEAST64_PREFIX "i" -# define SCNiFAST8 __PRI8_PREFIX "i" -# define SCNiFAST16 __PRIFAST16_PREFIX "i" -# define SCNiFAST32 __PRI32_PREFIX "i" -# define SCNiFAST64 __PRI64_PREFIX "i" +# define SCNiFAST8 __PRI_FAST8_PREFIX "i" +# define SCNiFAST16 __PRI_FAST16_PREFIX "i" +# define SCNiFAST32 __PRI_FAST32_PREFIX "i" +# define SCNiFAST64 __PRI_FAST64_PREFIX "i" /* Unsigned decimal notation. */ # define SCNu8 __PRI8_PREFIX "u" @@ -187,15 +187,15 @@ __PUSH_FC_STDLIB # define SCNu32 __PRI32_PREFIX "u" # define SCNu64 __PRI64_PREFIX "u" -# define SCNuLEAST8 __PRI8_PREFIX "u" -# define SCNuLEAST16 __PRI16_PREFIX "u" -# define SCNuLEAST32 __PRI32_PREFIX "u" -# define SCNuLEAST64 __PRI64_PREFIX "u" +# define SCNuLEAST8 __PRI_LEAST8_PREFIX "u" +# define SCNuLEAST16 __PRI_LEAST16_PREFIX "u" +# define SCNuLEAST32 __PRI_LEAST32_PREFIX "u" +# define SCNuLEAST64 __PRI_LEAST64_PREFIX "u" -# define SCNuFAST8 __PRI8_PREFIX "u" -# define SCNuFAST16 __PRIFAST16_PREFIX "u" -# define SCNuFAST32 __PRI32_PREFIX "u" -# define SCNuFAST64 __PRI64_PREFIX "u" +# define SCNuFAST8 __PRI_FAST8_PREFIX "u" +# define SCNuFAST16 __PRI_FAST16_PREFIX "u" +# define SCNuFAST32 __PRI_FAST32_PREFIX "u" +# define SCNuFAST64 __PRI_FAST64_PREFIX "u" /* Octal notation. */ # define SCNo8 __PRI8_PREFIX "o" @@ -203,15 +203,15 @@ __PUSH_FC_STDLIB # define SCNo32 __PRI32_PREFIX "o" # define SCNo64 __PRI64_PREFIX "o" -# define SCNoLEAST8 __PRI8_PREFIX "o" -# define SCNoLEAST16 __PRI16_PREFIX "o" -# define SCNoLEAST32 __PRI32_PREFIX "o" -# define SCNoLEAST64 __PRI64_PREFIX "o" +# define SCNoLEAST8 __PRI_LEAST8_PREFIX "o" +# define SCNoLEAST16 __PRI_LEAST16_PREFIX "o" +# define SCNoLEAST32 __PRI_LEAST32_PREFIX "o" +# define SCNoLEAST64 __PRI_LEAST64_PREFIX "o" -# define SCNoFAST8 __PRI8_PREFIX "o" -# define SCNoFAST16 __PRIFAST16_PREFIX "o" -# define SCNoFAST32 __PRI32_PREFIX "o" -# define SCNoFAST64 __PRI64_PREFIX "o" +# define SCNoFAST8 __PRI_FAST8_PREFIX "o" +# define SCNoFAST16 __PRI_FAST16_PREFIX "o" +# define SCNoFAST32 __PRI_FAST32_PREFIX "o" +# define SCNoFAST64 __PRI_FAST64_PREFIX "o" /* Hexadecimal notation. */ # define SCNx8 __PRI8_PREFIX "x" @@ -219,15 +219,15 @@ __PUSH_FC_STDLIB # define SCNx32 __PRI32_PREFIX "x" # define SCNx64 __PRI64_PREFIX "x" -# define SCNxLEAST8 __PRI8_PREFIX "x" -# define SCNxLEAST16 __PRI16_PREFIX "x" -# define SCNxLEAST32 __PRI32_PREFIX "x" -# define SCNxLEAST64 __PRI64_PREFIX "x" +# define SCNxLEAST8 __PRI_LEAST8_PREFIX "x" +# define SCNxLEAST16 __PRI_LEAST16_PREFIX "x" +# define SCNxLEAST32 __PRI_LEAST32_PREFIX "x" +# define SCNxLEAST64 __PRI_LEAST64_PREFIX "x" -# define SCNxFAST8 __PRI8_PREFIX "x" -# define SCNxFAST16 __PRIFAST16_PREFIX "x" -# define SCNxFAST32 __PRI32_PREFIX "x" -# define SCNxFAST64 __PRI64_PREFIX "x" +# define SCNxFAST8 __PRI_FAST8_PREFIX "x" +# define SCNxFAST16 __PRI_FAST16_PREFIX "x" +# define SCNxFAST32 __PRI_FAST32_PREFIX "x" +# define SCNxFAST64 __PRI_FAST64_PREFIX "x" /* Macros for scanning `intmax_t' and `uintmax_t'. */ @@ -289,4 +289,3 @@ __END_DECLS __POP_FC_STDLIB #endif - diff --git a/share/libc/limits.h b/share/libc/limits.h index 40e674b2b6d78b2d22cd2f7bac416809e8fba3a3..1e78408515458227a89bc497e13e09409fbc9327 100644 --- a/share/libc/limits.h +++ b/share/libc/limits.h @@ -76,30 +76,9 @@ /* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ # define ULLONG_MAX __FC_ULLONG_MAX -/* Maximum number of bytes in a pathname, including the terminating - null character. (Minimum is 256.) */ -#define PATH_MAX __FC_PATH_MAX - -/* Maximum length of a host name (not including the terminating null) - as returned from the gethostname() function. - Note: Mac OS does not define this constant. */ -#define HOST_NAME_MAX __FC_HOST_NAME_MAX - -/* Maximum length of a terminal device name. */ -#define TTY_NAME_MAX __FC_TTY_NAME_MAX - -/* Maximum length of argument to the exec functions including environment data. - Minimum Acceptable Value: {_POSIX_ARG_MAX} (4096 in POSIX.1-2008) - "... the total space used to store the environment and the arguments to the - process is limited to {ARG_MAX} bytes." - */ -#define ARG_MAX 4096 - -// POSIX; used by <sys/uio.h>. -// Must be >= _XOPEN_IOV_MAX, which is 16. -// 1024 is the value used by some Linux implementations. -#define IOV_MAX 1024 +// POSIX-specific definitions +/*** Most restrictive values for the constants below, as mandated by POSIX */ // Maximum Values @@ -166,4 +145,82 @@ #define NL_TEXTMAX _POSIX2_LINE_MAX #define NZERO 20 +/*** POSIX constants. Frama-C usually takes Linux' values by default, but + it can be overloaded by passing e.g. `-cpp-extra-args="-D__FC_XXXX=nnnn"` + on Frama-C's command line. A value of -1 will deactivate the macro (all of + them are optional). +*/ +#define STR(S) # S +#define expand(macro) STR(macro) + +/* Maximum number of bytes in a pathname, including the terminating + null character. (Minimum is 256.) */ +#ifdef __FC_PATH_MAX +# if __FC_PATH_MAX >= 0 + _Static_assert(__FC_PATH_MAX >=_POSIX_PATH_MAX, "__FC_PATH_MAX is too small (" expand(__FC_PATH_MAX) "): minimal value is " expand( _POSIX_PATH_MAX)); +# define PATH_MAX __FC_PATH_MAX +# else +# undef PATH_MAX +# endif +#else +# define PATH_MAX 4096 +#endif + +/* Maximum length of a host name (not including the terminating null) + as returned from the gethostname() function. + Note: Mac OS does not define this constant, and Linux use a strictly smaller + one than what POSIX mandate +*/ +#ifdef __FC_HOST_NAME_MAX +# if __FC_HOST_NAME_MAX >= 0 + // _Static_assert(__FC_HOST_NAME_MAX >=_POSIX_HOST_NAME_MAX, "__FC_HOST_NAME_MAX is too small (" expand(__FC_HOST_NAME_MAX) "): minimal value is " expand(_POSIX_HOST_NAME_MAX)); +# define HOST_NAME_MAX __FC_HOST_NAME_MAX +# else +# undef HOST_NAME_MAX +# endif +#else +# define HOST_NAME_MAX 255 +#endif + +/* Maximum length of a terminal device name. */ +#ifdef __FC_TTY_NAME_MAX +# if __FC_TTY_NAME_MAX >= 0 + _Static_assert(__FC_HOST_NAME_MAX >=_POSIX_TTY_NAME_MAX, "__FC_TTY_NAME_MAX is too small (" expand(__FC_TTY_NAME_MAX) "): minimal value is " expand(_POSIX_TTY_NAME_MAX)); +# define TTY_NAME_MAX __FC_TTY_NAME_MAX +# else +# undef TTY_NAME_MAX +# endif +#else +# define TTY_NAME_MAX 9 +#endif + +/* Maximum length of argument to the exec functions including environment data. + Minimum Acceptable Value: {_POSIX_ARG_MAX} (4096 in POSIX.1-2008) + "... the total space used to store the environment and the arguments to the + process is limited to {ARG_MAX} bytes." + */ +#ifdef __FC_ARG_MAX +# if __FC_ARG_MAX >= 0 + _Static_assert(__FC_ARG_MAX >=_POSIX_ARG_MAX, "__FC_ARG_MAX is too small (" expand(__FC_ARG_MAX) "): minimal value is " expand(__POSIX_ARG_MAX)); +# define ARG_MAX __FC_ARG_MAX +# else +# undef ARG_MAX +# endif +#else +# define ARG_MAX 4096 +#endif + +// POSIX; used by <sys/uio.h>. +// Must be >= _XOPEN_IOV_MAX, which is 16. +#ifdef __FC_IOV_MAX +# if __FC_IOV_MAX >= 0 + _Static_assert(__FC_IOV_MAX >=_XOPEN_IOV_MAX, "__FC_IOV_MAX is too small (" expand(__FC_IOV_MAX) "): minimal value is " expand(_XOPEN_IOV_MAX)); +# define IOV_MAX __FC_IOV_MAX +# else +# undef IOV_MAX +# endif +#else +# define IOV_MAX 255 +#endif + #endif diff --git a/share/libc/signal.h b/share/libc/signal.h index 126a96f1f5eb0c79b8be42f718c9cdd4057f7cf1..30851947103312e43d4a0adf40dfc50484c68c82 100644 --- a/share/libc/signal.h +++ b/share/libc/signal.h @@ -35,9 +35,8 @@ __PUSH_FC_STDLIB __BEGIN_DECLS -/* TODO: put sig_atomic_t in machdep */ #ifndef __sig_atomic_t_defined -typedef volatile int sig_atomic_t; +typedef volatile __FC_SIG_ATOMIC_T sig_atomic_t; #define __sig_atomic_t_defined #endif @@ -103,9 +102,16 @@ extern void __fc_sig_err(int); #define SIGRTMIN 32 #define SIGRTMAX 64 +/* Non-standard macros (depending on the OS, the name has an underscore or not) + supposed to be the number of distinct signals that may be raised. + Upcoming POSIX standard seems to allow for a NSIG_MAX macro in limits.h that + would have roughly the same usage as NSIG (NSIG_MAX would be the maximal value + that a signal can have, i.e. NSIG-1 if we start at 0 and don't leave holes. If + this ever becomes supported, we might use this macro instead +*/ +#ifdef __FC_NSIG #define NSIG __FC_NSIG -#ifdef __FC__NSIG -#define _NSIG __FC__NSIG +#define _NSIG __FC_NSIG #endif #define SA_NOCLDSTOP 0x00000001 diff --git a/share/libc/stdint.h b/share/libc/stdint.h index 09169deced239d98936f085195b16650aed1ba28..839a90e3dc1132e9b5b6a947ef2c27164faf0ec4 100644 --- a/share/libc/stdint.h +++ b/share/libc/stdint.h @@ -96,8 +96,8 @@ typedef __UINTPTR_T uintptr_t; #endif /* ISO C: 7.18.1.5 */ -typedef __INT_MAX_T intmax_t; -typedef __UINT_MAX_T uintmax_t; +typedef __INTMAX_T intmax_t; +typedef __UINTMAX_T uintmax_t; /* ISO C: 7.18.2.1 */ #define INT8_MIN (-128) @@ -147,9 +147,9 @@ typedef __UINT_MAX_T uintmax_t; /* ISO C: 7.18.2.4 - Done directly with definition of corresponding types. */ /* ISO C: 7.18.2.5 */ -#define INTMAX_MIN __FC_INTMAX_MIN -#define INTMAX_MAX __FC_INTMAX_MAX -#define UINTMAX_MAX __FC_UINTMAX_MAX +#define INTMAX_MIN __INTMAX_MIN +#define INTMAX_MAX __INTMAX_MAX +#define UINTMAX_MAX __UINTMAX_MAX /* ISO C: 7.18.3 */ diff --git a/share/libc/stdio.h b/share/libc/stdio.h index eb9282338d5d02a068833c6b89765bf6cac52ff3..736bcfa6f6f4e52131b4d68b2a431f809a707fc2 100644 --- a/share/libc/stdio.h +++ b/share/libc/stdio.h @@ -621,7 +621,5 @@ int asprintf(char **strp, const char *fmt, ...); __END_DECLS -#define IOV_MAX 1024 - __POP_FC_STDLIB #endif diff --git a/share/libc/sys/socket.h b/share/libc/sys/socket.h index 5885125caafe53c8d88ffdb47095ed3a97f7d89a..f96e482a5e5a6ada267a7e4d7f40605abbf8503c 100644 --- a/share/libc/sys/socket.h +++ b/share/libc/sys/socket.h @@ -25,7 +25,7 @@ #include "../features.h" __PUSH_FC_STDLIB __BEGIN_DECLS -#include "../__fc_machdep.h" +#include "__fc_machdep.h" #include "../errno.h" diff --git a/share/libc/sys/types.h b/share/libc/sys/types.h index 73ac60e89245e728374ec8684164b1d3b5ff3c3a..38ae7d90f8b15a832c296f94cc8f0607f4f09dee 100644 --- a/share/libc/sys/types.h +++ b/share/libc/sys/types.h @@ -26,7 +26,7 @@ __PUSH_FC_STDLIB __BEGIN_DECLS -#include "../__fc_machdep.h" +#include "__fc_machdep.h" #include "../__fc_define_id_t.h" #include "../__fc_define_pid_t.h" #include "../__fc_define_size_t.h" diff --git a/share/libc/unistd.h b/share/libc/unistd.h index b6e8f0b54628de43c8fe181b61ec43f8e1837c44..a5ba5bf7da343d2590a12be9a56d68c547ecd89e 100644 --- a/share/libc/unistd.h +++ b/share/libc/unistd.h @@ -38,6 +38,13 @@ __PUSH_FC_STDLIB #include "__fc_define_intptr_t.h" #include "__fc_define_fds.h" #include "limits.h" + +#ifndef __FC_POSIX_VERSION +#error "unistd.h should only be included with a POSIX machdep" +#endif + +#define _POSIX_VERSION __FC_POSIX_VERSION + __BEGIN_DECLS extern volatile int Frama_C_entropy_source; diff --git a/share/machdeps/.machdep_gcc_x86_16.yaml.validated b/share/machdeps/.machdep_gcc_x86_16.yaml.validated new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/share/machdeps/.machdep_msvc_x86_64.yaml.validated b/share/machdeps/.machdep_msvc_x86_64.yaml.validated new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/dev/update_api_doc.sh b/share/machdeps/Makefile old mode 100755 new mode 100644 similarity index 61% rename from dev/update_api_doc.sh rename to share/machdeps/Makefile index 879e0d50410e98b64cf220c67bef3c2ef0567ee3..f2fc15fd2e11603d2a235e5e64f4aa128eed77e8 --- a/dev/update_api_doc.sh +++ b/share/machdeps/Makefile @@ -1,4 +1,3 @@ -#!/bin/sh ########################################################################## # # # This file is part of Frama-C. # @@ -21,12 +20,29 @@ # # ########################################################################## -next=$1 +MANUAL_MACHDEPS=machdep_gcc_x86_16.yaml machdep_msvc_x86_64.yaml -if test -z "$next"; then - echo "Missing argument. Usage is:" - echo "\$ ./bin/update_api_doc.sh <NEXT>" - echo "See the Release Management Documentation for an example." -else - find src -name '*.ml*' -exec sed -i -e "s/Frama-C+dev/${next}/gI" '{}' ';' -fi +update-all: machdep_*.yaml $(MANUAL_MACHDEPS:%=.%.validated) + +machdep_avr_8.yaml \ +machdep_avr_16.yaml \ +machdep_gcc_x86_32.yaml \ +machdep_gcc_x86_64.yaml \ +machdep_ppc_32.yaml : \ +%.yaml: machdep-schema.yaml make_machdep/make_machdep.py make_machdep/*.c + @./make_machdep/make_machdep.py -i --from-file $@ --check + +machdep_x86_16.yaml machdep_x86_32.yaml machdep_x86_64.yaml: \ +machdep_%.yaml: machdep_gcc_%.yaml Makefile + @sed -e 's/sizeof_fun: .*/sizeof_fun: -1/' \ + -e 's/sizeof_void: .*/sizeof_void: -1/' \ + -e 's/alignof_fun: .*/alignof_fun: -1/' \ + -e 's/compiler: .*/compiler: generic/' \ + -e 's/machdep_name: *machdep_gcc_\([[:alnum:]]*\)/machdep_name: machdep_\1/' \ + -e '/ *#undef __GCC.*/d' -e '/ *#define __GCC.*/d' \ + $< > $@ + +.%.validated: % machdep-schema.yaml + @echo "Checking $*" + @./make_machdep/make_machdep.py --from-file $* --check-only + @touch $@ diff --git a/share/machdeps/machdep-schema.yaml b/share/machdeps/machdep-schema.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d36c36b1ad8621056f0bf22ca56be363d85212cd --- /dev/null +++ b/share/machdeps/machdep-schema.yaml @@ -0,0 +1,391 @@ +# Schema of the machine information required by Frama-C. + +alignof_aligned: + + description: alignment of a type with 'aligned' attribute + + type: integer + +alignof_double: + + description: alignment of 'double' type + + type: integer + +alignof_float: + + description: alignment of 'float' type + + type: integer + +alignof_fun: + + description: (non-standard) alignment of a function type. Negative if unsupported + + type: integer + +alignof_int: + + description: alignment of 'int' type + + type: integer + +alignof_long: + + description: alignment of 'long' type + + type: integer + +alignof_longdouble: + + description: alignment of 'long double' type + + type: integer + +alignof_longlong: + + description: alignment of 'long long' type + + type: integer + +alignof_ptr: + + description: alignment of 'void*' type + + type: integer + +alignof_short: + + description: alignment of 'short' type + + type: integer + +alignof_str: + + description: alignment of string + + type: integer + +bufsiz: + + description: value of 'BUFSIZ' macro + + type: string + +char_is_unsigned: + + description: whether 'char' is unsigned + + type: boolean + +compiler: + + description: compiler being used + + type: string + +cpp_arch_flags: + + description: | + arguments to be given to the compiler to select the corresponding + architecture (e.g. '-m32') + + type: list + + items: + + - type: string + +custom_defs: + description: | + arbitrary text that will be reproduced verbatim in the generated + header + type: string + +eof: + + description: value of 'EOF' macro + + type: string + +errno: + + description: all error macros defined in errno.h + + type: list + + items: + + type: object + name: + description: macro name (lowercase) + type: string + value: + description: actual value + type: string + +filename_max: + + description: value of 'FILENAME_MAX' macro + + type: string + +fopen_max: + + description: value of 'FOPEN_MAX' macro + + type: string + +has__builtin_va_list: + + description: Whether '__builtin_va_list' is a known type + + type: boolean + +host_name_max: + + description: expansion of 'HOST_NAME_MAX' POSIX macro + + type: string + +int_fast8_t: + + description: definition of 'int_fast8_t' + + type: string + +int_fast16_t: + + description: definition of 'int_fast16_t' + + type: string + +int_fast32_t: + + description: definition of 'int_fast32_t' + + type: string + +int_fast64_t: + + description: definition of 'int_fast64_t' + + type: string + +intptr_t: + description: definition of 'intptr_t' + + type: string + +l_tmpnam: + + description: value of 'L_tmpnam' macro + + type: string + +little_endian: + + description: whether the architecture is little-endian + + type: boolean + +machdep_name: + + description: | + name of the machdep. Will be used to define a macro allowing + to know during preprocessing which machdep has been selected. + + type: string + +mb_cur_max: + + description: expansion of 'MB_CUR_MAX' macro + + type: string + +nsig: + + description: number of possible signals (non standard macro, empty if undefined) + + type: string + +path_max: + + description: expansion of 'PATH_MAX' POSIX macro + + type: string + +posix_version: + description: | + value of the macro '_POSIX_VERSION' + leave empty for non-POSIX systems + + type: string + +ptrdiff_t: + + description: definition of 'ptrdiff_t' + + type: string + +rand_max: + + description: expansion of 'RAND_MAX' macro + + type: string + +sig_atomic_t: + + description: representation of 'sig_atomic_t' (defined in signal.h) + + type: string + +size_t: + + description: type of 'sizeof e' + + type: string + +sizeof_double: + + description: size of 'double' type + + type: integer + +sizeof_float: + + description: size of 'float' type + + type: integer + +sizeof_fun: + + description: (non-standard) size of a function type. Negative if unsupported + + type: integer + +sizeof_int: + + description: size of 'int' type + + type: integer + +sizeof_long: + + description: size of 'long' type + + type: integer + +sizeof_longdouble: + + description: size of 'long double' type + + type: integer + +sizeof_longlong: + + description: size of 'long long' type + + type: integer + +sizeof_ptr: + + description: size of 'void*' type + + type: integer + +sizeof_short: + + description: size of 'short' type + + type: integer + +sizeof_void: + + description: (non-standard) size of 'void' type. Negative if unsupported + + type: integer + +ssize_t: + + description: definition of 'ssize_t' (POSIX standard type) + + type: string + +time_t: + + description: definition of 'time_t' (in time.h) + + type: string + +tmp_max: + + description: value of 'TMP_MAX' macro + + type: string + +tty_name_max: + + description: value of 'TTY_NAME_MAX' POSIX macro + + type: string + +uint_fast8_t: + + description: definition of 'uint_fast8_t' + + type: string + +uint_fast16_t: + + description: definition of 'uint_fast16_t' + + type: string + +uint_fast32_t: + + description: definition of 'uint_fast32_t' + + type: string + +uint_fast64_t: + + description: definition of 'uint_fast64_t' + + type: string + +uintptr_t: + + description: definition of 'uintptr_t' + + type: string + +version: + + description: information on this machdep + + type: string + +wchar_t: + + description: definition of 'wchar_t' + + type: string + +weof: + + description: value of 'WEOF' macro + + type: string + +wint_t: + + description: definition of 'wint_t' + + type: string + +wordsize: + + description: value of "__WORDSIZE" macro + + type: string diff --git a/share/machdeps/machdep_avr_16.yaml b/share/machdeps/machdep_avr_16.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f5ee3f6c8487f9c21f3de15a75d7255d4ff617d8 --- /dev/null +++ b/share/machdeps/machdep_avr_16.yaml @@ -0,0 +1,759 @@ +alignof_aligned: 1 +alignof_double: 1 +alignof_float: 1 +alignof_fun: 4 +alignof_int: 1 +alignof_long: 1 +alignof_longdouble: 1 +alignof_longlong: 1 +alignof_ptr: 1 +alignof_short: 2 +alignof_str: 1 +bufsiz: '1024' +char_is_unsigned: false +compiler: clang +cpp_arch_flags: +- -target +- avr +- -m16 +custom_defs: | + #undef AVR + #define AVR 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __AVR + #define __AVR 1 + #undef __AVR__ + #define __AVR__ 1 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 1 + #undef __BITINT_MAXWIDTH__ + #define __BITINT_MAXWIDTH__ 128 + #undef __BOOL_WIDTH__ + #define __BOOL_WIDTH__ 8 + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ unsigned int + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ long unsigned int + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __CLANG_ATOMIC_BOOL_LOCK_FREE + #define __CLANG_ATOMIC_BOOL_LOCK_FREE 1 + #undef __CLANG_ATOMIC_CHAR16_T_LOCK_FREE + #define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 1 + #undef __CLANG_ATOMIC_CHAR32_T_LOCK_FREE + #define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 1 + #undef __CLANG_ATOMIC_CHAR_LOCK_FREE + #define __CLANG_ATOMIC_CHAR_LOCK_FREE 1 + #undef __CLANG_ATOMIC_INT_LOCK_FREE + #define __CLANG_ATOMIC_INT_LOCK_FREE 1 + #undef __CLANG_ATOMIC_LLONG_LOCK_FREE + #define __CLANG_ATOMIC_LLONG_LOCK_FREE 1 + #undef __CLANG_ATOMIC_LONG_LOCK_FREE + #define __CLANG_ATOMIC_LONG_LOCK_FREE 1 + #undef __CLANG_ATOMIC_POINTER_LOCK_FREE + #define __CLANG_ATOMIC_POINTER_LOCK_FREE 1 + #undef __CLANG_ATOMIC_SHORT_LOCK_FREE + #define __CLANG_ATOMIC_SHORT_LOCK_FREE 1 + #undef __CLANG_ATOMIC_WCHAR_T_LOCK_FREE + #define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 1 + #undef __CONSTANT_CFSTRINGS__ + #define __CONSTANT_CFSTRINGS__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 9 + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ 1.40129846e-45 + #undef __DBL_DIG__ + #define __DBL_DIG__ 6 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ 1.19209290e-7 + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 24 + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 38 + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 128 + #undef __DBL_MAX__ + #define __DBL_MAX__ 3.40282347e+38 + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-37) + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-125) + #undef __DBL_MIN__ + #define __DBL_MIN__ 1.17549435e-38 + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ + #undef __ELF__ + #define __ELF__ 1 + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846e-45F + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209290e-7F + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282347e+38F + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435e-38F + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __GCC_ATOMIC_BOOL_LOCK_FREE + #define __GCC_ATOMIC_BOOL_LOCK_FREE 1 + #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1 + #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1 + #undef __GCC_ATOMIC_CHAR_LOCK_FREE + #define __GCC_ATOMIC_CHAR_LOCK_FREE 1 + #undef __GCC_ATOMIC_INT_LOCK_FREE + #define __GCC_ATOMIC_INT_LOCK_FREE 1 + #undef __GCC_ATOMIC_LLONG_LOCK_FREE + #define __GCC_ATOMIC_LLONG_LOCK_FREE 1 + #undef __GCC_ATOMIC_LONG_LOCK_FREE + #define __GCC_ATOMIC_LONG_LOCK_FREE 1 + #undef __GCC_ATOMIC_POINTER_LOCK_FREE + #define __GCC_ATOMIC_POINTER_LOCK_FREE 1 + #undef __GCC_ATOMIC_SHORT_LOCK_FREE + #define __GCC_ATOMIC_SHORT_LOCK_FREE 1 + #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL + #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 + #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE + #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 2 + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __GNUC__ + #define __GNUC__ 4 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1002 + #undef __INT16_C_SUFFIX__ + #define __INT16_C_SUFFIX__ + #undef __INT16_FMTd__ + #define __INT16_FMTd__ "d" + #undef __INT16_FMTi__ + #define __INT16_FMTi__ "i" + #undef __INT16_MAX__ + #define __INT16_MAX__ 32767 + #undef __INT16_TYPE__ + #define __INT16_TYPE__ int + #undef __INT32_C_SUFFIX__ + #define __INT32_C_SUFFIX__ L + #undef __INT32_FMTd__ + #define __INT32_FMTd__ "ld" + #undef __INT32_FMTi__ + #define __INT32_FMTi__ "li" + #undef __INT32_MAX__ + #define __INT32_MAX__ 2147483647L + #undef __INT32_TYPE__ + #define __INT32_TYPE__ long int + #undef __INT64_C_SUFFIX__ + #define __INT64_C_SUFFIX__ LL + #undef __INT64_FMTd__ + #define __INT64_FMTd__ "lld" + #undef __INT64_FMTi__ + #define __INT64_FMTi__ "lli" + #undef __INT64_MAX__ + #define __INT64_MAX__ 9223372036854775807LL + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long long int + #undef __INT8_C_SUFFIX__ + #define __INT8_C_SUFFIX__ + #undef __INT8_FMTd__ + #define __INT8_FMTd__ "hhd" + #undef __INT8_FMTi__ + #define __INT8_FMTi__ "hhi" + #undef __INT8_MAX__ + #define __INT8_MAX__ 127 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __INTMAX_C_SUFFIX__ + #define __INTMAX_C_SUFFIX__ LL + #undef __INTMAX_FMTd__ + #define __INTMAX_FMTd__ "lld" + #undef __INTMAX_FMTi__ + #define __INTMAX_FMTi__ "lli" + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 9223372036854775807LL + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long long int + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __INTPTR_FMTd__ + #define __INTPTR_FMTd__ "d" + #undef __INTPTR_FMTi__ + #define __INTPTR_FMTi__ "i" + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 32767 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ int + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 16 + #undef __INT_FAST16_FMTd__ + #define __INT_FAST16_FMTd__ "d" + #undef __INT_FAST16_FMTi__ + #define __INT_FAST16_FMTi__ "i" + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 32767 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ int + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 16 + #undef __INT_FAST32_FMTd__ + #define __INT_FAST32_FMTd__ "ld" + #undef __INT_FAST32_FMTi__ + #define __INT_FAST32_FMTi__ "li" + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 2147483647L + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ long int + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 32 + #undef __INT_FAST64_FMTd__ + #define __INT_FAST64_FMTd__ "lld" + #undef __INT_FAST64_FMTi__ + #define __INT_FAST64_FMTi__ "lli" + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 9223372036854775807LL + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long long int + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __INT_FAST8_FMTd__ + #define __INT_FAST8_FMTd__ "hhd" + #undef __INT_FAST8_FMTi__ + #define __INT_FAST8_FMTi__ "hhi" + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 127 + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __INT_LEAST16_FMTd__ + #define __INT_LEAST16_FMTd__ "d" + #undef __INT_LEAST16_FMTi__ + #define __INT_LEAST16_FMTi__ "i" + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 32767 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ int + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __INT_LEAST32_FMTd__ + #define __INT_LEAST32_FMTd__ "ld" + #undef __INT_LEAST32_FMTi__ + #define __INT_LEAST32_FMTi__ "li" + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 2147483647L + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ long int + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INT_LEAST64_FMTd__ + #define __INT_LEAST64_FMTd__ "lld" + #undef __INT_LEAST64_FMTi__ + #define __INT_LEAST64_FMTi__ "lli" + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 9223372036854775807LL + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long long int + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __INT_LEAST8_FMTd__ + #define __INT_LEAST8_FMTd__ "hhd" + #undef __INT_LEAST8_FMTi__ + #define __INT_LEAST8_FMTi__ "hhi" + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 127 + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __INT_MAX__ + #define __INT_MAX__ 32767 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 16 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 9 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 1.40129846e-45L + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 6 + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.19209290e-7L + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 24 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 38 + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 128 + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 3.40282347e+38L + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-37) + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-125) + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 1.17549435e-38L + #undef __LITTLE_ENDIAN__ + #define __LITTLE_ENDIAN__ 1 + #undef __LLONG_WIDTH__ + #define __LLONG_WIDTH__ 64 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 9223372036854775807LL + #undef __LONG_MAX__ + #define __LONG_MAX__ 2147483647L + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 32 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __OBJC_BOOL_IS_BOOL + #define __OBJC_BOOL_IS_BOOL 0 + #undef __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES + #define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3 + #undef __OPENCL_MEMORY_SCOPE_DEVICE + #define __OPENCL_MEMORY_SCOPE_DEVICE 2 + #undef __OPENCL_MEMORY_SCOPE_SUB_GROUP + #define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4 + #undef __OPENCL_MEMORY_SCOPE_WORK_GROUP + #define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 + #undef __OPENCL_MEMORY_SCOPE_WORK_ITEM + #define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __POINTER_WIDTH__ + #define __POINTER_WIDTH__ 16 + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __PTRDIFF_FMTd__ + #define __PTRDIFF_FMTd__ "d" + #undef __PTRDIFF_FMTi__ + #define __PTRDIFF_FMTi__ "i" + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 32767 + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ int + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 127 + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 32767 + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 127 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 8 + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 4 + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 2 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 4 + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 4 + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 2 + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 2 + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 2 + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 2 + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 2 + #undef __SIZE_FMTX__ + #define __SIZE_FMTX__ "X" + #undef __SIZE_FMTo__ + #define __SIZE_FMTo__ "o" + #undef __SIZE_FMTu__ + #define __SIZE_FMTu__ "u" + #undef __SIZE_FMTx__ + #define __SIZE_FMTx__ "x" + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 65535U + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ unsigned int + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 16 + #undef __UINT16_C_SUFFIX__ + #define __UINT16_C_SUFFIX__ U + #undef __UINT16_FMTX__ + #define __UINT16_FMTX__ "X" + #undef __UINT16_FMTo__ + #define __UINT16_FMTo__ "o" + #undef __UINT16_FMTu__ + #define __UINT16_FMTu__ "u" + #undef __UINT16_FMTx__ + #define __UINT16_FMTx__ "x" + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 65535U + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ unsigned int + #undef __UINT32_C_SUFFIX__ + #define __UINT32_C_SUFFIX__ UL + #undef __UINT32_FMTX__ + #define __UINT32_FMTX__ "lX" + #undef __UINT32_FMTo__ + #define __UINT32_FMTo__ "lo" + #undef __UINT32_FMTu__ + #define __UINT32_FMTu__ "lu" + #undef __UINT32_FMTx__ + #define __UINT32_FMTx__ "lx" + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 4294967295UL + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ long unsigned int + #undef __UINT64_C_SUFFIX__ + #define __UINT64_C_SUFFIX__ ULL + #undef __UINT64_FMTX__ + #define __UINT64_FMTX__ "llX" + #undef __UINT64_FMTo__ + #define __UINT64_FMTo__ "llo" + #undef __UINT64_FMTu__ + #define __UINT64_FMTu__ "llu" + #undef __UINT64_FMTx__ + #define __UINT64_FMTx__ "llx" + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 18446744073709551615ULL + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long long unsigned int + #undef __UINT8_C_SUFFIX__ + #define __UINT8_C_SUFFIX__ + #undef __UINT8_FMTX__ + #define __UINT8_FMTX__ "hhX" + #undef __UINT8_FMTo__ + #define __UINT8_FMTo__ "hho" + #undef __UINT8_FMTu__ + #define __UINT8_FMTu__ "hhu" + #undef __UINT8_FMTx__ + #define __UINT8_FMTx__ "hhx" + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 255 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __UINTMAX_C_SUFFIX__ + #define __UINTMAX_C_SUFFIX__ ULL + #undef __UINTMAX_FMTX__ + #define __UINTMAX_FMTX__ "llX" + #undef __UINTMAX_FMTo__ + #define __UINTMAX_FMTo__ "llo" + #undef __UINTMAX_FMTu__ + #define __UINTMAX_FMTu__ "llu" + #undef __UINTMAX_FMTx__ + #define __UINTMAX_FMTx__ "llx" + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 18446744073709551615ULL + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long long unsigned int + #undef __UINTMAX_WIDTH__ + #define __UINTMAX_WIDTH__ 64 + #undef __UINTPTR_FMTX__ + #define __UINTPTR_FMTX__ "X" + #undef __UINTPTR_FMTo__ + #define __UINTPTR_FMTo__ "o" + #undef __UINTPTR_FMTu__ + #define __UINTPTR_FMTu__ "u" + #undef __UINTPTR_FMTx__ + #define __UINTPTR_FMTx__ "x" + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 65535U + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ unsigned int + #undef __UINTPTR_WIDTH__ + #define __UINTPTR_WIDTH__ 16 + #undef __UINT_FAST16_FMTX__ + #define __UINT_FAST16_FMTX__ "X" + #undef __UINT_FAST16_FMTo__ + #define __UINT_FAST16_FMTo__ "o" + #undef __UINT_FAST16_FMTu__ + #define __UINT_FAST16_FMTu__ "u" + #undef __UINT_FAST16_FMTx__ + #define __UINT_FAST16_FMTx__ "x" + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 65535U + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ unsigned int + #undef __UINT_FAST32_FMTX__ + #define __UINT_FAST32_FMTX__ "lX" + #undef __UINT_FAST32_FMTo__ + #define __UINT_FAST32_FMTo__ "lo" + #undef __UINT_FAST32_FMTu__ + #define __UINT_FAST32_FMTu__ "lu" + #undef __UINT_FAST32_FMTx__ + #define __UINT_FAST32_FMTx__ "lx" + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 4294967295UL + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ long unsigned int + #undef __UINT_FAST64_FMTX__ + #define __UINT_FAST64_FMTX__ "llX" + #undef __UINT_FAST64_FMTo__ + #define __UINT_FAST64_FMTo__ "llo" + #undef __UINT_FAST64_FMTu__ + #define __UINT_FAST64_FMTu__ "llu" + #undef __UINT_FAST64_FMTx__ + #define __UINT_FAST64_FMTx__ "llx" + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 18446744073709551615ULL + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long long unsigned int + #undef __UINT_FAST8_FMTX__ + #define __UINT_FAST8_FMTX__ "hhX" + #undef __UINT_FAST8_FMTo__ + #define __UINT_FAST8_FMTo__ "hho" + #undef __UINT_FAST8_FMTu__ + #define __UINT_FAST8_FMTu__ "hhu" + #undef __UINT_FAST8_FMTx__ + #define __UINT_FAST8_FMTx__ "hhx" + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 255 + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __UINT_LEAST16_FMTX__ + #define __UINT_LEAST16_FMTX__ "X" + #undef __UINT_LEAST16_FMTo__ + #define __UINT_LEAST16_FMTo__ "o" + #undef __UINT_LEAST16_FMTu__ + #define __UINT_LEAST16_FMTu__ "u" + #undef __UINT_LEAST16_FMTx__ + #define __UINT_LEAST16_FMTx__ "x" + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 65535U + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ unsigned int + #undef __UINT_LEAST32_FMTX__ + #define __UINT_LEAST32_FMTX__ "lX" + #undef __UINT_LEAST32_FMTo__ + #define __UINT_LEAST32_FMTo__ "lo" + #undef __UINT_LEAST32_FMTu__ + #define __UINT_LEAST32_FMTu__ "lu" + #undef __UINT_LEAST32_FMTx__ + #define __UINT_LEAST32_FMTx__ "lx" + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 4294967295UL + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ long unsigned int + #undef __UINT_LEAST64_FMTX__ + #define __UINT_LEAST64_FMTX__ "llX" + #undef __UINT_LEAST64_FMTo__ + #define __UINT_LEAST64_FMTo__ "llo" + #undef __UINT_LEAST64_FMTu__ + #define __UINT_LEAST64_FMTu__ "llu" + #undef __UINT_LEAST64_FMTx__ + #define __UINT_LEAST64_FMTx__ "llx" + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 18446744073709551615ULL + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long long unsigned int + #undef __UINT_LEAST8_FMTX__ + #define __UINT_LEAST8_FMTX__ "hhX" + #undef __UINT_LEAST8_FMTo__ + #define __UINT_LEAST8_FMTo__ "hho" + #undef __UINT_LEAST8_FMTu__ + #define __UINT_LEAST8_FMTu__ "hhu" + #undef __UINT_LEAST8_FMTx__ + #define __UINT_LEAST8_FMTx__ "hhx" + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 255 + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __VERSION__ + #define __VERSION__ "Clang 15.0.7" + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 32767 + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ int + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 16 + #undef __WINT_MAX__ + #define __WINT_MAX__ 32767 + #undef __WINT_TYPE__ + #define __WINT_TYPE__ int + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 16 + #undef __clang__ + #define __clang__ 1 + #undef __clang_literal_encoding__ + #define __clang_literal_encoding__ "UTF-8" + #undef __clang_major__ + #define __clang_major__ 15 + #undef __clang_minor__ + #define __clang_minor__ 0 + #undef __clang_patchlevel__ + #define __clang_patchlevel__ 7 + #undef __clang_version__ + #define __clang_version__ "15.0.7 " + #undef __clang_wide_literal_encoding__ + #define __clang_wide_literal_encoding__ "UTF-16" + #undef __llvm__ + #define __llvm__ 1 +eof: (-1) +errno: + e2big: ((int)(66072050 & 0xffff)) + eacces: ((int)(66072050 & 0xffff)) + eaddrinuse: ((int)(66072050 & 0xffff)) + eaddrnotavail: ((int)(66072050 & 0xffff)) + eafnosupport: ((int)(66072050 & 0xffff)) + eagain: ((int)(66072050 & 0xffff)) + ealready: ((int)(66072050 & 0xffff)) + ebadf: ((int)(66072050 & 0xffff)) + ebusy: ((int)(66072050 & 0xffff)) + echild: ((int)(66072050 & 0xffff)) + econnaborted: ((int)(66072050 & 0xffff)) + econnrefused: ((int)(66072050 & 0xffff)) + econnreset: ((int)(66072050 & 0xffff)) + edeadlk: ((int)(66072050 & 0xffff)) + edestaddrreq: ((int)(66072050 & 0xffff)) + edom: '33' + eexist: ((int)(66072050 & 0xffff)) + efault: ((int)(66072050 & 0xffff)) + efbig: ((int)(66072050 & 0xffff)) + ehostunreach: ((int)(66072050 & 0xffff)) + eilseq: ((int)(66072050 & 0xffff)) + einprogress: ((int)(66072050 & 0xffff)) + eintr: ((int)(2453066 & 0x7fff)) + einval: ((int)(66072050 & 0xffff)) + eio: ((int)(66072050 & 0xffff)) + eisconn: ((int)(66072050 & 0xffff)) + eisdir: ((int)(66072050 & 0xffff)) + eloop: ((int)(66072050 & 0xffff)) + emfile: ((int)(66072050 & 0xffff)) + emlink: ((int)(66072050 & 0xffff)) + emsgsize: ((int)(66072050 & 0xffff)) + enametoolong: ((int)(66072050 & 0xffff)) + enetdown: ((int)(66072050 & 0xffff)) + enetreset: ((int)(66072050 & 0xffff)) + enetunreach: ((int)(66072050 & 0xffff)) + enfile: ((int)(66072050 & 0xffff)) + enobufs: ((int)(66072050 & 0xffff)) + enodev: ((int)(66072050 & 0xffff)) + enoent: ((int)(66072050 & 0xffff)) + enoexec: ((int)(66072050 & 0xffff)) + enolck: ((int)(66072050 & 0xffff)) + enomem: ((int)(66072050 & 0xffff)) + enomsg: ((int)(66072050 & 0xffff)) + enoprotoopt: ((int)(66072050 & 0xffff)) + enospc: ((int)(66072050 & 0xffff)) + enosys: ((int)(66081697 & 0x7fff)) + enotconn: ((int)(66072050 & 0xffff)) + enotdir: ((int)(66072050 & 0xffff)) + enotempty: ((int)(66072050 & 0xffff)) + enotsock: ((int)(66072050 & 0xffff)) + enotty: ((int)(66072050 & 0xffff)) + enxio: ((int)(66072050 & 0xffff)) + eopnotsupp: ((int)(66072050 & 0xffff)) + eperm: ((int)(66072050 & 0xffff)) + epipe: ((int)(66072050 & 0xffff)) + eprotonosupport: ((int)(66072050 & 0xffff)) + eprototype: ((int)(66072050 & 0xffff)) + erange: '34' + erofs: ((int)(66072050 & 0xffff)) + espipe: ((int)(66072050 & 0xffff)) + esrch: ((int)(66072050 & 0xffff)) + etimedout: ((int)(66072050 & 0xffff)) + ewouldblock: ((int)(66072050 & 0xffff)) + exdev: ((int)(66072050 & 0xffff)) +filename_max: '' +fopen_max: '' +has__builtin_va_list: true +host_name_max: '64' +int_fast16_t: int +int_fast32_t: long +int_fast64_t: long long +int_fast8_t: signed char +intptr_t: int +l_tmpnam: '' +little_endian: true +machdep_name: machdep_avr_16 +mb_cur_max: ((size_t)16) +nsig: '' +path_max: '4096' +posix_version: '' +ptrdiff_t: int +rand_max: '0x7FFF' +sig_atomic_t: '' +size_t: unsigned int +sizeof_double: 4 +sizeof_float: 4 +sizeof_fun: 1 +sizeof_int: 2 +sizeof_long: 4 +sizeof_longdouble: 4 +sizeof_longlong: 8 +sizeof_ptr: 2 +sizeof_short: 2 +sizeof_void: 1 +ssize_t: '' +time_t: unsigned long +tmp_max: '' +tty_name_max: '32' +uint_fast16_t: unsigned int +uint_fast32_t: unsigned long +uint_fast64_t: unsigned long long +uint_fast8_t: unsigned char +uintptr_t: unsigned int +version: clang version 15.0.7 +wchar_t: int +weof: (0xffffffffu) +wint_t: int +wordsize: '32' diff --git a/share/machdeps/machdep_avr_8.yaml b/share/machdeps/machdep_avr_8.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9a9268a4d5590425281b29da80561ab9d037b8cd --- /dev/null +++ b/share/machdeps/machdep_avr_8.yaml @@ -0,0 +1,758 @@ +alignof_aligned: 1 +alignof_double: 1 +alignof_float: 1 +alignof_fun: 4 +alignof_int: 1 +alignof_long: 1 +alignof_longdouble: 1 +alignof_longlong: 1 +alignof_ptr: 1 +alignof_short: 2 +alignof_str: 1 +bufsiz: '1024' +char_is_unsigned: false +compiler: clang +cpp_arch_flags: +- -target +- avr +custom_defs: | + #undef AVR + #define AVR 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __AVR + #define __AVR 1 + #undef __AVR__ + #define __AVR__ 1 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 1 + #undef __BITINT_MAXWIDTH__ + #define __BITINT_MAXWIDTH__ 128 + #undef __BOOL_WIDTH__ + #define __BOOL_WIDTH__ 8 + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ unsigned int + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ long unsigned int + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __CLANG_ATOMIC_BOOL_LOCK_FREE + #define __CLANG_ATOMIC_BOOL_LOCK_FREE 1 + #undef __CLANG_ATOMIC_CHAR16_T_LOCK_FREE + #define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 1 + #undef __CLANG_ATOMIC_CHAR32_T_LOCK_FREE + #define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 1 + #undef __CLANG_ATOMIC_CHAR_LOCK_FREE + #define __CLANG_ATOMIC_CHAR_LOCK_FREE 1 + #undef __CLANG_ATOMIC_INT_LOCK_FREE + #define __CLANG_ATOMIC_INT_LOCK_FREE 1 + #undef __CLANG_ATOMIC_LLONG_LOCK_FREE + #define __CLANG_ATOMIC_LLONG_LOCK_FREE 1 + #undef __CLANG_ATOMIC_LONG_LOCK_FREE + #define __CLANG_ATOMIC_LONG_LOCK_FREE 1 + #undef __CLANG_ATOMIC_POINTER_LOCK_FREE + #define __CLANG_ATOMIC_POINTER_LOCK_FREE 1 + #undef __CLANG_ATOMIC_SHORT_LOCK_FREE + #define __CLANG_ATOMIC_SHORT_LOCK_FREE 1 + #undef __CLANG_ATOMIC_WCHAR_T_LOCK_FREE + #define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 1 + #undef __CONSTANT_CFSTRINGS__ + #define __CONSTANT_CFSTRINGS__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 9 + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ 1.40129846e-45 + #undef __DBL_DIG__ + #define __DBL_DIG__ 6 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ 1.19209290e-7 + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 24 + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 38 + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 128 + #undef __DBL_MAX__ + #define __DBL_MAX__ 3.40282347e+38 + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-37) + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-125) + #undef __DBL_MIN__ + #define __DBL_MIN__ 1.17549435e-38 + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ + #undef __ELF__ + #define __ELF__ 1 + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846e-45F + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209290e-7F + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282347e+38F + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435e-38F + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __GCC_ATOMIC_BOOL_LOCK_FREE + #define __GCC_ATOMIC_BOOL_LOCK_FREE 1 + #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 1 + #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 1 + #undef __GCC_ATOMIC_CHAR_LOCK_FREE + #define __GCC_ATOMIC_CHAR_LOCK_FREE 1 + #undef __GCC_ATOMIC_INT_LOCK_FREE + #define __GCC_ATOMIC_INT_LOCK_FREE 1 + #undef __GCC_ATOMIC_LLONG_LOCK_FREE + #define __GCC_ATOMIC_LLONG_LOCK_FREE 1 + #undef __GCC_ATOMIC_LONG_LOCK_FREE + #define __GCC_ATOMIC_LONG_LOCK_FREE 1 + #undef __GCC_ATOMIC_POINTER_LOCK_FREE + #define __GCC_ATOMIC_POINTER_LOCK_FREE 1 + #undef __GCC_ATOMIC_SHORT_LOCK_FREE + #define __GCC_ATOMIC_SHORT_LOCK_FREE 1 + #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL + #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 + #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE + #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 2 + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __GNUC__ + #define __GNUC__ 4 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1002 + #undef __INT16_C_SUFFIX__ + #define __INT16_C_SUFFIX__ + #undef __INT16_FMTd__ + #define __INT16_FMTd__ "d" + #undef __INT16_FMTi__ + #define __INT16_FMTi__ "i" + #undef __INT16_MAX__ + #define __INT16_MAX__ 32767 + #undef __INT16_TYPE__ + #define __INT16_TYPE__ int + #undef __INT32_C_SUFFIX__ + #define __INT32_C_SUFFIX__ L + #undef __INT32_FMTd__ + #define __INT32_FMTd__ "ld" + #undef __INT32_FMTi__ + #define __INT32_FMTi__ "li" + #undef __INT32_MAX__ + #define __INT32_MAX__ 2147483647L + #undef __INT32_TYPE__ + #define __INT32_TYPE__ long int + #undef __INT64_C_SUFFIX__ + #define __INT64_C_SUFFIX__ LL + #undef __INT64_FMTd__ + #define __INT64_FMTd__ "lld" + #undef __INT64_FMTi__ + #define __INT64_FMTi__ "lli" + #undef __INT64_MAX__ + #define __INT64_MAX__ 9223372036854775807LL + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long long int + #undef __INT8_C_SUFFIX__ + #define __INT8_C_SUFFIX__ + #undef __INT8_FMTd__ + #define __INT8_FMTd__ "hhd" + #undef __INT8_FMTi__ + #define __INT8_FMTi__ "hhi" + #undef __INT8_MAX__ + #define __INT8_MAX__ 127 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __INTMAX_C_SUFFIX__ + #define __INTMAX_C_SUFFIX__ LL + #undef __INTMAX_FMTd__ + #define __INTMAX_FMTd__ "lld" + #undef __INTMAX_FMTi__ + #define __INTMAX_FMTi__ "lli" + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 9223372036854775807LL + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long long int + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __INTPTR_FMTd__ + #define __INTPTR_FMTd__ "d" + #undef __INTPTR_FMTi__ + #define __INTPTR_FMTi__ "i" + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 32767 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ int + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 16 + #undef __INT_FAST16_FMTd__ + #define __INT_FAST16_FMTd__ "d" + #undef __INT_FAST16_FMTi__ + #define __INT_FAST16_FMTi__ "i" + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 32767 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ int + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 16 + #undef __INT_FAST32_FMTd__ + #define __INT_FAST32_FMTd__ "ld" + #undef __INT_FAST32_FMTi__ + #define __INT_FAST32_FMTi__ "li" + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 2147483647L + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ long int + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 32 + #undef __INT_FAST64_FMTd__ + #define __INT_FAST64_FMTd__ "lld" + #undef __INT_FAST64_FMTi__ + #define __INT_FAST64_FMTi__ "lli" + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 9223372036854775807LL + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long long int + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __INT_FAST8_FMTd__ + #define __INT_FAST8_FMTd__ "hhd" + #undef __INT_FAST8_FMTi__ + #define __INT_FAST8_FMTi__ "hhi" + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 127 + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __INT_LEAST16_FMTd__ + #define __INT_LEAST16_FMTd__ "d" + #undef __INT_LEAST16_FMTi__ + #define __INT_LEAST16_FMTi__ "i" + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 32767 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ int + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __INT_LEAST32_FMTd__ + #define __INT_LEAST32_FMTd__ "ld" + #undef __INT_LEAST32_FMTi__ + #define __INT_LEAST32_FMTi__ "li" + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 2147483647L + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ long int + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INT_LEAST64_FMTd__ + #define __INT_LEAST64_FMTd__ "lld" + #undef __INT_LEAST64_FMTi__ + #define __INT_LEAST64_FMTi__ "lli" + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 9223372036854775807LL + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long long int + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __INT_LEAST8_FMTd__ + #define __INT_LEAST8_FMTd__ "hhd" + #undef __INT_LEAST8_FMTi__ + #define __INT_LEAST8_FMTi__ "hhi" + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 127 + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __INT_MAX__ + #define __INT_MAX__ 32767 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 16 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 9 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 1.40129846e-45L + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 6 + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.19209290e-7L + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 24 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 38 + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 128 + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 3.40282347e+38L + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-37) + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-125) + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 1.17549435e-38L + #undef __LITTLE_ENDIAN__ + #define __LITTLE_ENDIAN__ 1 + #undef __LLONG_WIDTH__ + #define __LLONG_WIDTH__ 64 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 9223372036854775807LL + #undef __LONG_MAX__ + #define __LONG_MAX__ 2147483647L + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 32 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __OBJC_BOOL_IS_BOOL + #define __OBJC_BOOL_IS_BOOL 0 + #undef __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES + #define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3 + #undef __OPENCL_MEMORY_SCOPE_DEVICE + #define __OPENCL_MEMORY_SCOPE_DEVICE 2 + #undef __OPENCL_MEMORY_SCOPE_SUB_GROUP + #define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4 + #undef __OPENCL_MEMORY_SCOPE_WORK_GROUP + #define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 + #undef __OPENCL_MEMORY_SCOPE_WORK_ITEM + #define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __POINTER_WIDTH__ + #define __POINTER_WIDTH__ 16 + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __PTRDIFF_FMTd__ + #define __PTRDIFF_FMTd__ "d" + #undef __PTRDIFF_FMTi__ + #define __PTRDIFF_FMTi__ "i" + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 32767 + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ int + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 127 + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 32767 + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 127 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 8 + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 4 + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 2 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 4 + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 4 + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 2 + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 2 + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 2 + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 2 + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 2 + #undef __SIZE_FMTX__ + #define __SIZE_FMTX__ "X" + #undef __SIZE_FMTo__ + #define __SIZE_FMTo__ "o" + #undef __SIZE_FMTu__ + #define __SIZE_FMTu__ "u" + #undef __SIZE_FMTx__ + #define __SIZE_FMTx__ "x" + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 65535U + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ unsigned int + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 16 + #undef __UINT16_C_SUFFIX__ + #define __UINT16_C_SUFFIX__ U + #undef __UINT16_FMTX__ + #define __UINT16_FMTX__ "X" + #undef __UINT16_FMTo__ + #define __UINT16_FMTo__ "o" + #undef __UINT16_FMTu__ + #define __UINT16_FMTu__ "u" + #undef __UINT16_FMTx__ + #define __UINT16_FMTx__ "x" + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 65535U + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ unsigned int + #undef __UINT32_C_SUFFIX__ + #define __UINT32_C_SUFFIX__ UL + #undef __UINT32_FMTX__ + #define __UINT32_FMTX__ "lX" + #undef __UINT32_FMTo__ + #define __UINT32_FMTo__ "lo" + #undef __UINT32_FMTu__ + #define __UINT32_FMTu__ "lu" + #undef __UINT32_FMTx__ + #define __UINT32_FMTx__ "lx" + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 4294967295UL + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ long unsigned int + #undef __UINT64_C_SUFFIX__ + #define __UINT64_C_SUFFIX__ ULL + #undef __UINT64_FMTX__ + #define __UINT64_FMTX__ "llX" + #undef __UINT64_FMTo__ + #define __UINT64_FMTo__ "llo" + #undef __UINT64_FMTu__ + #define __UINT64_FMTu__ "llu" + #undef __UINT64_FMTx__ + #define __UINT64_FMTx__ "llx" + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 18446744073709551615ULL + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long long unsigned int + #undef __UINT8_C_SUFFIX__ + #define __UINT8_C_SUFFIX__ + #undef __UINT8_FMTX__ + #define __UINT8_FMTX__ "hhX" + #undef __UINT8_FMTo__ + #define __UINT8_FMTo__ "hho" + #undef __UINT8_FMTu__ + #define __UINT8_FMTu__ "hhu" + #undef __UINT8_FMTx__ + #define __UINT8_FMTx__ "hhx" + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 255 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __UINTMAX_C_SUFFIX__ + #define __UINTMAX_C_SUFFIX__ ULL + #undef __UINTMAX_FMTX__ + #define __UINTMAX_FMTX__ "llX" + #undef __UINTMAX_FMTo__ + #define __UINTMAX_FMTo__ "llo" + #undef __UINTMAX_FMTu__ + #define __UINTMAX_FMTu__ "llu" + #undef __UINTMAX_FMTx__ + #define __UINTMAX_FMTx__ "llx" + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 18446744073709551615ULL + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long long unsigned int + #undef __UINTMAX_WIDTH__ + #define __UINTMAX_WIDTH__ 64 + #undef __UINTPTR_FMTX__ + #define __UINTPTR_FMTX__ "X" + #undef __UINTPTR_FMTo__ + #define __UINTPTR_FMTo__ "o" + #undef __UINTPTR_FMTu__ + #define __UINTPTR_FMTu__ "u" + #undef __UINTPTR_FMTx__ + #define __UINTPTR_FMTx__ "x" + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 65535U + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ unsigned int + #undef __UINTPTR_WIDTH__ + #define __UINTPTR_WIDTH__ 16 + #undef __UINT_FAST16_FMTX__ + #define __UINT_FAST16_FMTX__ "X" + #undef __UINT_FAST16_FMTo__ + #define __UINT_FAST16_FMTo__ "o" + #undef __UINT_FAST16_FMTu__ + #define __UINT_FAST16_FMTu__ "u" + #undef __UINT_FAST16_FMTx__ + #define __UINT_FAST16_FMTx__ "x" + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 65535U + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ unsigned int + #undef __UINT_FAST32_FMTX__ + #define __UINT_FAST32_FMTX__ "lX" + #undef __UINT_FAST32_FMTo__ + #define __UINT_FAST32_FMTo__ "lo" + #undef __UINT_FAST32_FMTu__ + #define __UINT_FAST32_FMTu__ "lu" + #undef __UINT_FAST32_FMTx__ + #define __UINT_FAST32_FMTx__ "lx" + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 4294967295UL + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ long unsigned int + #undef __UINT_FAST64_FMTX__ + #define __UINT_FAST64_FMTX__ "llX" + #undef __UINT_FAST64_FMTo__ + #define __UINT_FAST64_FMTo__ "llo" + #undef __UINT_FAST64_FMTu__ + #define __UINT_FAST64_FMTu__ "llu" + #undef __UINT_FAST64_FMTx__ + #define __UINT_FAST64_FMTx__ "llx" + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 18446744073709551615ULL + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long long unsigned int + #undef __UINT_FAST8_FMTX__ + #define __UINT_FAST8_FMTX__ "hhX" + #undef __UINT_FAST8_FMTo__ + #define __UINT_FAST8_FMTo__ "hho" + #undef __UINT_FAST8_FMTu__ + #define __UINT_FAST8_FMTu__ "hhu" + #undef __UINT_FAST8_FMTx__ + #define __UINT_FAST8_FMTx__ "hhx" + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 255 + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __UINT_LEAST16_FMTX__ + #define __UINT_LEAST16_FMTX__ "X" + #undef __UINT_LEAST16_FMTo__ + #define __UINT_LEAST16_FMTo__ "o" + #undef __UINT_LEAST16_FMTu__ + #define __UINT_LEAST16_FMTu__ "u" + #undef __UINT_LEAST16_FMTx__ + #define __UINT_LEAST16_FMTx__ "x" + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 65535U + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ unsigned int + #undef __UINT_LEAST32_FMTX__ + #define __UINT_LEAST32_FMTX__ "lX" + #undef __UINT_LEAST32_FMTo__ + #define __UINT_LEAST32_FMTo__ "lo" + #undef __UINT_LEAST32_FMTu__ + #define __UINT_LEAST32_FMTu__ "lu" + #undef __UINT_LEAST32_FMTx__ + #define __UINT_LEAST32_FMTx__ "lx" + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 4294967295UL + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ long unsigned int + #undef __UINT_LEAST64_FMTX__ + #define __UINT_LEAST64_FMTX__ "llX" + #undef __UINT_LEAST64_FMTo__ + #define __UINT_LEAST64_FMTo__ "llo" + #undef __UINT_LEAST64_FMTu__ + #define __UINT_LEAST64_FMTu__ "llu" + #undef __UINT_LEAST64_FMTx__ + #define __UINT_LEAST64_FMTx__ "llx" + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 18446744073709551615ULL + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long long unsigned int + #undef __UINT_LEAST8_FMTX__ + #define __UINT_LEAST8_FMTX__ "hhX" + #undef __UINT_LEAST8_FMTo__ + #define __UINT_LEAST8_FMTo__ "hho" + #undef __UINT_LEAST8_FMTu__ + #define __UINT_LEAST8_FMTu__ "hhu" + #undef __UINT_LEAST8_FMTx__ + #define __UINT_LEAST8_FMTx__ "hhx" + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 255 + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __VERSION__ + #define __VERSION__ "Clang 15.0.7" + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 32767 + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ int + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 16 + #undef __WINT_MAX__ + #define __WINT_MAX__ 32767 + #undef __WINT_TYPE__ + #define __WINT_TYPE__ int + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 16 + #undef __clang__ + #define __clang__ 1 + #undef __clang_literal_encoding__ + #define __clang_literal_encoding__ "UTF-8" + #undef __clang_major__ + #define __clang_major__ 15 + #undef __clang_minor__ + #define __clang_minor__ 0 + #undef __clang_patchlevel__ + #define __clang_patchlevel__ 7 + #undef __clang_version__ + #define __clang_version__ "15.0.7 " + #undef __clang_wide_literal_encoding__ + #define __clang_wide_literal_encoding__ "UTF-16" + #undef __llvm__ + #define __llvm__ 1 +eof: (-1) +errno: + e2big: ((int)(66072050 & 0xffff)) + eacces: ((int)(66072050 & 0xffff)) + eaddrinuse: ((int)(66072050 & 0xffff)) + eaddrnotavail: ((int)(66072050 & 0xffff)) + eafnosupport: ((int)(66072050 & 0xffff)) + eagain: ((int)(66072050 & 0xffff)) + ealready: ((int)(66072050 & 0xffff)) + ebadf: ((int)(66072050 & 0xffff)) + ebusy: ((int)(66072050 & 0xffff)) + echild: ((int)(66072050 & 0xffff)) + econnaborted: ((int)(66072050 & 0xffff)) + econnrefused: ((int)(66072050 & 0xffff)) + econnreset: ((int)(66072050 & 0xffff)) + edeadlk: ((int)(66072050 & 0xffff)) + edestaddrreq: ((int)(66072050 & 0xffff)) + edom: '33' + eexist: ((int)(66072050 & 0xffff)) + efault: ((int)(66072050 & 0xffff)) + efbig: ((int)(66072050 & 0xffff)) + ehostunreach: ((int)(66072050 & 0xffff)) + eilseq: ((int)(66072050 & 0xffff)) + einprogress: ((int)(66072050 & 0xffff)) + eintr: ((int)(2453066 & 0x7fff)) + einval: ((int)(66072050 & 0xffff)) + eio: ((int)(66072050 & 0xffff)) + eisconn: ((int)(66072050 & 0xffff)) + eisdir: ((int)(66072050 & 0xffff)) + eloop: ((int)(66072050 & 0xffff)) + emfile: ((int)(66072050 & 0xffff)) + emlink: ((int)(66072050 & 0xffff)) + emsgsize: ((int)(66072050 & 0xffff)) + enametoolong: ((int)(66072050 & 0xffff)) + enetdown: ((int)(66072050 & 0xffff)) + enetreset: ((int)(66072050 & 0xffff)) + enetunreach: ((int)(66072050 & 0xffff)) + enfile: ((int)(66072050 & 0xffff)) + enobufs: ((int)(66072050 & 0xffff)) + enodev: ((int)(66072050 & 0xffff)) + enoent: ((int)(66072050 & 0xffff)) + enoexec: ((int)(66072050 & 0xffff)) + enolck: ((int)(66072050 & 0xffff)) + enomem: ((int)(66072050 & 0xffff)) + enomsg: ((int)(66072050 & 0xffff)) + enoprotoopt: ((int)(66072050 & 0xffff)) + enospc: ((int)(66072050 & 0xffff)) + enosys: ((int)(66081697 & 0x7fff)) + enotconn: ((int)(66072050 & 0xffff)) + enotdir: ((int)(66072050 & 0xffff)) + enotempty: ((int)(66072050 & 0xffff)) + enotsock: ((int)(66072050 & 0xffff)) + enotty: ((int)(66072050 & 0xffff)) + enxio: ((int)(66072050 & 0xffff)) + eopnotsupp: ((int)(66072050 & 0xffff)) + eperm: ((int)(66072050 & 0xffff)) + epipe: ((int)(66072050 & 0xffff)) + eprotonosupport: ((int)(66072050 & 0xffff)) + eprototype: ((int)(66072050 & 0xffff)) + erange: '34' + erofs: ((int)(66072050 & 0xffff)) + espipe: ((int)(66072050 & 0xffff)) + esrch: ((int)(66072050 & 0xffff)) + etimedout: ((int)(66072050 & 0xffff)) + ewouldblock: ((int)(66072050 & 0xffff)) + exdev: ((int)(66072050 & 0xffff)) +filename_max: '' +fopen_max: '' +has__builtin_va_list: true +host_name_max: '64' +int_fast16_t: int +int_fast32_t: long +int_fast64_t: long long +int_fast8_t: signed char +intptr_t: int +l_tmpnam: '' +little_endian: true +machdep_name: machdep_avr_8 +mb_cur_max: ((size_t)16) +nsig: '' +path_max: '4096' +posix_version: '' +ptrdiff_t: int +rand_max: '0x7FFF' +sig_atomic_t: '' +size_t: unsigned int +sizeof_double: 4 +sizeof_float: 4 +sizeof_fun: 1 +sizeof_int: 2 +sizeof_long: 4 +sizeof_longdouble: 4 +sizeof_longlong: 8 +sizeof_ptr: 2 +sizeof_short: 2 +sizeof_void: 1 +ssize_t: '' +time_t: unsigned long +tmp_max: '' +tty_name_max: '32' +uint_fast16_t: unsigned int +uint_fast32_t: unsigned long +uint_fast64_t: unsigned long long +uint_fast8_t: unsigned char +uintptr_t: unsigned int +version: clang version 15.0.7 +wchar_t: int +weof: (0xffffffffu) +wint_t: int +wordsize: '32' diff --git a/share/machdeps/machdep_gcc_x86_16.yaml b/share/machdeps/machdep_gcc_x86_16.yaml new file mode 100644 index 0000000000000000000000000000000000000000..87f4e68c223a9cdc2860fbc0b398b3c69d428327 --- /dev/null +++ b/share/machdeps/machdep_gcc_x86_16.yaml @@ -0,0 +1,928 @@ +alignof_aligned: 8 +alignof_double: 8 +alignof_float: 2 +alignof_fun: 1 +alignof_int: 2 +alignof_long: 4 +alignof_longdouble: 16 +alignof_longlong: 4 +alignof_ptr: 4 +alignof_short: 2 +alignof_str: 1 +char_is_unsigned: false +compiler: gcc +cpp_arch_flags: +- -m16 + +# adapted from the builtin macros of gcc_x86_32 +custom_defs: | + #undef __SSP_STRONG__ + #define __SSP_STRONG__ 3 + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-1021) + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 0xffff + #undef __FLT16_HAS_QUIET_NAN__ + #define __FLT16_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __FLT128_MAX_10_EXP__ + #define __FLT128_MAX_10_EXP__ 4932 + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F + #undef __GCC_IEC_559_COMPLEX + #define __GCC_IEC_559_COMPLEX 2 + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __SIZEOF_FLOAT80__ + #define __SIZEOF_FLOAT80__ 12 + #undef __INTMAX_C + #define __INTMAX_C(c) c ## LL + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 0xff + #undef __SCHAR_WIDTH__ + #define __SCHAR_WIDTH__ 8 + #undef __WINT_MAX__ + #define __WINT_MAX__ 0xffffffffU + #undef __FLT32_MIN_EXP__ + #define __FLT32_MIN_EXP__ (-125) + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 0xffffffffU + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 0x7fffffffL + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 + #undef __GCC_ATOMIC_CHAR_LOCK_FREE + #define __GCC_ATOMIC_CHAR_LOCK_FREE 2 + #undef __GCC_IEC_559 + #define __GCC_IEC_559 2 + #undef __FLT32X_DECIMAL_DIG__ + #define __FLT32X_DECIMAL_DIG__ 17 + #undef __FLT_EVAL_METHOD__ + #define __FLT_EVAL_METHOD__ 2 + #undef __FLT64_DECIMAL_DIG__ + #define __FLT64_DECIMAL_DIG__ 17 + #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL + #undef __SIG_ATOMIC_TYPE__ + #define __SIG_ATOMIC_TYPE__ int + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-307) + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT32X_MAX_EXP__ + #define __FLT32X_MAX_EXP__ 1024 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 + #undef __FLT32_HAS_DENORM__ + #define __FLT32_HAS_DENORM__ 1 + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 0xff + #undef __FLT32_MAX_10_EXP__ + #define __FLT32_MAX_10_EXP__ 38 + #undef __DEC64_MAX_EXP__ + #define __DEC64_MAX_EXP__ 385 + #undef __INT8_C + #define __INT8_C(c) c + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 0x7fff + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __FLT64X_MAX_10_EXP__ + #define __FLT64X_MAX_10_EXP__ 4932 + #undef __LDBL_IS_IEC_60559__ + #define __LDBL_IS_IEC_60559__ 2 + #undef __FLT64X_HAS_QUIET_NAN__ + #define __FLT64X_HAS_QUIET_NAN__ 1 + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 0xff + #undef __GCC_ATOMIC_BOOL_LOCK_FREE + #define __GCC_ATOMIC_BOOL_LOCK_FREE 2 + #undef __LAHF_SAHF__ + #define __LAHF_SAHF__ 1 + #undef __FLT128_DENORM_MIN__ + #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128 + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long long unsigned int + #undef __linux + #define __linux 1 + #undef __DEC32_EPSILON__ + #define __DEC32_EPSILON__ 1E-6DF + #undef __FLT_EVAL_METHOD_TS_18661_3__ + #define __FLT_EVAL_METHOD_TS_18661_3__ 2 + #undef __unix + #define __unix 1 + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 0xffffffffU + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) + #undef __FLT128_MIN_EXP__ + #define __FLT128_MIN_EXP__ (-16381) + #undef __WINT_MIN__ + #define __WINT_MIN__ 0U + #undef __FLT128_MIN_10_EXP__ + #define __FLT128_MIN_10_EXP__ (-4931) + #undef __FLT32X_IS_IEC_60559__ + #define __FLT32X_IS_IEC_60559__ 2 + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 0x7f + #undef __FLT128_MANT_DIG__ + #define __FLT128_MANT_DIG__ 113 + #undef __WCHAR_MIN__ + #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1) + #undef __INT64_C + #define __INT64_C(c) c ## LL + #undef __GCC_ATOMIC_POINTER_LOCK_FREE + #define __GCC_ATOMIC_POINTER_LOCK_FREE 2 + #undef __FLT32X_MANT_DIG__ + #define __FLT32X_MANT_DIG__ 53 + #undef __FLT64X_EPSILON__ + #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x + #undef __DEC64_MIN_EXP__ + #define __DEC64_MIN_EXP__ (-382) + #undef __DBL_DIG__ + #define __DBL_DIG__ 15 + #undef __FLT32_DIG__ + #define __FLT32_DIG__ 6 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __FLT32_IS_IEC_60559__ + #define __FLT32_IS_IEC_60559__ 2 + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L + #undef __DBL_IS_IEC_60559__ + #define __DBL_IS_IEC_60559__ 2 + #undef __DEC32_MAX__ + #define __DEC32_MAX__ 9.999999E96DF + #undef __FLT64X_DENORM_MIN__ + #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x + #undef __FLT32X_HAS_INFINITY__ + #define __FLT32X_HAS_INFINITY__ 1 + #undef __INT32_MAX__ + #define __INT32_MAX__ 0x7fffffff + #undef __FLT16_DIG__ + #define __FLT16_DIG__ 3 + #undef __unix__ + #define __unix__ 1 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 16 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 4 + #undef __UINT16_C + #define __UINT16_C(c) c + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ 21 + #undef __FLT64_EPSILON__ + #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64 + #undef __gnu_linux__ + #define __gnu_linux__ 1 + #undef __FLT128_IS_IEC_60559__ + #define __FLT128_IS_IEC_60559__ 2 + #undef __FLT64X_MIN_10_EXP__ + #define __FLT64X_MIN_10_EXP__ (-4931) + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __FLT16_MIN_EXP__ + #define __FLT16_MIN_EXP__ (-13) + #undef __FLT64_MANT_DIG__ + #define __FLT64_MANT_DIG__ 53 + #undef __FLT64X_MANT_DIG__ + #define __FLT64X_MANT_DIG__ 64 + #undef __GNUC__ + #define __GNUC__ 12 + #undef __pie__ + #define __pie__ 2 + #undef __MMX__ + #define __MMX__ 1 + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 12 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 16 + #undef __FLT64_MAX_10_EXP__ + #define __FLT64_MAX_10_EXP__ 308 + #undef __FLT16_MAX_10_EXP__ + #define __FLT16_MAX_10_EXP__ 4 + #undef __DBL_MAX__ + #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 0x7fffffff + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __HAVE_SPECULATION_SAFE_VALUE + #define __HAVE_SPECULATION_SAFE_VALUE 1 + #undef __DEC32_MIN_EXP__ + #define __DEC32_MIN_EXP__ (-94) + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 32 + #undef __FLT64X_HAS_INFINITY__ + #define __FLT64X_HAS_INFINITY__ 1 + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 0xffffffffU + #undef __FLT32X_HAS_DENORM__ + #define __FLT32X_HAS_DENORM__ 1 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ int + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __SEG_GS + #define __SEG_GS 1 + #undef __FLT128_HAS_INFINITY__ + #define __FLT128_HAS_INFINITY__ 1 + #undef __DEC32_MIN__ + #define __DEC32_MIN__ 1E-95DF + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 1024 + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 16 + #undef __FLT32_MAX__ + #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __DEC128_EPSILON__ + #define __DEC128_EPSILON__ 1E-33DL + #undef __FLT16_DECIMAL_DIG__ + #define __FLT16_DECIMAL_DIG__ 5 + #undef __ATOMIC_HLE_RELEASE + #define __ATOMIC_HLE_RELEASE 131072 + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 0x7fffffff + #undef __ATOMIC_HLE_ACQUIRE + #define __ATOMIC_HLE_ACQUIRE 65536 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 2 + #undef __FLT64X_MIN_EXP__ + #define __FLT64X_MIN_EXP__ (-16381) + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 4 + #undef __LONG_LONG_WIDTH__ + #define __LONG_LONG_WIDTH__ 64 + #undef __FLT32_MAX_EXP__ + #define __FLT32_MAX_EXP__ 128 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1017 + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __GCC_HAVE_DWARF2_CFI_ASM + #define __GCC_HAVE_DWARF2_CFI_ASM 1 + #undef __INT16_MAX__ + #define __INT16_MAX__ 0x7fff + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long long int + #undef __FLT64_DENORM_MIN__ + #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64 + #undef __DBL_MIN__ + #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) + #undef __FLT16_DENORM_MIN__ + #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16 + #undef __FLT128_EPSILON__ + #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128 + #undef __FLT64X_NORM_MAX__ + #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 4 + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __FLT32X_EPSILON__ + #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x + #undef __DECIMAL_BID_FORMAT__ + #define __DECIMAL_BID_FORMAT__ 1 + #undef __FLT64_MIN_EXP__ + #define __FLT64_MIN_EXP__ (-1021) + #undef __FLT64_MIN_10_EXP__ + #define __FLT64_MIN_10_EXP__ (-307) + #undef __FLT16_MIN_10_EXP__ + #define __FLT16_MIN_10_EXP__ (-4) + #undef __FLT64X_DECIMAL_DIG__ + #define __FLT64X_DECIMAL_DIG__ 21 + #undef __DEC128_MIN__ + #define __DEC128_MIN__ 1E-6143DL + #undef __REGISTER_PREFIX__ + #define __REGISTER_PREFIX__ + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 0xffff + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __FLT32_MIN__ + #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __DEC_EVAL_METHOD__ + #define __DEC_EVAL_METHOD__ 2 + #undef __DEC128_MAX__ + #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL + #undef __i386 + #define __i386 1 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 21 + #undef __VERSION__ + #define __VERSION__ "12.2.1 20230201" + #undef __UINT64_C + #define __UINT64_C(c) c ## ULL + #undef _STDC_PREDEF_H + #define _STDC_PREDEF_H 1 + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 0x7fffffff + #undef __GCC_ATOMIC_INT_LOCK_FREE + #define __GCC_ATOMIC_INT_LOCK_FREE 2 + #undef __FLT128_MAX_EXP__ + #define __FLT128_MAX_EXP__ 16384 + #undef __FLT32_MANT_DIG__ + #define __FLT32_MANT_DIG__ 24 + #undef __FLOAT_WORD_ORDER__ + #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __FLT32X_MIN_EXP__ + #define __FLT32X_MIN_EXP__ (-1021) + #undef i386 + #define i386 1 + #undef __FLT128_HAS_DENORM__ + #define __FLT128_HAS_DENORM__ 1 + #undef __FLT32_DECIMAL_DIG__ + #define __FLT32_DECIMAL_DIG__ 9 + #undef __FLT128_DIG__ + #define __FLT128_DIG__ 33 + #undef __INT32_C + #define __INT32_C(c) c ## L + #undef __DEC64_EPSILON__ + #define __DEC64_EPSILON__ 1E-15DD + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __DEC128_MIN_EXP__ + #define __DEC128_MIN_EXP__ (-6142) + #undef __code_model_32__ + #define __code_model_32__ 1 + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ long + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ short unsigned int + #undef unix + #define unix 1 + #undef __i386__ + #define __i386__ 1 + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ unsigned int + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 0xffffffffffffffffULL + #undef __FLT_IS_IEC_60559__ + #define __FLT_IS_IEC_60559__ 2 + #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME + #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE" + #undef __FLT64X_DIG__ + #define __FLT64X_DIG__ 18 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __ELF__ + #define __ELF__ 1 + #undef __GCC_ASM_FLAG_OUTPUTS__ + #define __GCC_ASM_FLAG_OUTPUTS__ 1 + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ unsigned long + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ short int + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L + #undef __UINTMAX_C + #define __UINTMAX_C(c) c ## ULL + #undef __k8 + #define __k8 1 + #undef __FLT32X_MIN__ + #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 0x7fffffff + #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE + #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 4 + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 18 + #undef __FLT64_IS_IEC_60559__ + #define __FLT64_IS_IEC_60559__ 2 + #undef __FLT16_IS_IEC_60559__ + #define __FLT16_IS_IEC_60559__ 2 + #undef __FLT16_MAX_EXP__ + #define __FLT16_MAX_EXP__ 16 + #undef __DEC32_SUBNORMAL_MIN__ + #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 0x7fffffff + #undef __GCC_CONSTRUCTIVE_SIZE + #define __GCC_CONSTRUCTIVE_SIZE 64 + #undef __FLT64_DIG__ + #define __FLT64_DIG__ 15 + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 0xffffffffU + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long long unsigned int + #undef __FLT16_EPSILON__ + #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16 + #undef __ILP32__ + #define __ILP32__ 1 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __LONG_MAX__ + #define __LONG_MAX__ 0x7fffffffL + #undef __FLT64X_HAS_DENORM__ + #define __FLT64X_HAS_DENORM__ 1 + #undef __DEC128_SUBNORMAL_MIN__ + #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __GNUC_EXECUTION_CHARSET_NAME + #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8" + #undef _ILP32 + #define _ILP32 1 + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ unsigned int + #undef __DEC64_MAX__ + #define __DEC64_MAX__ 9.999999999999999E384DD + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 32 + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ short unsigned int + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 32 + #undef __SEG_FS + #define __SEG_FS 1 + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 0x7fff + #undef __FLT16_NORM_MAX__ + #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __DEC64_MANT_DIG__ + #define __DEC64_MANT_DIG__ 16 + #undef __INT64_MAX__ + #define __INT64_MAX__ 0x7fffffffffffffffLL + #undef __FLT32_DENORM_MIN__ + #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 32 + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long long int + #undef __INT16_TYPE__ + #define __INT16_TYPE__ short int + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __FLT16_MAX__ + #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 4 + #undef __DEC32_MAX_EXP__ + #define __DEC32_MAX_EXP__ 97 + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 0x7f + #undef __FLT128_MAX__ + #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 0x7fffffff + #undef linux + #define linux 1 + #undef __FLT64_HAS_QUIET_NAN__ + #define __FLT64_HAS_QUIET_NAN__ 1 + #undef __FLT32_MIN_10_EXP__ + #define __FLT32_MIN_10_EXP__ (-37) + #undef __FLT32X_DIG__ + #define __FLT32X_DIG__ 15 + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 16 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 64 + #undef __FLT64_HAS_INFINITY__ + #define __FLT64_HAS_INFINITY__ 1 + #undef __FLT64X_MAX__ + #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __FLT16_HAS_INFINITY__ + #define __FLT16_HAS_INFINITY__ 1 + #undef __SIG_ATOMIC_MIN__ + #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) + #undef __GCC_ATOMIC_LONG_LOCK_FREE + #define __GCC_ATOMIC_LONG_LOCK_FREE 2 + #undef __DEC32_MANT_DIG__ + #define __DEC32_MANT_DIG__ 7 + #undef __FLT16_MANT_DIG__ + #define __FLT16_MANT_DIG__ 11 + #undef __k8__ + #define __k8__ 1 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ long + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ short unsigned int + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ int + #undef __pic__ + #define __pic__ 2 + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 0xffffffffU + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL + #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL + #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 + #undef __FLT_NORM_MAX__ + #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __FLT32_HAS_INFINITY__ + #define __FLT32_HAS_INFINITY__ 1 + #undef __FLT64X_MAX_EXP__ + #define __FLT64X_MAX_EXP__ 16384 + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long long unsigned int + #undef __INT_MAX__ + #define __INT_MAX__ 0x7fff + #undef __linux__ + #define __linux__ 1 + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long long int + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 53 + #undef __SIZEOF_FLOAT128__ + #define __SIZEOF_FLOAT128__ 16 + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL + #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 + #undef __DEC64_MIN__ + #define __DEC64_MIN__ 1E-383DD + #undef __WINT_TYPE__ + #define __WINT_TYPE__ unsigned long + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ unsigned long + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __FLT32_NORM_MAX__ + #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __SSE__ + #define __SSE__ 1 + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-16381) + #undef __FLT64_MAX__ + #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 32 + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 0x7f + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 16384 + #undef __FLT32X_MAX_10_EXP__ + #define __FLT32X_MAX_10_EXP__ 308 + #undef __FLT16_MIN__ + #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16 + #undef __FLT64X_IS_IEC_60559__ + #define __FLT64X_IS_IEC_60559__ 2 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 4932 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) + #undef __FLT128_MIN__ + #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128 + #undef __UINT8_C + #define __UINT8_C(c) c + #undef __FLT64_MAX_EXP__ + #define __FLT64_MAX_EXP__ 1024 + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ long + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 2 + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long long unsigned int + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __FLT128_NORM_MAX__ + #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __FLT64_NORM_MAX__ + #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __FLT128_HAS_QUIET_NAN__ + #define __FLT128_HAS_QUIET_NAN__ 1 + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 0x7fffffffffffffffLL + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __FLT64X_MIN__ + #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __FLT64_HAS_DENORM__ + #define __FLT64_HAS_DENORM__ 1 + #undef __FLT32_EPSILON__ + #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32 + #undef __FLT16_HAS_DENORM__ + #define __FLT16_HAS_DENORM__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 17 + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __FXSR__ + #define __FXSR__ 1 + #undef __FLT32X_MAX__ + #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __DBL_NORM_MAX__ + #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __GCC_DESTRUCTIVE_SIZE + #define __GCC_DESTRUCTIVE_SIZE 64 + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __UINT32_C + #define __UINT32_C(c) c ## UL + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F + #undef __INT8_MAX__ + #define __INT8_MAX__ 0x7f + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 32 + #undef __PIC__ + #define __PIC__ 2 + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ unsigned long + #undef __FLT32X_NORM_MAX__ + #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ unsigned long + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __SSE2__ + #define __SSE2__ 1 + #undef __INT32_TYPE__ + #define __INT32_TYPE__ long + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 8 + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT64_MIN__ + #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64 + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long long int + #undef __DEC128_MAX_EXP__ + #define __DEC128_MAX_EXP__ 6145 + #undef __FLT32X_HAS_QUIET_NAN__ + #define __FLT32X_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 2 + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 32 + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 0xffffffffffffffffULL + #undef __PIE__ + #define __PIE__ 2 + #undef __FLT32X_DENORM_MIN__ + #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 308 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L + #undef __INT16_C + #define __INT16_C(c) c + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ int + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __FLT32X_MIN_10_EXP__ + #define __FLT32X_MIN_10_EXP__ (-307) + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ unsigned int + #undef __DEC64_SUBNORMAL_MIN__ + #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD + #undef __DEC128_MANT_DIG__ + #define __DEC128_MANT_DIG__ 34 + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-4931) + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __FLT128_DECIMAL_DIG__ + #define __FLT128_DECIMAL_DIG__ 36 + #undef __GCC_ATOMIC_LLONG_LOCK_FREE + #define __GCC_ATOMIC_LLONG_LOCK_FREE 2 + #undef __FLT32_HAS_QUIET_NAN__ + #define __FLT32_HAS_QUIET_NAN__ 1 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 0xffffU + #undef __LDBL_NORM_MAX__ + #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __GCC_ATOMIC_SHORT_LOCK_FREE + #define __GCC_ATOMIC_SHORT_LOCK_FREE 2 + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 + +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotrecoverable: '131' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eownerdead: '130' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +has__builtin_va_list: true +int_fast8_t: signed char +int_fast16_t: signed int +int_fast32_t: long +int_fast64_t: long long +intptr_t: long +little_endian: true +nsig: '65' +ptrdiff_t: int +sig_atomic_t: int +size_t: unsigned int +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: 1 +sizeof_int: 2 +sizeof_long: 4 +sizeof_longdouble: 16 +sizeof_longlong: 8 +sizeof_ptr: 4 +sizeof_short: 2 +sizeof_void: 1 +ssize_t: int +time_t: long +uint_fast8_t: unsigned char +uint_fast16_t: unsigned int +uint_fast32_t: unsigned long +uint_fast64_t: unsigned long long +uintptr_t: unsigned long +version: none +wchar_t: int +weof: (0xffffffffUL) +wint_t: unsigned long +wordsize: '16' +posix_version: '200809L' +bufsiz: '8192' +eof: '(-1)' +fopen_max: '16' +filename_max: '2048' +path_max: '256' +host_name_max: '64' +tty_name_max: '32' +l_tmpnam: '2048' +tmp_max: '0xFFFFFFFF' +rand_max: '32767' +mb_cur_max: '((size_t)16)' +machdep_name: machdep_gcc_x86_16 diff --git a/share/machdeps/machdep_gcc_x86_32.yaml b/share/machdeps/machdep_gcc_x86_32.yaml new file mode 100644 index 0000000000000000000000000000000000000000..09ad500596d56e7f598c51c524221615a08a9a67 --- /dev/null +++ b/share/machdeps/machdep_gcc_x86_32.yaml @@ -0,0 +1,957 @@ +alignof_aligned: 16 +alignof_double: 4 +alignof_float: 4 +alignof_fun: 1 +alignof_int: 4 +alignof_long: 4 +alignof_longdouble: 4 +alignof_longlong: 4 +alignof_ptr: 4 +alignof_short: 2 +alignof_str: 1 +bufsiz: '8192' +char_is_unsigned: false +compiler: gcc +cpp_arch_flags: +- -m32 +custom_defs: | + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-1021) + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 0xffff + #undef __FLT16_HAS_QUIET_NAN__ + #define __FLT16_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __FLT128_MAX_10_EXP__ + #define __FLT128_MAX_10_EXP__ 4932 + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F + #undef __GCC_IEC_559_COMPLEX + #define __GCC_IEC_559_COMPLEX 2 + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __SIZEOF_FLOAT80__ + #define __SIZEOF_FLOAT80__ 12 + #undef __BFLT16_DENORM_MIN__ + #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16 + #undef __INTMAX_C + #define __INTMAX_C(c) c ## LL + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 0xff + #undef __SCHAR_WIDTH__ + #define __SCHAR_WIDTH__ 8 + #undef __WINT_MAX__ + #define __WINT_MAX__ 0xffffffffU + #undef __FLT32_MIN_EXP__ + #define __FLT32_MIN_EXP__ (-125) + #undef __BFLT16_NORM_MAX__ + #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_MIN_10_EXP__ + #define __BFLT16_MIN_10_EXP__ (-37) + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 0x7fffffffL + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 + #undef __GCC_ATOMIC_CHAR_LOCK_FREE + #define __GCC_ATOMIC_CHAR_LOCK_FREE 2 + #undef __GCC_IEC_559 + #define __GCC_IEC_559 2 + #undef __FLT32X_DECIMAL_DIG__ + #define __FLT32X_DECIMAL_DIG__ 17 + #undef __FLT_EVAL_METHOD__ + #define __FLT_EVAL_METHOD__ 2 + #undef __FLT64_DECIMAL_DIG__ + #define __FLT64_DECIMAL_DIG__ 17 + #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL + #undef __SIG_ATOMIC_TYPE__ + #define __SIG_ATOMIC_TYPE__ int + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-307) + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT32X_MAX_EXP__ + #define __FLT32X_MAX_EXP__ 1024 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 + #undef __FLT32_HAS_DENORM__ + #define __FLT32_HAS_DENORM__ 1 + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 0xff + #undef __FLT32_MAX_10_EXP__ + #define __FLT32_MAX_10_EXP__ 38 + #undef __DEC64_MAX_EXP__ + #define __DEC64_MAX_EXP__ 385 + #undef __INT8_C + #define __INT8_C(c) c + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 0x7fff + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __FLT64X_MAX_10_EXP__ + #define __FLT64X_MAX_10_EXP__ 4932 + #undef __BFLT16_MAX_10_EXP__ + #define __BFLT16_MAX_10_EXP__ 38 + #undef __BFLT16_MAX_EXP__ + #define __BFLT16_MAX_EXP__ 128 + #undef __LDBL_IS_IEC_60559__ + #define __LDBL_IS_IEC_60559__ 1 + #undef __FLT64X_HAS_QUIET_NAN__ + #define __FLT64X_HAS_QUIET_NAN__ 1 + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 0xff + #undef __GCC_ATOMIC_BOOL_LOCK_FREE + #define __GCC_ATOMIC_BOOL_LOCK_FREE 2 + #undef __LAHF_SAHF__ + #define __LAHF_SAHF__ 1 + #undef __FLT128_DENORM_MIN__ + #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128 + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long long unsigned int + #undef __BFLT16_DECIMAL_DIG__ + #define __BFLT16_DECIMAL_DIG__ 4 + #undef __linux + #define __linux 1 + #undef __DEC32_EPSILON__ + #define __DEC32_EPSILON__ 1E-6DF + #undef __FLT_EVAL_METHOD_TS_18661_3__ + #define __FLT_EVAL_METHOD_TS_18661_3__ 2 + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 0xffffffffU + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) + #undef __FLT128_MIN_EXP__ + #define __FLT128_MIN_EXP__ (-16381) + #undef __WINT_MIN__ + #define __WINT_MIN__ 0U + #undef __FLT128_MIN_10_EXP__ + #define __FLT128_MIN_10_EXP__ (-4931) + #undef __FLT32X_IS_IEC_60559__ + #define __FLT32X_IS_IEC_60559__ 1 + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 0x7f + #undef __FLT128_MANT_DIG__ + #define __FLT128_MANT_DIG__ 113 + #undef __WCHAR_MIN__ + #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1) + #undef __INT64_C + #define __INT64_C(c) c ## LL + #undef __SSP_STRONG__ + #define __SSP_STRONG__ 3 + #undef __GCC_ATOMIC_POINTER_LOCK_FREE + #define __GCC_ATOMIC_POINTER_LOCK_FREE 2 + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __unix + #define __unix 1 + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL + #undef __FLT32X_MANT_DIG__ + #define __FLT32X_MANT_DIG__ 53 + #undef __FLT64X_EPSILON__ + #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x + #undef __DEC64_MIN_EXP__ + #define __DEC64_MIN_EXP__ (-382) + #undef __DBL_DIG__ + #define __DBL_DIG__ 15 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __FLT32_IS_IEC_60559__ + #define __FLT32_IS_IEC_60559__ 1 + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L + #undef __DBL_IS_IEC_60559__ + #define __DBL_IS_IEC_60559__ 1 + #undef __DEC32_MAX__ + #define __DEC32_MAX__ 9.999999E96DF + #undef __FLT64X_DENORM_MIN__ + #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x + #undef __FLT32X_HAS_INFINITY__ + #define __FLT32X_HAS_INFINITY__ 1 + #undef __unix__ + #define __unix__ 1 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 32 + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ 21 + #undef __FLT64_EPSILON__ + #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64 + #undef __gnu_linux__ + #define __gnu_linux__ 1 + #undef __FLT128_IS_IEC_60559__ + #define __FLT128_IS_IEC_60559__ 1 + #undef __FLT64X_MIN_10_EXP__ + #define __FLT64X_MIN_10_EXP__ (-4931) + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __FLT16_MIN_EXP__ + #define __FLT16_MIN_EXP__ (-13) + #undef __FLT64_MANT_DIG__ + #define __FLT64_MANT_DIG__ 53 + #undef __FLT64X_MANT_DIG__ + #define __FLT64X_MANT_DIG__ 64 + #undef __BFLT16_DIG__ + #define __BFLT16_DIG__ 2 + #undef __GNUC__ + #define __GNUC__ 13 + #undef __pie__ + #define __pie__ 2 + #undef __MMX__ + #define __MMX__ 1 + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 12 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 16 + #undef __FLT64_MAX_10_EXP__ + #define __FLT64_MAX_10_EXP__ 308 + #undef __BFLT16_IS_IEC_60559__ + #define __BFLT16_IS_IEC_60559__ 0 + #undef __FLT16_MAX_10_EXP__ + #define __FLT16_MAX_10_EXP__ 4 + #undef __DBL_MAX__ + #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 0x7fffffff + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __INT64_MAX__ + #define __INT64_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __HAVE_SPECULATION_SAFE_VALUE + #define __HAVE_SPECULATION_SAFE_VALUE 1 + #undef __DEC32_MIN_EXP__ + #define __DEC32_MIN_EXP__ (-94) + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 32 + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 0xffffffffU + #undef __FLT32X_HAS_DENORM__ + #define __FLT32X_HAS_DENORM__ 1 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ int + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __SEG_GS + #define __SEG_GS 1 + #undef __BFLT16_EPSILON__ + #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16 + #undef __FLT128_HAS_INFINITY__ + #define __FLT128_HAS_INFINITY__ 1 + #undef __DEC32_MIN__ + #define __DEC32_MIN__ 1E-95DF + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 1024 + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 32 + #undef __FLT32_MAX__ + #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __DEC128_EPSILON__ + #define __DEC128_EPSILON__ 1E-33DL + #undef __FLT16_DECIMAL_DIG__ + #define __FLT16_DECIMAL_DIG__ 5 + #undef __ATOMIC_HLE_RELEASE + #define __ATOMIC_HLE_RELEASE 131072 + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 0x7fffffff + #undef __ATOMIC_HLE_ACQUIRE + #define __ATOMIC_HLE_ACQUIRE 65536 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 4 + #undef __BFLT16_HAS_INFINITY__ + #define __BFLT16_HAS_INFINITY__ 1 + #undef __FLT64X_MIN_EXP__ + #define __FLT64X_MIN_EXP__ (-16381) + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 4 + #undef __LONG_LONG_WIDTH__ + #define __LONG_LONG_WIDTH__ 64 + #undef __FLT32_MAX_EXP__ + #define __FLT32_MAX_EXP__ 128 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1018 + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __GCC_HAVE_DWARF2_CFI_ASM + #define __GCC_HAVE_DWARF2_CFI_ASM 1 + #undef __INT16_MAX__ + #define __INT16_MAX__ 0x7fff + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long long int + #undef __BFLT16_MAX__ + #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_HAS_DENORM__ + #define __BFLT16_HAS_DENORM__ 1 + #undef __FLT64_DENORM_MIN__ + #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64 + #undef __FLT16_DENORM_MIN__ + #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16 + #undef __FLT128_EPSILON__ + #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128 + #undef __FLT64X_NORM_MAX__ + #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 4 + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ unsigned int + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __FLT32X_EPSILON__ + #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 16384 + #undef __DECIMAL_BID_FORMAT__ + #define __DECIMAL_BID_FORMAT__ 1 + #undef __FLT64_MIN_EXP__ + #define __FLT64_MIN_EXP__ (-1021) + #undef __FLT64_MIN_10_EXP__ + #define __FLT64_MIN_10_EXP__ (-307) + #undef __FLT16_MIN_10_EXP__ + #define __FLT16_MIN_10_EXP__ (-4) + #undef __FLT64X_DECIMAL_DIG__ + #define __FLT64X_DECIMAL_DIG__ 21 + #undef __DEC128_MIN__ + #define __DEC128_MIN__ 1E-6143DL + #undef __REGISTER_PREFIX__ + #define __REGISTER_PREFIX__ + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 0xffff + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __FLT32_MIN__ + #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __DEC_EVAL_METHOD__ + #define __DEC_EVAL_METHOD__ 2 + #undef __i386 + #define __i386 1 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 21 + #undef __VERSION__ + #define __VERSION__ "13.1.1 20230429" + #undef __UINT64_C + #define __UINT64_C(c) c ## ULL + #undef _STDC_PREDEF_H + #define _STDC_PREDEF_H 1 + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 0x7fffffff + #undef __GCC_ATOMIC_INT_LOCK_FREE + #define __GCC_ATOMIC_INT_LOCK_FREE 2 + #undef __FLT128_MAX_EXP__ + #define __FLT128_MAX_EXP__ 16384 + #undef __FLT32_MANT_DIG__ + #define __FLT32_MANT_DIG__ 24 + #undef __FLOAT_WORD_ORDER__ + #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __FLT32X_MIN_EXP__ + #define __FLT32X_MIN_EXP__ (-1021) + #undef i386 + #define i386 1 + #undef __BFLT16_MIN__ + #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16 + #undef __FLT128_HAS_DENORM__ + #define __FLT128_HAS_DENORM__ 1 + #undef __FLT32_DECIMAL_DIG__ + #define __FLT32_DECIMAL_DIG__ 9 + #undef __FLT128_DIG__ + #define __FLT128_DIG__ 33 + #undef __INT32_C + #define __INT32_C(c) c + #undef __DEC64_EPSILON__ + #define __DEC64_EPSILON__ 1E-15DD + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __DEC128_MIN_EXP__ + #define __DEC128_MIN_EXP__ (-6142) + #undef __code_model_32__ + #define __code_model_32__ 1 + #undef __DEC128_MAX__ + #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ int + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ short unsigned int + #undef __DEC128_MAX_EXP__ + #define __DEC128_MAX_EXP__ 6145 + #undef unix + #define unix 1 + #undef __i386__ + #define __i386__ 1 + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 0xffffffffffffffffULL + #undef __FLT_IS_IEC_60559__ + #define __FLT_IS_IEC_60559__ 1 + #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME + #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE" + #undef __FLT64X_DIG__ + #define __FLT64X_DIG__ 18 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __ELF__ + #define __ELF__ 1 + #undef __GCC_ASM_FLAG_OUTPUTS__ + #define __GCC_ASM_FLAG_OUTPUTS__ 1 + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ unsigned int + #undef __BFLT16_HAS_QUIET_NAN__ + #define __BFLT16_HAS_QUIET_NAN__ 1 + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ short int + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L + #undef __UINTMAX_C + #define __UINTMAX_C(c) c ## ULL + #undef __FLT16_DIG__ + #define __FLT16_DIG__ 3 + #undef __k8 + #define __k8 1 + #undef __FLT32X_MIN__ + #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 0x7fffffff + #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE + #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 4 + #undef __FLT64X_HAS_INFINITY__ + #define __FLT64X_HAS_INFINITY__ 1 + #undef __FLT32_HAS_INFINITY__ + #define __FLT32_HAS_INFINITY__ 1 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 4 + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 18 + #undef __FLT64_IS_IEC_60559__ + #define __FLT64_IS_IEC_60559__ 1 + #undef __FLT16_IS_IEC_60559__ + #define __FLT16_IS_IEC_60559__ 1 + #undef __FLT16_MAX_EXP__ + #define __FLT16_MAX_EXP__ 16 + #undef __DEC32_SUBNORMAL_MIN__ + #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 0x7fffffff + #undef __GCC_CONSTRUCTIVE_SIZE + #define __GCC_CONSTRUCTIVE_SIZE 64 + #undef __FLT64_DIG__ + #define __FLT64_DIG__ 15 + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 0xffffffffU + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long long unsigned int + #undef __FLT16_EPSILON__ + #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16 + #undef __ILP32__ + #define __ILP32__ 1 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __LONG_MAX__ + #define __LONG_MAX__ 0x7fffffffL + #undef __FLT64X_HAS_DENORM__ + #define __FLT64X_HAS_DENORM__ 1 + #undef __DEC128_SUBNORMAL_MIN__ + #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __GNUC_EXECUTION_CHARSET_NAME + #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8" + #undef _ILP32 + #define _ILP32 1 + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ unsigned int + #undef __DEC64_MAX__ + #define __DEC64_MAX__ 9.999999999999999E384DD + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 32 + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ short unsigned int + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 32 + #undef __SEG_FS + #define __SEG_FS 1 + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 0x7fff + #undef __FLT16_NORM_MAX__ + #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __DEC64_MANT_DIG__ + #define __DEC64_MANT_DIG__ 16 + #undef __FLT32_DENORM_MIN__ + #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 32 + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long long int + #undef __INT16_TYPE__ + #define __INT16_TYPE__ short int + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __FLT16_MAX__ + #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __FLT128_MIN__ + #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 4 + #undef __DEC32_MAX_EXP__ + #define __DEC32_MAX_EXP__ 97 + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 0x7f + #undef __FLT128_MAX__ + #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 0x7fffffff + #undef linux + #define linux 1 + #undef __FLT64_HAS_QUIET_NAN__ + #define __FLT64_HAS_QUIET_NAN__ 1 + #undef __FLT32_MIN_10_EXP__ + #define __FLT32_MIN_10_EXP__ (-37) + #undef __FLT32X_DIG__ + #define __FLT32X_DIG__ 15 + #undef __UINT16_C + #define __UINT16_C(c) c + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 32 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 64 + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 32 + #undef __FLT64_HAS_INFINITY__ + #define __FLT64_HAS_INFINITY__ 1 + #undef __FLT64X_MAX__ + #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __FLT16_HAS_INFINITY__ + #define __FLT16_HAS_INFINITY__ 1 + #undef __SIG_ATOMIC_MIN__ + #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) + #undef __GCC_ATOMIC_LONG_LOCK_FREE + #define __GCC_ATOMIC_LONG_LOCK_FREE 2 + #undef __DEC32_MANT_DIG__ + #define __DEC32_MANT_DIG__ 7 + #undef __FLT16_MANT_DIG__ + #define __FLT16_MANT_DIG__ 11 + #undef __k8__ + #define __k8__ 1 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ int + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ short unsigned int + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ long int + #undef __pic__ + #define __pic__ 2 + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 0xffffffffU + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL + #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL + #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 + #undef __FLT_NORM_MAX__ + #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __FLT64X_MAX_EXP__ + #define __FLT64X_MAX_EXP__ 16384 + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long long unsigned int + #undef __BFLT16_MIN_EXP__ + #define __BFLT16_MIN_EXP__ (-125) + #undef __INT_MAX__ + #define __INT_MAX__ 0x7fffffff + #undef __linux__ + #define __linux__ 1 + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long long int + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 53 + #undef __SIZEOF_FLOAT128__ + #define __SIZEOF_FLOAT128__ 16 + #undef __BFLT16_MANT_DIG__ + #define __BFLT16_MANT_DIG__ 8 + #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 + #undef __DEC64_MIN__ + #define __DEC64_MIN__ 1E-383DD + #undef __WINT_TYPE__ + #define __WINT_TYPE__ unsigned int + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ unsigned int + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __FLT32_NORM_MAX__ + #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __SSE__ + #define __SSE__ 1 + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-16381) + #undef __FLT64_MAX__ + #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 32 + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 0x7f + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __FLT32X_MAX_10_EXP__ + #define __FLT32X_MAX_10_EXP__ 308 + #undef __FLT16_MIN__ + #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16 + #undef __FLT64X_IS_IEC_60559__ + #define __FLT64X_IS_IEC_60559__ 1 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 4932 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ int + #undef __UINT8_C + #define __UINT8_C(c) c + #undef __FLT64_MAX_EXP__ + #define __FLT64_MAX_EXP__ 1024 + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 4 + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long long unsigned int + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __FLT128_NORM_MAX__ + #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __FLT64_NORM_MAX__ + #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __FLT128_HAS_QUIET_NAN__ + #define __FLT128_HAS_QUIET_NAN__ 1 + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 0x7fffffffffffffffLL + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __FLT64X_MIN__ + #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __FLT64_HAS_DENORM__ + #define __FLT64_HAS_DENORM__ 1 + #undef __FLT32_EPSILON__ + #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32 + #undef __FLT16_HAS_DENORM__ + #define __FLT16_HAS_DENORM__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 17 + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __FXSR__ + #define __FXSR__ 1 + #undef __FLT32X_MAX__ + #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __DBL_NORM_MAX__ + #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __GCC_DESTRUCTIVE_SIZE + #define __GCC_DESTRUCTIVE_SIZE 64 + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __FLT32_DIG__ + #define __FLT32_DIG__ 6 + #undef __UINT32_C + #define __UINT32_C(c) c ## U + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F + #undef __INT8_MAX__ + #define __INT8_MAX__ 0x7f + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 32 + #undef __DBL_MIN__ + #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) + #undef __PIC__ + #define __PIC__ 2 + #undef __INT32_MAX__ + #define __INT32_MAX__ 0x7fffffff + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ unsigned int + #undef __FLT32X_NORM_MAX__ + #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ unsigned int + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __SSE2__ + #define __SSE2__ 1 + #undef __INT32_TYPE__ + #define __INT32_TYPE__ int + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 8 + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT64_MIN__ + #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64 + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long long int + #undef __FLT32X_HAS_QUIET_NAN__ + #define __FLT32X_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 1 + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 0xffffffffffffffffULL + #undef __PIE__ + #define __PIE__ 2 + #undef __FLT32X_DENORM_MIN__ + #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 308 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L + #undef __INT16_C + #define __INT16_C(c) c + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ int + #undef __FLT32X_MIN_10_EXP__ + #define __FLT32X_MIN_10_EXP__ (-307) + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ unsigned int + #undef __DEC64_SUBNORMAL_MIN__ + #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD + #undef __DEC128_MANT_DIG__ + #define __DEC128_MANT_DIG__ 34 + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-4931) + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __FLT128_DECIMAL_DIG__ + #define __FLT128_DECIMAL_DIG__ 36 + #undef __GCC_ATOMIC_LLONG_LOCK_FREE + #define __GCC_ATOMIC_LLONG_LOCK_FREE 2 + #undef __FLT32_HAS_QUIET_NAN__ + #define __FLT32_HAS_QUIET_NAN__ 1 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 0xffffffffU + #undef __LDBL_NORM_MAX__ + #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __GCC_ATOMIC_SHORT_LOCK_FREE + #define __GCC_ATOMIC_SHORT_LOCK_FREE 2 + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 0xffffffffU + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 +eof: (-1) +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotrecoverable: '131' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eownerdead: '130' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +filename_max: '4096' +fopen_max: '16' +has__builtin_va_list: true +host_name_max: '64' +int_fast16_t: int +int_fast32_t: int +int_fast64_t: long long +int_fast8_t: signed char +intptr_t: int +l_tmpnam: '20' +little_endian: true +machdep_name: machdep_gcc_x86_32 +mb_cur_max: ((size_t) 16 ) +nsig: (64 + 1) +path_max: '4096' +posix_version: 200809L +ptrdiff_t: int +rand_max: '2147483647' +sig_atomic_t: int +size_t: unsigned int +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: 1 +sizeof_int: 4 +sizeof_long: 4 +sizeof_longdouble: 12 +sizeof_longlong: 8 +sizeof_ptr: 4 +sizeof_short: 2 +sizeof_void: 1 +ssize_t: int +time_t: long +tmp_max: '238328' +tty_name_max: '32' +uint_fast16_t: unsigned int +uint_fast32_t: unsigned int +uint_fast64_t: unsigned long long +uint_fast8_t: unsigned char +uintptr_t: unsigned int +version: gcc (GCC) 13.1.1 20230429 +wchar_t: long +weof: (0xffffffffu) +wint_t: unsigned int +wordsize: '32' diff --git a/share/machdeps/machdep_gcc_x86_64.yaml b/share/machdeps/machdep_gcc_x86_64.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6c81caac58ab722684b40814e8d81381839cff2d --- /dev/null +++ b/share/machdeps/machdep_gcc_x86_64.yaml @@ -0,0 +1,965 @@ +alignof_aligned: 16 +alignof_double: 8 +alignof_float: 4 +alignof_fun: 1 +alignof_int: 4 +alignof_long: 8 +alignof_longdouble: 16 +alignof_longlong: 8 +alignof_ptr: 8 +alignof_short: 2 +alignof_str: 1 +bufsiz: '8192' +char_is_unsigned: false +compiler: gcc +cpp_arch_flags: +- -m64 +custom_defs: | + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-1021) + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 0xffff + #undef __FLT16_HAS_QUIET_NAN__ + #define __FLT16_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __FLT128_MAX_10_EXP__ + #define __FLT128_MAX_10_EXP__ 4932 + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F + #undef __GCC_IEC_559_COMPLEX + #define __GCC_IEC_559_COMPLEX 2 + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __SIZEOF_FLOAT80__ + #define __SIZEOF_FLOAT80__ 16 + #undef __BFLT16_DENORM_MIN__ + #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16 + #undef __INTMAX_C + #define __INTMAX_C(c) c ## L + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 0xff + #undef __SCHAR_WIDTH__ + #define __SCHAR_WIDTH__ 8 + #undef __WINT_MAX__ + #define __WINT_MAX__ 0xffffffffU + #undef __FLT32_MIN_EXP__ + #define __FLT32_MIN_EXP__ (-125) + #undef __BFLT16_NORM_MAX__ + #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_MIN_10_EXP__ + #define __BFLT16_MIN_10_EXP__ (-37) + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 0x7fffffff + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 + #undef __GCC_ATOMIC_CHAR_LOCK_FREE + #define __GCC_ATOMIC_CHAR_LOCK_FREE 2 + #undef __GCC_IEC_559 + #define __GCC_IEC_559 2 + #undef __FLT32X_DECIMAL_DIG__ + #define __FLT32X_DECIMAL_DIG__ 17 + #undef __FLT_EVAL_METHOD__ + #define __FLT_EVAL_METHOD__ 0 + #undef __FLT64_DECIMAL_DIG__ + #define __FLT64_DECIMAL_DIG__ 17 + #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 0xffffffffffffffffUL + #undef __SIG_ATOMIC_TYPE__ + #define __SIG_ATOMIC_TYPE__ int + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-307) + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT32X_MAX_EXP__ + #define __FLT32X_MAX_EXP__ 1024 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 + #undef __FLT32_HAS_DENORM__ + #define __FLT32_HAS_DENORM__ 1 + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 0xff + #undef __FLT32_MAX_10_EXP__ + #define __FLT32_MAX_10_EXP__ 38 + #undef __DEC64_MAX_EXP__ + #define __DEC64_MAX_EXP__ 385 + #undef __INT8_C + #define __INT8_C(c) c + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 0x7fff + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __FLT64X_MAX_10_EXP__ + #define __FLT64X_MAX_10_EXP__ 4932 + #undef __BFLT16_MAX_10_EXP__ + #define __BFLT16_MAX_10_EXP__ 38 + #undef __BFLT16_MAX_EXP__ + #define __BFLT16_MAX_EXP__ 128 + #undef __LDBL_IS_IEC_60559__ + #define __LDBL_IS_IEC_60559__ 1 + #undef __FLT64X_HAS_QUIET_NAN__ + #define __FLT64X_HAS_QUIET_NAN__ 1 + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 0xff + #undef __GCC_ATOMIC_BOOL_LOCK_FREE + #define __GCC_ATOMIC_BOOL_LOCK_FREE 2 + #undef __FLT128_DENORM_MIN__ + #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128 + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long unsigned int + #undef __BFLT16_DECIMAL_DIG__ + #define __BFLT16_DECIMAL_DIG__ 4 + #undef __linux + #define __linux 1 + #undef __DEC32_EPSILON__ + #define __DEC32_EPSILON__ 1E-6DF + #undef __FLT_EVAL_METHOD_TS_18661_3__ + #define __FLT_EVAL_METHOD_TS_18661_3__ 0 + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 0xffffffffU + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) + #undef __FLT128_MIN_EXP__ + #define __FLT128_MIN_EXP__ (-16381) + #undef __WINT_MIN__ + #define __WINT_MIN__ 0U + #undef __FLT128_MIN_10_EXP__ + #define __FLT128_MIN_10_EXP__ (-4931) + #undef __FLT32X_IS_IEC_60559__ + #define __FLT32X_IS_IEC_60559__ 1 + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 0x7f + #undef __FLT128_MANT_DIG__ + #define __FLT128_MANT_DIG__ 113 + #undef __WCHAR_MIN__ + #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1) + #undef __INT64_C + #define __INT64_C(c) c ## L + #undef __SSP_STRONG__ + #define __SSP_STRONG__ 3 + #undef __GCC_ATOMIC_POINTER_LOCK_FREE + #define __GCC_ATOMIC_POINTER_LOCK_FREE 2 + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __unix + #define __unix 1 + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 0x7fffffffffffffffL + #undef __FLT32X_MANT_DIG__ + #define __FLT32X_MANT_DIG__ 53 + #undef __FLT64X_EPSILON__ + #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x + #undef __DEC64_MIN_EXP__ + #define __DEC64_MIN_EXP__ (-382) + #undef __DBL_DIG__ + #define __DBL_DIG__ 15 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __FLT32_IS_IEC_60559__ + #define __FLT32_IS_IEC_60559__ 1 + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L + #undef __DBL_IS_IEC_60559__ + #define __DBL_IS_IEC_60559__ 1 + #undef __DEC32_MAX__ + #define __DEC32_MAX__ 9.999999E96DF + #undef __FLT64X_DENORM_MIN__ + #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x + #undef __FLT32X_HAS_INFINITY__ + #define __FLT32X_HAS_INFINITY__ 1 + #undef __unix__ + #define __unix__ 1 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 32 + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ 21 + #undef __FLT64_EPSILON__ + #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64 + #undef __gnu_linux__ + #define __gnu_linux__ 1 + #undef __FLT128_IS_IEC_60559__ + #define __FLT128_IS_IEC_60559__ 1 + #undef __FLT64X_MIN_10_EXP__ + #define __FLT64X_MIN_10_EXP__ (-4931) + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __FLT16_MIN_EXP__ + #define __FLT16_MIN_EXP__ (-13) + #undef __FLT64_MANT_DIG__ + #define __FLT64_MANT_DIG__ 53 + #undef __FLT64X_MANT_DIG__ + #define __FLT64X_MANT_DIG__ 64 + #undef __BFLT16_DIG__ + #define __BFLT16_DIG__ 2 + #undef __GNUC__ + #define __GNUC__ 13 + #undef __pie__ + #define __pie__ 2 + #undef __MMX__ + #define __MMX__ 1 + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 16 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 16 + #undef __FLT64_MAX_10_EXP__ + #define __FLT64_MAX_10_EXP__ 308 + #undef __BFLT16_IS_IEC_60559__ + #define __BFLT16_IS_IEC_60559__ 0 + #undef __FLT16_MAX_10_EXP__ + #define __FLT16_MAX_10_EXP__ 4 + #undef __DBL_MAX__ + #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 0x7fffffffffffffffL + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __INT64_MAX__ + #define __INT64_MAX__ 0x7fffffffffffffffL + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __HAVE_SPECULATION_SAFE_VALUE + #define __HAVE_SPECULATION_SAFE_VALUE 1 + #undef __DEC32_MIN_EXP__ + #define __DEC32_MIN_EXP__ (-94) + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 64 + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 0xffffffffU + #undef __FLT32X_HAS_DENORM__ + #define __FLT32X_HAS_DENORM__ 1 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ long int + #undef __MMX_WITH_SSE__ + #define __MMX_WITH_SSE__ 1 + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __SEG_GS + #define __SEG_GS 1 + #undef __BFLT16_EPSILON__ + #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16 + #undef __FLT128_HAS_INFINITY__ + #define __FLT128_HAS_INFINITY__ 1 + #undef __DEC32_MIN__ + #define __DEC32_MIN__ 1E-95DF + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 1024 + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 32 + #undef __FLT32_MAX__ + #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __DEC128_EPSILON__ + #define __DEC128_EPSILON__ 1E-33DL + #undef __FLT16_DECIMAL_DIG__ + #define __FLT16_DECIMAL_DIG__ 5 + #undef __SSE2_MATH__ + #define __SSE2_MATH__ 1 + #undef __ATOMIC_HLE_RELEASE + #define __ATOMIC_HLE_RELEASE 131072 + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 0x7fffffffffffffffL + #undef __amd64 + #define __amd64 1 + #undef __ATOMIC_HLE_ACQUIRE + #define __ATOMIC_HLE_ACQUIRE 65536 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 8 + #undef __BFLT16_HAS_INFINITY__ + #define __BFLT16_HAS_INFINITY__ 1 + #undef __FLT64X_MIN_EXP__ + #define __FLT64X_MIN_EXP__ (-16381) + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 4 + #undef __LONG_LONG_WIDTH__ + #define __LONG_LONG_WIDTH__ 64 + #undef __FLT32_MAX_EXP__ + #define __FLT32_MAX_EXP__ 128 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1018 + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __GCC_HAVE_DWARF2_CFI_ASM + #define __GCC_HAVE_DWARF2_CFI_ASM 1 + #undef __INT16_MAX__ + #define __INT16_MAX__ 0x7fff + #undef __x86_64 + #define __x86_64 1 + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long int + #undef __BFLT16_MAX__ + #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_HAS_DENORM__ + #define __BFLT16_HAS_DENORM__ 1 + #undef __FLT64_DENORM_MIN__ + #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64 + #undef __FLT16_DENORM_MIN__ + #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16 + #undef __FLT128_EPSILON__ + #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128 + #undef __FLT64X_NORM_MAX__ + #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 8 + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ long unsigned int + #undef __LP64__ + #define __LP64__ 1 + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __FLT32X_EPSILON__ + #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 16384 + #undef __DECIMAL_BID_FORMAT__ + #define __DECIMAL_BID_FORMAT__ 1 + #undef __FLT64_MIN_EXP__ + #define __FLT64_MIN_EXP__ (-1021) + #undef __FLT64_MIN_10_EXP__ + #define __FLT64_MIN_10_EXP__ (-307) + #undef __FLT16_MIN_10_EXP__ + #define __FLT16_MIN_10_EXP__ (-4) + #undef __FLT64X_DECIMAL_DIG__ + #define __FLT64X_DECIMAL_DIG__ 21 + #undef __DEC128_MIN__ + #define __DEC128_MIN__ 1E-6143DL + #undef __REGISTER_PREFIX__ + #define __REGISTER_PREFIX__ + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 0xffff + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __FLT32_MIN__ + #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __DEC_EVAL_METHOD__ + #define __DEC_EVAL_METHOD__ 2 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 21 + #undef __VERSION__ + #define __VERSION__ "13.1.1 20230429" + #undef __UINT64_C + #define __UINT64_C(c) c ## UL + #undef _STDC_PREDEF_H + #define _STDC_PREDEF_H 1 + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 0x7fffffff + #undef __GCC_ATOMIC_INT_LOCK_FREE + #define __GCC_ATOMIC_INT_LOCK_FREE 2 + #undef __FLT128_MAX_EXP__ + #define __FLT128_MAX_EXP__ 16384 + #undef __FLT32_MANT_DIG__ + #define __FLT32_MANT_DIG__ 24 + #undef __FLOAT_WORD_ORDER__ + #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __FLT32X_MIN_EXP__ + #define __FLT32X_MIN_EXP__ (-1021) + #undef __BFLT16_MIN__ + #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16 + #undef __FLT128_HAS_DENORM__ + #define __FLT128_HAS_DENORM__ 1 + #undef __FLT32_DECIMAL_DIG__ + #define __FLT32_DECIMAL_DIG__ 9 + #undef __FLT128_DIG__ + #define __FLT128_DIG__ 33 + #undef __INT32_C + #define __INT32_C(c) c + #undef __DEC64_EPSILON__ + #define __DEC64_EPSILON__ 1E-15DD + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __DEC128_MIN_EXP__ + #define __DEC128_MIN_EXP__ (-6142) + #undef __DEC128_MAX__ + #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ long int + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ short unsigned int + #undef __DEC128_MAX_EXP__ + #define __DEC128_MAX_EXP__ 6145 + #undef unix + #define unix 1 + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 0xffffffffffffffffUL + #undef __FLT_IS_IEC_60559__ + #define __FLT_IS_IEC_60559__ 1 + #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME + #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE" + #undef __FLT64X_DIG__ + #define __FLT64X_DIG__ 18 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __ELF__ + #define __ELF__ 1 + #undef __GCC_ASM_FLAG_OUTPUTS__ + #define __GCC_ASM_FLAG_OUTPUTS__ 1 + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ unsigned int + #undef __BFLT16_HAS_QUIET_NAN__ + #define __BFLT16_HAS_QUIET_NAN__ 1 + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ short int + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L + #undef __UINTMAX_C + #define __UINTMAX_C(c) c ## UL + #undef __FLT16_DIG__ + #define __FLT16_DIG__ 3 + #undef __SSE_MATH__ + #define __SSE_MATH__ 1 + #undef __k8 + #define __k8 1 + #undef __FLT32X_MIN__ + #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 0x7fffffff + #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE + #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 8 + #undef __FLT64X_HAS_INFINITY__ + #define __FLT64X_HAS_INFINITY__ 1 + #undef __FLT32_HAS_INFINITY__ + #define __FLT32_HAS_INFINITY__ 1 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 8 + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 18 + #undef __FLT64_IS_IEC_60559__ + #define __FLT64_IS_IEC_60559__ 1 + #undef __x86_64__ + #define __x86_64__ 1 + #undef __FLT16_IS_IEC_60559__ + #define __FLT16_IS_IEC_60559__ 1 + #undef __FLT16_MAX_EXP__ + #define __FLT16_MAX_EXP__ 16 + #undef __DEC32_SUBNORMAL_MIN__ + #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 0x7fffffffffffffffL + #undef __GCC_CONSTRUCTIVE_SIZE + #define __GCC_CONSTRUCTIVE_SIZE 64 + #undef __FLT64_DIG__ + #define __FLT64_DIG__ 15 + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 0xffffffffffffffffUL + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long unsigned int + #undef __FLT16_EPSILON__ + #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __LONG_MAX__ + #define __LONG_MAX__ 0x7fffffffffffffffL + #undef __FLT64X_HAS_DENORM__ + #define __FLT64X_HAS_DENORM__ 1 + #undef __DEC128_SUBNORMAL_MIN__ + #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __GNUC_EXECUTION_CHARSET_NAME + #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8" + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ long unsigned int + #undef __DEC64_MAX__ + #define __DEC64_MAX__ 9.999999999999999E384DD + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 64 + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ short unsigned int + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 64 + #undef __SEG_FS + #define __SEG_FS 1 + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 0x7fff + #undef __FLT16_NORM_MAX__ + #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __DEC64_MANT_DIG__ + #define __DEC64_MANT_DIG__ 16 + #undef __FLT32_DENORM_MIN__ + #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 32 + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long int + #undef __INT16_TYPE__ + #define __INT16_TYPE__ short int + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __FLT16_MAX__ + #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __FLT128_MIN__ + #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 4 + #undef __DEC32_MAX_EXP__ + #define __DEC32_MAX_EXP__ 97 + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 0x7f + #undef __FLT128_MAX__ + #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 0x7fffffffffffffffL + #undef linux + #define linux 1 + #undef __FLT64_HAS_QUIET_NAN__ + #define __FLT64_HAS_QUIET_NAN__ 1 + #undef __FLT32_MIN_10_EXP__ + #define __FLT32_MIN_10_EXP__ (-37) + #undef __FLT32X_DIG__ + #define __FLT32X_DIG__ 15 + #undef __UINT16_C + #define __UINT16_C(c) c + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 64 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 64 + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 64 + #undef __FLT64_HAS_INFINITY__ + #define __FLT64_HAS_INFINITY__ 1 + #undef __FLT64X_MAX__ + #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __FLT16_HAS_INFINITY__ + #define __FLT16_HAS_INFINITY__ 1 + #undef __SIG_ATOMIC_MIN__ + #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) + #undef __code_model_small__ + #define __code_model_small__ 1 + #undef __GCC_ATOMIC_LONG_LOCK_FREE + #define __GCC_ATOMIC_LONG_LOCK_FREE 2 + #undef __DEC32_MANT_DIG__ + #define __DEC32_MANT_DIG__ 7 + #undef __FLT16_MANT_DIG__ + #define __FLT16_MANT_DIG__ 11 + #undef __k8__ + #define __k8__ 1 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ long int + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ short unsigned int + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ int + #undef __pic__ + #define __pic__ 2 + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 0xffffffffffffffffUL + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 0x7fffffffffffffffL + #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL + #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 + #undef __FLT_NORM_MAX__ + #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __FLT64X_MAX_EXP__ + #define __FLT64X_MAX_EXP__ 16384 + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long unsigned int + #undef __BFLT16_MIN_EXP__ + #define __BFLT16_MIN_EXP__ (-125) + #undef __INT_MAX__ + #define __INT_MAX__ 0x7fffffff + #undef __linux__ + #define __linux__ 1 + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long int + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 53 + #undef __SIZEOF_FLOAT128__ + #define __SIZEOF_FLOAT128__ 16 + #undef __BFLT16_MANT_DIG__ + #define __BFLT16_MANT_DIG__ 8 + #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 + #undef __DEC64_MIN__ + #define __DEC64_MIN__ 1E-383DD + #undef __WINT_TYPE__ + #define __WINT_TYPE__ unsigned int + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ unsigned int + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __FLT32_NORM_MAX__ + #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __SSE__ + #define __SSE__ 1 + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-16381) + #undef __FLT64_MAX__ + #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __amd64__ + #define __amd64__ 1 + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 32 + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 0x7f + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __FLT32X_MAX_10_EXP__ + #define __FLT32X_MAX_10_EXP__ 308 + #undef __SIZEOF_INT128__ + #define __SIZEOF_INT128__ 16 + #undef __FLT16_MIN__ + #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16 + #undef __FLT64X_IS_IEC_60559__ + #define __FLT64X_IS_IEC_60559__ 1 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 4932 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ int + #undef _LP64 + #define _LP64 1 + #undef __UINT8_C + #define __UINT8_C(c) c + #undef __FLT64_MAX_EXP__ + #define __FLT64_MAX_EXP__ 1024 + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 4 + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long unsigned int + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __FLT128_NORM_MAX__ + #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __FLT64_NORM_MAX__ + #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __FLT128_HAS_QUIET_NAN__ + #define __FLT128_HAS_QUIET_NAN__ 1 + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 0x7fffffffffffffffL + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __FLT64X_MIN__ + #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __FLT64_HAS_DENORM__ + #define __FLT64_HAS_DENORM__ 1 + #undef __FLT32_EPSILON__ + #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32 + #undef __FLT16_HAS_DENORM__ + #define __FLT16_HAS_DENORM__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 17 + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __FXSR__ + #define __FXSR__ 1 + #undef __FLT32X_MAX__ + #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __DBL_NORM_MAX__ + #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __GCC_DESTRUCTIVE_SIZE + #define __GCC_DESTRUCTIVE_SIZE 64 + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __FLT32_DIG__ + #define __FLT32_DIG__ 6 + #undef __UINT32_C + #define __UINT32_C(c) c ## U + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F + #undef __INT8_MAX__ + #define __INT8_MAX__ 0x7f + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 64 + #undef __DBL_MIN__ + #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) + #undef __PIC__ + #define __PIC__ 2 + #undef __INT32_MAX__ + #define __INT32_MAX__ 0x7fffffff + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ long unsigned int + #undef __FLT32X_NORM_MAX__ + #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ unsigned int + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __SSE2__ + #define __SSE2__ 1 + #undef __INT32_TYPE__ + #define __INT32_TYPE__ int + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 8 + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT64_MIN__ + #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64 + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long int + #undef __FLT32X_HAS_QUIET_NAN__ + #define __FLT32X_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 1 + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 0xffffffffffffffffUL + #undef __PIE__ + #define __PIE__ 2 + #undef __FLT32X_DENORM_MIN__ + #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 308 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L + #undef __INT16_C + #define __INT16_C(c) c + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ long int + #undef __FLT32X_MIN_10_EXP__ + #define __FLT32X_MIN_10_EXP__ (-307) + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ long unsigned int + #undef __DEC64_SUBNORMAL_MIN__ + #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD + #undef __DEC128_MANT_DIG__ + #define __DEC128_MANT_DIG__ 34 + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-4931) + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __FLT128_DECIMAL_DIG__ + #define __FLT128_DECIMAL_DIG__ 36 + #undef __GCC_ATOMIC_LLONG_LOCK_FREE + #define __GCC_ATOMIC_LLONG_LOCK_FREE 2 + #undef __FLT32_HAS_QUIET_NAN__ + #define __FLT32_HAS_QUIET_NAN__ 1 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 0xffffffffffffffffUL + #undef __LDBL_NORM_MAX__ + #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __GCC_ATOMIC_SHORT_LOCK_FREE + #define __GCC_ATOMIC_SHORT_LOCK_FREE 2 + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 0xffffffffffffffffUL + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 +eof: (-1) +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotrecoverable: '131' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eownerdead: '130' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +filename_max: '4096' +fopen_max: '16' +has__builtin_va_list: true +host_name_max: '64' +int_fast16_t: long +int_fast32_t: long +int_fast64_t: long +int_fast8_t: signed char +intptr_t: long +l_tmpnam: '20' +little_endian: true +machdep_name: machdep_gcc_x86_64 +mb_cur_max: ((size_t) 16 ) +nsig: (64 + 1) +path_max: '4096' +posix_version: 200809L +ptrdiff_t: long +rand_max: '2147483647' +sig_atomic_t: int +size_t: unsigned long +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: 1 +sizeof_int: 4 +sizeof_long: 8 +sizeof_longdouble: 16 +sizeof_longlong: 8 +sizeof_ptr: 8 +sizeof_short: 2 +sizeof_void: 1 +ssize_t: long +time_t: long +tmp_max: '238328' +tty_name_max: '32' +uint_fast16_t: unsigned long +uint_fast32_t: unsigned long +uint_fast64_t: unsigned long +uint_fast8_t: unsigned char +uintptr_t: unsigned long +version: gcc (GCC) 13.1.1 20230429 +wchar_t: int +weof: (0xffffffffu) +wint_t: unsigned int +wordsize: '64' diff --git a/share/machdeps/machdep_msvc_x86_64.yaml b/share/machdeps/machdep_msvc_x86_64.yaml new file mode 100644 index 0000000000000000000000000000000000000000..59f2f5d98f1d29548c658c44e8c2403e5dda32a4 --- /dev/null +++ b/share/machdeps/machdep_msvc_x86_64.yaml @@ -0,0 +1,175 @@ +alignof_aligned: 1 +alignof_double: 8 +alignof_float: 4 +alignof_fun: -1 +alignof_int: 4 +alignof_long: 4 +alignof_longdouble: 8 +alignof_longlong: 8 +alignof_ptr: 8 +alignof_short: 2 +alignof_str: 1 +char_is_unsigned: false +compiler: msvc +cpp_arch_flags: +- -m64 +custom_defs: | + #define _MSC_FULL_VER 160040219 + #define _MSC_VER 1600 + #undef __ptr64 + #define __ptr64 + #undef __ptr32 + #define __ptr32 + #undef __unaligned + #define __unaligned + #undef __cdecl + #define __cdecl + #undef __possibly_notnullterminated + #define __possibly_notnullterminated + #ifndef errno_t + # define errno_t int + # define _ERRNO_T_DEFINED + #endif + #ifndef _WIN64 + # define _WIN64 1 + #endif + #ifndef _AMD64_ + # define _AMD64_ 1 + #endif + #ifndef _M_AMD64 + # define _M_AMD64 1 + #endif + #ifndef _M_X64 + # define _M_X64 1 + #endif + +errno: + eperm: '1' + enoent: '2' + esrch: '3' + eintr: '4' + eio: '5' + enxio: '6' + e2big: '7' + enoexec: '8' + ebadf: '9' + echild: '10' + eagain: '11' + enomem: '12' + eacces: '13' + efault: '14' + ebusy: '16' + eexist: '17' + exdev: '18' + enodev: '19' + enotdir: '20' + eisdir: '21' + einval: '22' + enfile: '23' + emfile: '24' + enotty: '25' + etxtbsy: '139' + efbig: '27' + enospc: '28' + espipe: '29' + erofs: '30' + emlink: '31' + epipe: '32' + edom: '33' + erange: '34' + edeadlk: '36' + enametoolong: '38' + enolck: '39' + enosys: '40' + enotempty: '41' + eloop: '114' + ewouldblock: '140' + enomsg: '122' + eidrm: '111' + edeadlock: '36' + enostr: '125' + enodata: '120' + etime: '137' + enosr: '124' + enolink: '121' + eproto: '134' + ebadmsg: '104' + eoverflow: '132' + eilseq: '42' + enotsock: '128' + edestaddrreq: '109' + emsgsize: '115' + eprototype: '136' + enoprotoopt: '123' + eprotonosupport: '135' + enotsup: '129' + eopnotsupp: '130' + eafnosupport: '102' + eaddrinuse: '100' + eaddrnotavail: '101' + enetdown: '116' + enetunreach: '118' + enetreset: '117' + econnaborted: '106' + econnreset: '108' + enobufs: '119' + eisconn: '113' + enotconn: '126' + etimedout: '138' + econnrefused: '107' + ehostunreach: '110' + ealready: '103' + einprogress: '112' + ecanceled: '105' + eownerdead: '133' + enotrecoverable: '127' +has__builtin_va_list: false +int_fast8_t: signed char +int_fast16_t: signed int +int_fast32_t: signed int +int_fast64_t: signed long long +intptr_t: signed long long +little_endian: true +nsig: '23' +ptrdiff_t: long long +# NB: wasn't defined at all in old __fc_machdep.h +sig_atomic_t: int +size_t: unsigned long long +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: -1 +sizeof_int: 4 +sizeof_long: 4 +sizeof_longdouble: 8 +sizeof_longlong: 8 +sizeof_ptr: 8 +sizeof_short: 2 +sizeof_void: 0 +ssize_t: long long +time_t: long long +uint_fast8_t: unsigned char +uint_fast16_t: unsigned int +uint_fast32_t: unsigned int +uint_fast64_t: unsigned long long +uintptr_t: unsigned long long +version: MSVC - X86-64bits mode +wchar_t: unsigned short +weof: (0xffffU) +wint_t: unsigned short +wordsize: '64' +posix_version: '' +# NB: except for l_tmpnam, the corresponding macro are not defined in the old +# __fc_machdep.h in the MSVC_X86_64 section. The values below have thus been +# taken from gnu +bufsiz: '8192' +eof: '(-1)' +fopen_max: '20' +host_name_max: '255' +path_max: '256' +tty_name_max: '32' +filename_max: '2048' +l_tmpnam: '20' +tmp_max: '0xFFFFFFFF' +rand_max: '32767' +mb_cur_max: '((size_t)16)' +machdep_name: machdep_msvc_x86_64 diff --git a/share/machdeps/machdep_ppc_32.yaml b/share/machdeps/machdep_ppc_32.yaml new file mode 100644 index 0000000000000000000000000000000000000000..58d1be5602866bb9938417137cb94df3ff5ed8f4 --- /dev/null +++ b/share/machdeps/machdep_ppc_32.yaml @@ -0,0 +1,1207 @@ +alignof_aligned: 16 +alignof_double: 8 +alignof_float: 4 +alignof_fun: 4 +alignof_int: 4 +alignof_long: 4 +alignof_longdouble: 16 +alignof_longlong: 8 +alignof_ptr: 4 +alignof_short: 2 +alignof_str: 1 +bufsiz: '8192' +char_is_unsigned: true +compiler: clang +cpp_arch_flags: +- -target +- powerpc-apple-linux +- -mcpu=603 +custom_defs: | + #undef _ARCH_603 + #define _ARCH_603 1 + #undef _ARCH_PPC + #define _ARCH_PPC 1 + #undef _ARCH_PPCGR + #define _ARCH_PPCGR 1 + #undef _BIG_ENDIAN + #define _BIG_ENDIAN 1 + #undef _ILP32 + #define _ILP32 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 16 + #undef __BIG_ENDIAN__ + #define __BIG_ENDIAN__ 1 + #undef __BITINT_MAXWIDTH__ + #define __BITINT_MAXWIDTH__ 128 + #undef __BOOL_WIDTH__ + #define __BOOL_WIDTH__ 8 + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ unsigned short + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ unsigned int + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __CHAR_UNSIGNED__ + #define __CHAR_UNSIGNED__ 1 + #undef __CLANG_ATOMIC_BOOL_LOCK_FREE + #define __CLANG_ATOMIC_BOOL_LOCK_FREE 2 + #undef __CLANG_ATOMIC_CHAR16_T_LOCK_FREE + #define __CLANG_ATOMIC_CHAR16_T_LOCK_FREE 2 + #undef __CLANG_ATOMIC_CHAR32_T_LOCK_FREE + #define __CLANG_ATOMIC_CHAR32_T_LOCK_FREE 2 + #undef __CLANG_ATOMIC_CHAR_LOCK_FREE + #define __CLANG_ATOMIC_CHAR_LOCK_FREE 2 + #undef __CLANG_ATOMIC_INT_LOCK_FREE + #define __CLANG_ATOMIC_INT_LOCK_FREE 2 + #undef __CLANG_ATOMIC_LLONG_LOCK_FREE + #define __CLANG_ATOMIC_LLONG_LOCK_FREE 1 + #undef __CLANG_ATOMIC_LONG_LOCK_FREE + #define __CLANG_ATOMIC_LONG_LOCK_FREE 2 + #undef __CLANG_ATOMIC_POINTER_LOCK_FREE + #define __CLANG_ATOMIC_POINTER_LOCK_FREE 2 + #undef __CLANG_ATOMIC_SHORT_LOCK_FREE + #define __CLANG_ATOMIC_SHORT_LOCK_FREE 2 + #undef __CLANG_ATOMIC_WCHAR_T_LOCK_FREE + #define __CLANG_ATOMIC_WCHAR_T_LOCK_FREE 2 + #undef __CONSTANT_CFSTRINGS__ + #define __CONSTANT_CFSTRINGS__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 17 + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ 4.9406564584124654e-324 + #undef __DBL_DIG__ + #define __DBL_DIG__ 15 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ 2.2204460492503131e-16 + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 53 + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 308 + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 1024 + #undef __DBL_MAX__ + #define __DBL_MAX__ 1.7976931348623157e+308 + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-307) + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-1021) + #undef __DBL_MIN__ + #define __DBL_MIN__ 2.2250738585072014e-308 + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__ + #undef __ELF__ + #define __ELF__ 1 + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846e-45F + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209290e-7F + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282347e+38F + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435e-38F + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __GCC_ATOMIC_BOOL_LOCK_FREE + #define __GCC_ATOMIC_BOOL_LOCK_FREE 2 + #undef __GCC_ATOMIC_CHAR16_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 + #undef __GCC_ATOMIC_CHAR32_T_LOCK_FREE + #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 + #undef __GCC_ATOMIC_CHAR_LOCK_FREE + #define __GCC_ATOMIC_CHAR_LOCK_FREE 2 + #undef __GCC_ATOMIC_INT_LOCK_FREE + #define __GCC_ATOMIC_INT_LOCK_FREE 2 + #undef __GCC_ATOMIC_LLONG_LOCK_FREE + #define __GCC_ATOMIC_LLONG_LOCK_FREE 1 + #undef __GCC_ATOMIC_LONG_LOCK_FREE + #define __GCC_ATOMIC_LONG_LOCK_FREE 2 + #undef __GCC_ATOMIC_POINTER_LOCK_FREE + #define __GCC_ATOMIC_POINTER_LOCK_FREE 2 + #undef __GCC_ATOMIC_SHORT_LOCK_FREE + #define __GCC_ATOMIC_SHORT_LOCK_FREE 2 + #undef __GCC_ATOMIC_TEST_AND_SET_TRUEVAL + #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1 + #undef __GCC_ATOMIC_WCHAR_T_LOCK_FREE + #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 + #undef __GCC_HAVE_DWARF2_CFI_ASM + #define __GCC_HAVE_DWARF2_CFI_ASM 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 + #undef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 2 + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __GNUC__ + #define __GNUC__ 4 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1002 + #undef __HAVE_BSWAP__ + #define __HAVE_BSWAP__ 1 + #undef __ILP32__ + #define __ILP32__ 1 + #undef __INT16_C_SUFFIX__ + #define __INT16_C_SUFFIX__ + #undef __INT16_FMTd__ + #define __INT16_FMTd__ "hd" + #undef __INT16_FMTi__ + #define __INT16_FMTi__ "hi" + #undef __INT16_MAX__ + #define __INT16_MAX__ 32767 + #undef __INT16_TYPE__ + #define __INT16_TYPE__ short + #undef __INT32_C_SUFFIX__ + #define __INT32_C_SUFFIX__ + #undef __INT32_FMTd__ + #define __INT32_FMTd__ "d" + #undef __INT32_FMTi__ + #define __INT32_FMTi__ "i" + #undef __INT32_MAX__ + #define __INT32_MAX__ 2147483647 + #undef __INT32_TYPE__ + #define __INT32_TYPE__ int + #undef __INT64_C_SUFFIX__ + #define __INT64_C_SUFFIX__ LL + #undef __INT64_FMTd__ + #define __INT64_FMTd__ "lld" + #undef __INT64_FMTi__ + #define __INT64_FMTi__ "lli" + #undef __INT64_MAX__ + #define __INT64_MAX__ 9223372036854775807LL + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long long int + #undef __INT8_C_SUFFIX__ + #define __INT8_C_SUFFIX__ + #undef __INT8_FMTd__ + #define __INT8_FMTd__ "hhd" + #undef __INT8_FMTi__ + #define __INT8_FMTi__ "hhi" + #undef __INT8_MAX__ + #define __INT8_MAX__ 127 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __INTMAX_C_SUFFIX__ + #define __INTMAX_C_SUFFIX__ LL + #undef __INTMAX_FMTd__ + #define __INTMAX_FMTd__ "lld" + #undef __INTMAX_FMTi__ + #define __INTMAX_FMTi__ "lli" + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 9223372036854775807LL + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long long int + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __INTPTR_FMTd__ + #define __INTPTR_FMTd__ "d" + #undef __INTPTR_FMTi__ + #define __INTPTR_FMTi__ "i" + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 2147483647 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ int + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 32 + #undef __INT_FAST16_FMTd__ + #define __INT_FAST16_FMTd__ "hd" + #undef __INT_FAST16_FMTi__ + #define __INT_FAST16_FMTi__ "hi" + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 32767 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ short + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 16 + #undef __INT_FAST32_FMTd__ + #define __INT_FAST32_FMTd__ "d" + #undef __INT_FAST32_FMTi__ + #define __INT_FAST32_FMTi__ "i" + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 2147483647 + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ int + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 32 + #undef __INT_FAST64_FMTd__ + #define __INT_FAST64_FMTd__ "lld" + #undef __INT_FAST64_FMTi__ + #define __INT_FAST64_FMTi__ "lli" + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 9223372036854775807LL + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long long int + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __INT_FAST8_FMTd__ + #define __INT_FAST8_FMTd__ "hhd" + #undef __INT_FAST8_FMTi__ + #define __INT_FAST8_FMTi__ "hhi" + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 127 + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __INT_LEAST16_FMTd__ + #define __INT_LEAST16_FMTd__ "hd" + #undef __INT_LEAST16_FMTi__ + #define __INT_LEAST16_FMTi__ "hi" + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 32767 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ short + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __INT_LEAST32_FMTd__ + #define __INT_LEAST32_FMTd__ "d" + #undef __INT_LEAST32_FMTi__ + #define __INT_LEAST32_FMTi__ "i" + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 2147483647 + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ int + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INT_LEAST64_FMTd__ + #define __INT_LEAST64_FMTd__ "lld" + #undef __INT_LEAST64_FMTi__ + #define __INT_LEAST64_FMTi__ "lli" + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 9223372036854775807LL + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long long int + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __INT_LEAST8_FMTd__ + #define __INT_LEAST8_FMTd__ "hhd" + #undef __INT_LEAST8_FMTi__ + #define __INT_LEAST8_FMTi__ "hhi" + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 127 + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __INT_MAX__ + #define __INT_MAX__ 2147483647 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 32 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 33 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 4.94065645841246544176568792868221e-324L + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 31 + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 4.94065645841246544176568792868221e-324L + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 106 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 308 + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 1024 + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 1.79769313486231580793728971405301e+308L + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-291) + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-968) + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 2.00416836000897277799610805135016e-292L + #undef __LLONG_WIDTH__ + #define __LLONG_WIDTH__ 64 + #undef __LONGDOUBLE128 + #define __LONGDOUBLE128 1 + #undef __LONG_DOUBLE_128__ + #define __LONG_DOUBLE_128__ 1 + #undef __LONG_DOUBLE_IBM128__ + #define __LONG_DOUBLE_IBM128__ 1 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 9223372036854775807LL + #undef __LONG_MAX__ + #define __LONG_MAX__ 2147483647L + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 32 + #undef __NATURAL_ALIGNMENT__ + #define __NATURAL_ALIGNMENT__ 1 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __OBJC_BOOL_IS_BOOL + #define __OBJC_BOOL_IS_BOOL 0 + #undef __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES + #define __OPENCL_MEMORY_SCOPE_ALL_SVM_DEVICES 3 + #undef __OPENCL_MEMORY_SCOPE_DEVICE + #define __OPENCL_MEMORY_SCOPE_DEVICE 2 + #undef __OPENCL_MEMORY_SCOPE_SUB_GROUP + #define __OPENCL_MEMORY_SCOPE_SUB_GROUP 4 + #undef __OPENCL_MEMORY_SCOPE_WORK_GROUP + #define __OPENCL_MEMORY_SCOPE_WORK_GROUP 1 + #undef __OPENCL_MEMORY_SCOPE_WORK_ITEM + #define __OPENCL_MEMORY_SCOPE_WORK_ITEM 0 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __PIC__ + #define __PIC__ 2 + #undef __PIE__ + #define __PIE__ 2 + #undef __POINTER_WIDTH__ + #define __POINTER_WIDTH__ 32 + #undef __POWERPC__ + #define __POWERPC__ 1 + #undef __PPC__ + #define __PPC__ 1 + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __PTRDIFF_FMTd__ + #define __PTRDIFF_FMTd__ "d" + #undef __PTRDIFF_FMTi__ + #define __PTRDIFF_FMTi__ "i" + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 2147483647 + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ int + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 32 + #undef __REGISTER_PREFIX__ + #define __REGISTER_PREFIX__ + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 127 + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 32767 + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 2147483647 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 32 + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 8 + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 4 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 16 + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 4 + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 4 + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 4 + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 4 + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 4 + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 4 + #undef __SIZE_FMTX__ + #define __SIZE_FMTX__ "X" + #undef __SIZE_FMTo__ + #define __SIZE_FMTo__ "o" + #undef __SIZE_FMTu__ + #define __SIZE_FMTu__ "u" + #undef __SIZE_FMTx__ + #define __SIZE_FMTx__ "x" + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 4294967295U + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ unsigned int + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 32 + #undef __SSP_STRONG__ + #define __SSP_STRONG__ 2 + #undef __UINT16_C_SUFFIX__ + #define __UINT16_C_SUFFIX__ + #undef __UINT16_FMTX__ + #define __UINT16_FMTX__ "hX" + #undef __UINT16_FMTo__ + #define __UINT16_FMTo__ "ho" + #undef __UINT16_FMTu__ + #define __UINT16_FMTu__ "hu" + #undef __UINT16_FMTx__ + #define __UINT16_FMTx__ "hx" + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 65535 + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ unsigned short + #undef __UINT32_C_SUFFIX__ + #define __UINT32_C_SUFFIX__ U + #undef __UINT32_FMTX__ + #define __UINT32_FMTX__ "X" + #undef __UINT32_FMTo__ + #define __UINT32_FMTo__ "o" + #undef __UINT32_FMTu__ + #define __UINT32_FMTu__ "u" + #undef __UINT32_FMTx__ + #define __UINT32_FMTx__ "x" + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 4294967295U + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ unsigned int + #undef __UINT64_C_SUFFIX__ + #define __UINT64_C_SUFFIX__ ULL + #undef __UINT64_FMTX__ + #define __UINT64_FMTX__ "llX" + #undef __UINT64_FMTo__ + #define __UINT64_FMTo__ "llo" + #undef __UINT64_FMTu__ + #define __UINT64_FMTu__ "llu" + #undef __UINT64_FMTx__ + #define __UINT64_FMTx__ "llx" + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 18446744073709551615ULL + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long long unsigned int + #undef __UINT8_C_SUFFIX__ + #define __UINT8_C_SUFFIX__ + #undef __UINT8_FMTX__ + #define __UINT8_FMTX__ "hhX" + #undef __UINT8_FMTo__ + #define __UINT8_FMTo__ "hho" + #undef __UINT8_FMTu__ + #define __UINT8_FMTu__ "hhu" + #undef __UINT8_FMTx__ + #define __UINT8_FMTx__ "hhx" + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 255 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __UINTMAX_C_SUFFIX__ + #define __UINTMAX_C_SUFFIX__ ULL + #undef __UINTMAX_FMTX__ + #define __UINTMAX_FMTX__ "llX" + #undef __UINTMAX_FMTo__ + #define __UINTMAX_FMTo__ "llo" + #undef __UINTMAX_FMTu__ + #define __UINTMAX_FMTu__ "llu" + #undef __UINTMAX_FMTx__ + #define __UINTMAX_FMTx__ "llx" + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 18446744073709551615ULL + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long long unsigned int + #undef __UINTMAX_WIDTH__ + #define __UINTMAX_WIDTH__ 64 + #undef __UINTPTR_FMTX__ + #define __UINTPTR_FMTX__ "X" + #undef __UINTPTR_FMTo__ + #define __UINTPTR_FMTo__ "o" + #undef __UINTPTR_FMTu__ + #define __UINTPTR_FMTu__ "u" + #undef __UINTPTR_FMTx__ + #define __UINTPTR_FMTx__ "x" + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 4294967295U + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ unsigned int + #undef __UINTPTR_WIDTH__ + #define __UINTPTR_WIDTH__ 32 + #undef __UINT_FAST16_FMTX__ + #define __UINT_FAST16_FMTX__ "hX" + #undef __UINT_FAST16_FMTo__ + #define __UINT_FAST16_FMTo__ "ho" + #undef __UINT_FAST16_FMTu__ + #define __UINT_FAST16_FMTu__ "hu" + #undef __UINT_FAST16_FMTx__ + #define __UINT_FAST16_FMTx__ "hx" + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 65535 + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ unsigned short + #undef __UINT_FAST32_FMTX__ + #define __UINT_FAST32_FMTX__ "X" + #undef __UINT_FAST32_FMTo__ + #define __UINT_FAST32_FMTo__ "o" + #undef __UINT_FAST32_FMTu__ + #define __UINT_FAST32_FMTu__ "u" + #undef __UINT_FAST32_FMTx__ + #define __UINT_FAST32_FMTx__ "x" + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 4294967295U + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ unsigned int + #undef __UINT_FAST64_FMTX__ + #define __UINT_FAST64_FMTX__ "llX" + #undef __UINT_FAST64_FMTo__ + #define __UINT_FAST64_FMTo__ "llo" + #undef __UINT_FAST64_FMTu__ + #define __UINT_FAST64_FMTu__ "llu" + #undef __UINT_FAST64_FMTx__ + #define __UINT_FAST64_FMTx__ "llx" + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 18446744073709551615ULL + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long long unsigned int + #undef __UINT_FAST8_FMTX__ + #define __UINT_FAST8_FMTX__ "hhX" + #undef __UINT_FAST8_FMTo__ + #define __UINT_FAST8_FMTo__ "hho" + #undef __UINT_FAST8_FMTu__ + #define __UINT_FAST8_FMTu__ "hhu" + #undef __UINT_FAST8_FMTx__ + #define __UINT_FAST8_FMTx__ "hhx" + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 255 + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __UINT_LEAST16_FMTX__ + #define __UINT_LEAST16_FMTX__ "hX" + #undef __UINT_LEAST16_FMTo__ + #define __UINT_LEAST16_FMTo__ "ho" + #undef __UINT_LEAST16_FMTu__ + #define __UINT_LEAST16_FMTu__ "hu" + #undef __UINT_LEAST16_FMTx__ + #define __UINT_LEAST16_FMTx__ "hx" + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 65535 + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ unsigned short + #undef __UINT_LEAST32_FMTX__ + #define __UINT_LEAST32_FMTX__ "X" + #undef __UINT_LEAST32_FMTo__ + #define __UINT_LEAST32_FMTo__ "o" + #undef __UINT_LEAST32_FMTu__ + #define __UINT_LEAST32_FMTu__ "u" + #undef __UINT_LEAST32_FMTx__ + #define __UINT_LEAST32_FMTx__ "x" + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 4294967295U + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ unsigned int + #undef __UINT_LEAST64_FMTX__ + #define __UINT_LEAST64_FMTX__ "llX" + #undef __UINT_LEAST64_FMTo__ + #define __UINT_LEAST64_FMTo__ "llo" + #undef __UINT_LEAST64_FMTu__ + #define __UINT_LEAST64_FMTu__ "llu" + #undef __UINT_LEAST64_FMTx__ + #define __UINT_LEAST64_FMTx__ "llx" + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 18446744073709551615ULL + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long long unsigned int + #undef __UINT_LEAST8_FMTX__ + #define __UINT_LEAST8_FMTX__ "hhX" + #undef __UINT_LEAST8_FMTo__ + #define __UINT_LEAST8_FMTo__ "hho" + #undef __UINT_LEAST8_FMTu__ + #define __UINT_LEAST8_FMTu__ "hhu" + #undef __UINT_LEAST8_FMTx__ + #define __UINT_LEAST8_FMTx__ "hhx" + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 255 + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __VERSION__ + #define __VERSION__ "Clang 15.0.7" + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 2147483647 + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ int + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 32 + #undef __WINT_MAX__ + #define __WINT_MAX__ 4294967295U + #undef __WINT_TYPE__ + #define __WINT_TYPE__ unsigned int + #undef __WINT_UNSIGNED__ + #define __WINT_UNSIGNED__ 1 + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 32 + #undef __abs + #define __abs __builtin_abs + #undef __addex + #define __addex __builtin_ppc_addex + #undef __alignx + #define __alignx __builtin_ppc_alignx + #undef __alloca + #define __alloca __builtin_alloca + #undef __bcopy + #define __bcopy bcopy + #undef __bpermd + #define __bpermd __builtin_bpermd + #undef __builtin_maxfe + #define __builtin_maxfe __builtin_ppc_maxfe + #undef __builtin_maxfl + #define __builtin_maxfl __builtin_ppc_maxfl + #undef __builtin_maxfs + #define __builtin_maxfs __builtin_ppc_maxfs + #undef __builtin_minfe + #define __builtin_minfe __builtin_ppc_minfe + #undef __builtin_minfl + #define __builtin_minfl __builtin_ppc_minfl + #undef __builtin_minfs + #define __builtin_minfs __builtin_ppc_minfs + #undef __clang__ + #define __clang__ 1 + #undef __clang_literal_encoding__ + #define __clang_literal_encoding__ "UTF-8" + #undef __clang_major__ + #define __clang_major__ 15 + #undef __clang_minor__ + #define __clang_minor__ 0 + #undef __clang_patchlevel__ + #define __clang_patchlevel__ 7 + #undef __clang_version__ + #define __clang_version__ "15.0.7 " + #undef __clang_wide_literal_encoding__ + #define __clang_wide_literal_encoding__ "UTF-32" + #undef __cmpb + #define __cmpb __builtin_ppc_cmpb + #undef __cmpeqb + #define __cmpeqb __builtin_ppc_cmpeqb + #undef __cmplx + #define __cmplx __builtin_complex + #undef __cmplxf + #define __cmplxf __builtin_complex + #undef __cmplxl + #define __cmplxl __builtin_complex + #undef __cmprb + #define __cmprb __builtin_ppc_cmprb + #undef __cntlz4 + #define __cntlz4 __builtin_clz + #undef __cntlz8 + #define __cntlz8 __builtin_clzll + #undef __cnttz4 + #define __cnttz4 __builtin_ctz + #undef __cnttz8 + #define __cnttz8 __builtin_ctzll + #undef __compare_and_swap + #define __compare_and_swap __builtin_ppc_compare_and_swap + #undef __compare_and_swaplp + #define __compare_and_swaplp __builtin_ppc_compare_and_swaplp + #undef __compare_exp_eq + #define __compare_exp_eq __builtin_ppc_compare_exp_eq + #undef __compare_exp_gt + #define __compare_exp_gt __builtin_ppc_compare_exp_gt + #undef __compare_exp_lt + #define __compare_exp_lt __builtin_ppc_compare_exp_lt + #undef __compare_exp_uo + #define __compare_exp_uo __builtin_ppc_compare_exp_uo + #undef __darn + #define __darn __builtin_darn + #undef __darn_32 + #define __darn_32 __builtin_darn_32 + #undef __darn_raw + #define __darn_raw __builtin_darn_raw + #undef __dcbf + #define __dcbf __builtin_dcbf + #undef __dcbfl + #define __dcbfl __builtin_ppc_dcbfl + #undef __dcbflp + #define __dcbflp __builtin_ppc_dcbflp + #undef __dcbst + #define __dcbst __builtin_ppc_dcbst + #undef __dcbt + #define __dcbt __builtin_ppc_dcbt + #undef __dcbtst + #define __dcbtst __builtin_ppc_dcbtst + #undef __dcbtstt + #define __dcbtstt __builtin_ppc_dcbtstt + #undef __dcbtt + #define __dcbtt __builtin_ppc_dcbtt + #undef __dcbz + #define __dcbz __builtin_ppc_dcbz + #undef __divde + #define __divde __builtin_divde + #undef __divdeu + #define __divdeu __builtin_divdeu + #undef __divwe + #define __divwe __builtin_divwe + #undef __divweu + #define __divweu __builtin_divweu + #undef __eieio + #define __eieio __builtin_ppc_eieio + #undef __extract_exp + #define __extract_exp __builtin_ppc_extract_exp + #undef __extract_sig + #define __extract_sig __builtin_ppc_extract_sig + #undef __fcfid + #define __fcfid __builtin_ppc_fcfid + #undef __fcfud + #define __fcfud __builtin_ppc_fcfud + #undef __fctid + #define __fctid __builtin_ppc_fctid + #undef __fctidz + #define __fctidz __builtin_ppc_fctidz + #undef __fctiw + #define __fctiw __builtin_ppc_fctiw + #undef __fctiwz + #define __fctiwz __builtin_ppc_fctiwz + #undef __fctudz + #define __fctudz __builtin_ppc_fctudz + #undef __fctuwz + #define __fctuwz __builtin_ppc_fctuwz + #undef __fetch_and_add + #define __fetch_and_add __builtin_ppc_fetch_and_add + #undef __fetch_and_addlp + #define __fetch_and_addlp __builtin_ppc_fetch_and_addlp + #undef __fetch_and_and + #define __fetch_and_and __builtin_ppc_fetch_and_and + #undef __fetch_and_andlp + #define __fetch_and_andlp __builtin_ppc_fetch_and_andlp + #undef __fetch_and_or + #define __fetch_and_or __builtin_ppc_fetch_and_or + #undef __fetch_and_orlp + #define __fetch_and_orlp __builtin_ppc_fetch_and_orlp + #undef __fetch_and_swap + #define __fetch_and_swap __builtin_ppc_fetch_and_swap + #undef __fetch_and_swaplp + #define __fetch_and_swaplp __builtin_ppc_fetch_and_swaplp + #undef __fmadd + #define __fmadd __builtin_fma + #undef __fmadds + #define __fmadds __builtin_fmaf + #undef __fmsub + #define __fmsub __builtin_ppc_fmsub + #undef __fmsubs + #define __fmsubs __builtin_ppc_fmsubs + #undef __fnabs + #define __fnabs __builtin_ppc_fnabs + #undef __fnabss + #define __fnabss __builtin_ppc_fnabss + #undef __fnmadd + #define __fnmadd __builtin_ppc_fnmadd + #undef __fnmadds + #define __fnmadds __builtin_ppc_fnmadds + #undef __fnmsub + #define __fnmsub __builtin_ppc_fnmsub + #undef __fnmsubs + #define __fnmsubs __builtin_ppc_fnmsubs + #undef __fre + #define __fre __builtin_ppc_fre + #undef __fres + #define __fres __builtin_ppc_fres + #undef __fric + #define __fric __builtin_ppc_fric + #undef __frim + #define __frim __builtin_ppc_frim + #undef __frims + #define __frims __builtin_ppc_frims + #undef __frin + #define __frin __builtin_ppc_frin + #undef __frins + #define __frins __builtin_ppc_frins + #undef __frip + #define __frip __builtin_ppc_frip + #undef __frips + #define __frips __builtin_ppc_frips + #undef __friz + #define __friz __builtin_ppc_friz + #undef __frizs + #define __frizs __builtin_ppc_frizs + #undef __frsqrte + #define __frsqrte __builtin_ppc_frsqrte + #undef __frsqrtes + #define __frsqrtes __builtin_ppc_frsqrtes + #undef __fsel + #define __fsel __builtin_ppc_fsel + #undef __fsels + #define __fsels __builtin_ppc_fsels + #undef __fsqrt + #define __fsqrt __builtin_ppc_fsqrt + #undef __fsqrts + #define __fsqrts __builtin_ppc_fsqrts + #undef __gnu_linux__ + #define __gnu_linux__ 1 + #undef __icbt + #define __icbt __builtin_ppc_icbt + #undef __insert_exp + #define __insert_exp __builtin_ppc_insert_exp + #undef __iospace_eieio + #define __iospace_eieio __builtin_ppc_iospace_eieio + #undef __iospace_lwsync + #define __iospace_lwsync __builtin_ppc_iospace_lwsync + #undef __iospace_sync + #define __iospace_sync __builtin_ppc_iospace_sync + #undef __isync + #define __isync __builtin_ppc_isync + #undef __labs + #define __labs __builtin_labs + #undef __lbarx + #define __lbarx __builtin_ppc_lbarx + #undef __ldarx + #define __ldarx __builtin_ppc_ldarx + #undef __lharx + #define __lharx __builtin_ppc_lharx + #undef __linux + #define __linux 1 + #undef __linux__ + #define __linux__ 1 + #undef __llabs + #define __llabs __builtin_llabs + #undef __llvm__ + #define __llvm__ 1 + #undef __load2r + #define __load2r __builtin_ppc_load2r + #undef __load4r + #define __load4r __builtin_ppc_load4r + #undef __load8r + #define __load8r __builtin_ppc_load8r + #undef __lwarx + #define __lwarx __builtin_ppc_lwarx + #undef __lwsync + #define __lwsync __builtin_ppc_lwsync + #undef __maddhd + #define __maddhd __builtin_ppc_maddhd + #undef __maddhdu + #define __maddhdu __builtin_ppc_maddhdu + #undef __maddld + #define __maddld __builtin_ppc_maddld + #undef __mfmsr + #define __mfmsr __builtin_ppc_mfmsr + #undef __mfspr + #define __mfspr __builtin_ppc_mfspr + #undef __mftbu + #define __mftbu __builtin_ppc_mftbu + #undef __mtfsb0 + #define __mtfsb0 __builtin_ppc_mtfsb0 + #undef __mtfsb1 + #define __mtfsb1 __builtin_ppc_mtfsb1 + #undef __mtfsf + #define __mtfsf __builtin_ppc_mtfsf + #undef __mtfsfi + #define __mtfsfi __builtin_ppc_mtfsfi + #undef __mtmsr + #define __mtmsr __builtin_ppc_mtmsr + #undef __mtspr + #define __mtspr __builtin_ppc_mtspr + #undef __mulhd + #define __mulhd __builtin_ppc_mulhd + #undef __mulhdu + #define __mulhdu __builtin_ppc_mulhdu + #undef __mulhw + #define __mulhw __builtin_ppc_mulhw + #undef __mulhwu + #define __mulhwu __builtin_ppc_mulhwu + #undef __pic__ + #define __pic__ 2 + #undef __pie__ + #define __pie__ 2 + #undef __popcnt4 + #define __popcnt4 __builtin_popcount + #undef __popcnt8 + #define __popcnt8 __builtin_popcountll + #undef __popcntb + #define __popcntb __builtin_ppc_popcntb + #undef __poppar4 + #define __poppar4 __builtin_ppc_poppar4 + #undef __poppar8 + #define __poppar8 __builtin_ppc_poppar8 + #undef __powerpc__ + #define __powerpc__ 1 + #undef __ppc__ + #define __ppc__ 1 + #undef __rdlam + #define __rdlam __builtin_ppc_rdlam + #undef __readflm + #define __readflm __builtin_readflm + #undef __rldimi + #define __rldimi __builtin_ppc_rldimi + #undef __rlwimi + #define __rlwimi __builtin_ppc_rlwimi + #undef __rlwnm + #define __rlwnm __builtin_ppc_rlwnm + #undef __rotatel4 + #define __rotatel4 __builtin_rotateleft32 + #undef __rotatel8 + #define __rotatel8 __builtin_rotateleft64 + #undef __setb + #define __setb __builtin_ppc_setb + #undef __setflm + #define __setflm __builtin_setflm + #undef __setrnd + #define __setrnd __builtin_setrnd + #undef __stbcx + #define __stbcx __builtin_ppc_stbcx + #undef __stdcx + #define __stdcx __builtin_ppc_stdcx + #undef __stfiw + #define __stfiw __builtin_ppc_stfiw + #undef __sthcx + #define __sthcx __builtin_ppc_sthcx + #undef __store2r + #define __store2r __builtin_ppc_store2r + #undef __store4r + #define __store4r __builtin_ppc_store4r + #undef __store8r + #define __store8r __builtin_ppc_store8r + #undef __stwcx + #define __stwcx __builtin_ppc_stwcx + #undef __swdiv + #define __swdiv __builtin_ppc_swdiv + #undef __swdiv_nochk + #define __swdiv_nochk __builtin_ppc_swdiv_nochk + #undef __swdivs + #define __swdivs __builtin_ppc_swdivs + #undef __swdivs_nochk + #define __swdivs_nochk __builtin_ppc_swdivs_nochk + #undef __sync + #define __sync __builtin_ppc_sync + #undef __tdw + #define __tdw __builtin_ppc_tdw + #undef __test_data_class + #define __test_data_class __builtin_ppc_test_data_class + #undef __trap + #define __trap __builtin_ppc_trap + #undef __trapd + #define __trapd __builtin_ppc_trapd + #undef __tw + #define __tw __builtin_ppc_tw + #undef __unix + #define __unix 1 + #undef __unix__ + #define __unix__ 1 + #undef __vcipher + #define __vcipher __builtin_altivec_crypto_vcipher + #undef __vcipherlast + #define __vcipherlast __builtin_altivec_crypto_vcipherlast + #undef __vncipher + #define __vncipher __builtin_altivec_crypto_vncipher + #undef __vncipherlast + #define __vncipherlast __builtin_altivec_crypto_vncipherlast + #undef __vpermxor + #define __vpermxor __builtin_altivec_crypto_vpermxor + #undef __vpmsumb + #define __vpmsumb __builtin_altivec_crypto_vpmsumb + #undef __vpmsumd + #define __vpmsumd __builtin_altivec_crypto_vpmsumd + #undef __vpmsumh + #define __vpmsumh __builtin_altivec_crypto_vpmsumh + #undef __vpmsumw + #define __vpmsumw __builtin_altivec_crypto_vpmsumw + #undef linux + #define linux 1 + #undef unix + #define unix 1 +eof: (-1) +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotrecoverable: '131' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eownerdead: '130' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +filename_max: '4096' +fopen_max: '16' +has__builtin_va_list: true +host_name_max: '64' +int_fast16_t: int +int_fast32_t: int +int_fast64_t: long long +int_fast8_t: signed char +intptr_t: int +l_tmpnam: '20' +little_endian: false +machdep_name: machdep_ppc_32 +mb_cur_max: ((size_t)16) +nsig: (64 + 1) +path_max: '4096' +posix_version: 200809L +ptrdiff_t: int +rand_max: '2147483647' +sig_atomic_t: int +size_t: unsigned int +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: 1 +sizeof_int: 4 +sizeof_long: 4 +sizeof_longdouble: 16 +sizeof_longlong: 8 +sizeof_ptr: 4 +sizeof_short: 2 +sizeof_void: 1 +ssize_t: int +time_t: long +tmp_max: '238328' +tty_name_max: '32' +uint_fast16_t: unsigned int +uint_fast32_t: unsigned int +uint_fast64_t: unsigned long long +uint_fast8_t: unsigned char +uintptr_t: unsigned int +version: clang version 15.0.7 +wchar_t: int +weof: (0xffffffffu) +wint_t: unsigned int +wordsize: '32' diff --git a/share/machdeps/machdep_x86_16.yaml b/share/machdeps/machdep_x86_16.yaml new file mode 100644 index 0000000000000000000000000000000000000000..70f9b4bae3ca3d9ef817a5e5b66821de0120e44a --- /dev/null +++ b/share/machdeps/machdep_x86_16.yaml @@ -0,0 +1,886 @@ +alignof_aligned: 8 +alignof_double: 8 +alignof_float: 2 +alignof_fun: -1 +alignof_int: 2 +alignof_long: 4 +alignof_longdouble: 16 +alignof_longlong: 4 +alignof_ptr: 4 +alignof_short: 2 +alignof_str: 1 +char_is_unsigned: false +compiler: generic +cpp_arch_flags: +- -m16 + +# adapted from the builtin macros of gcc_x86_32 +custom_defs: | + #undef __SSP_STRONG__ + #define __SSP_STRONG__ 3 + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-1021) + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 0xffff + #undef __FLT16_HAS_QUIET_NAN__ + #define __FLT16_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __FLT128_MAX_10_EXP__ + #define __FLT128_MAX_10_EXP__ 4932 + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __SIZEOF_FLOAT80__ + #define __SIZEOF_FLOAT80__ 12 + #undef __INTMAX_C + #define __INTMAX_C(c) c ## LL + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 0xff + #undef __SCHAR_WIDTH__ + #define __SCHAR_WIDTH__ 8 + #undef __WINT_MAX__ + #define __WINT_MAX__ 0xffffffffU + #undef __FLT32_MIN_EXP__ + #define __FLT32_MIN_EXP__ (-125) + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 0xffffffffU + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 0x7fffffffL + #undef __FLT32X_DECIMAL_DIG__ + #define __FLT32X_DECIMAL_DIG__ 17 + #undef __FLT_EVAL_METHOD__ + #define __FLT_EVAL_METHOD__ 2 + #undef __FLT64_DECIMAL_DIG__ + #define __FLT64_DECIMAL_DIG__ 17 + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL + #undef __SIG_ATOMIC_TYPE__ + #define __SIG_ATOMIC_TYPE__ int + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-307) + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT32X_MAX_EXP__ + #define __FLT32X_MAX_EXP__ 1024 + #undef __FLT32_HAS_DENORM__ + #define __FLT32_HAS_DENORM__ 1 + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 0xff + #undef __FLT32_MAX_10_EXP__ + #define __FLT32_MAX_10_EXP__ 38 + #undef __DEC64_MAX_EXP__ + #define __DEC64_MAX_EXP__ 385 + #undef __INT8_C + #define __INT8_C(c) c + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 0x7fff + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __FLT64X_MAX_10_EXP__ + #define __FLT64X_MAX_10_EXP__ 4932 + #undef __LDBL_IS_IEC_60559__ + #define __LDBL_IS_IEC_60559__ 2 + #undef __FLT64X_HAS_QUIET_NAN__ + #define __FLT64X_HAS_QUIET_NAN__ 1 + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 0xff + #undef __LAHF_SAHF__ + #define __LAHF_SAHF__ 1 + #undef __FLT128_DENORM_MIN__ + #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128 + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long long unsigned int + #undef __linux + #define __linux 1 + #undef __DEC32_EPSILON__ + #define __DEC32_EPSILON__ 1E-6DF + #undef __FLT_EVAL_METHOD_TS_18661_3__ + #define __FLT_EVAL_METHOD_TS_18661_3__ 2 + #undef __unix + #define __unix 1 + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 0xffffffffU + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) + #undef __FLT128_MIN_EXP__ + #define __FLT128_MIN_EXP__ (-16381) + #undef __WINT_MIN__ + #define __WINT_MIN__ 0U + #undef __FLT128_MIN_10_EXP__ + #define __FLT128_MIN_10_EXP__ (-4931) + #undef __FLT32X_IS_IEC_60559__ + #define __FLT32X_IS_IEC_60559__ 2 + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 0x7f + #undef __FLT128_MANT_DIG__ + #define __FLT128_MANT_DIG__ 113 + #undef __WCHAR_MIN__ + #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1) + #undef __INT64_C + #define __INT64_C(c) c ## LL + #undef __FLT32X_MANT_DIG__ + #define __FLT32X_MANT_DIG__ 53 + #undef __FLT64X_EPSILON__ + #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x + #undef __DEC64_MIN_EXP__ + #define __DEC64_MIN_EXP__ (-382) + #undef __DBL_DIG__ + #define __DBL_DIG__ 15 + #undef __FLT32_DIG__ + #define __FLT32_DIG__ 6 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __FLT32_IS_IEC_60559__ + #define __FLT32_IS_IEC_60559__ 2 + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L + #undef __DBL_IS_IEC_60559__ + #define __DBL_IS_IEC_60559__ 2 + #undef __DEC32_MAX__ + #define __DEC32_MAX__ 9.999999E96DF + #undef __FLT64X_DENORM_MIN__ + #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x + #undef __FLT32X_HAS_INFINITY__ + #define __FLT32X_HAS_INFINITY__ 1 + #undef __INT32_MAX__ + #define __INT32_MAX__ 0x7fffffff + #undef __FLT16_DIG__ + #define __FLT16_DIG__ 3 + #undef __unix__ + #define __unix__ 1 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 16 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 4 + #undef __UINT16_C + #define __UINT16_C(c) c + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ 21 + #undef __FLT64_EPSILON__ + #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64 + #undef __gnu_linux__ + #define __gnu_linux__ 1 + #undef __FLT128_IS_IEC_60559__ + #define __FLT128_IS_IEC_60559__ 2 + #undef __FLT64X_MIN_10_EXP__ + #define __FLT64X_MIN_10_EXP__ (-4931) + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __FLT16_MIN_EXP__ + #define __FLT16_MIN_EXP__ (-13) + #undef __FLT64_MANT_DIG__ + #define __FLT64_MANT_DIG__ 53 + #undef __FLT64X_MANT_DIG__ + #define __FLT64X_MANT_DIG__ 64 + #undef __GNUC__ + #define __GNUC__ 12 + #undef __pie__ + #define __pie__ 2 + #undef __MMX__ + #define __MMX__ 1 + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 12 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 16 + #undef __FLT64_MAX_10_EXP__ + #define __FLT64_MAX_10_EXP__ 308 + #undef __FLT16_MAX_10_EXP__ + #define __FLT16_MAX_10_EXP__ 4 + #undef __DBL_MAX__ + #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 0x7fffffff + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __HAVE_SPECULATION_SAFE_VALUE + #define __HAVE_SPECULATION_SAFE_VALUE 1 + #undef __DEC32_MIN_EXP__ + #define __DEC32_MIN_EXP__ (-94) + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 32 + #undef __FLT64X_HAS_INFINITY__ + #define __FLT64X_HAS_INFINITY__ 1 + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 0xffffffffU + #undef __FLT32X_HAS_DENORM__ + #define __FLT32X_HAS_DENORM__ 1 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ int + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __SEG_GS + #define __SEG_GS 1 + #undef __FLT128_HAS_INFINITY__ + #define __FLT128_HAS_INFINITY__ 1 + #undef __DEC32_MIN__ + #define __DEC32_MIN__ 1E-95DF + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 1024 + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 16 + #undef __FLT32_MAX__ + #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __DEC128_EPSILON__ + #define __DEC128_EPSILON__ 1E-33DL + #undef __FLT16_DECIMAL_DIG__ + #define __FLT16_DECIMAL_DIG__ 5 + #undef __ATOMIC_HLE_RELEASE + #define __ATOMIC_HLE_RELEASE 131072 + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 0x7fffffff + #undef __ATOMIC_HLE_ACQUIRE + #define __ATOMIC_HLE_ACQUIRE 65536 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 2 + #undef __FLT64X_MIN_EXP__ + #define __FLT64X_MIN_EXP__ (-16381) + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 4 + #undef __LONG_LONG_WIDTH__ + #define __LONG_LONG_WIDTH__ 64 + #undef __FLT32_MAX_EXP__ + #define __FLT32_MAX_EXP__ 128 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1017 + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __INT16_MAX__ + #define __INT16_MAX__ 0x7fff + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long long int + #undef __FLT64_DENORM_MIN__ + #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64 + #undef __DBL_MIN__ + #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) + #undef __FLT16_DENORM_MIN__ + #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16 + #undef __FLT128_EPSILON__ + #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128 + #undef __FLT64X_NORM_MAX__ + #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 4 + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __FLT32X_EPSILON__ + #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x + #undef __DECIMAL_BID_FORMAT__ + #define __DECIMAL_BID_FORMAT__ 1 + #undef __FLT64_MIN_EXP__ + #define __FLT64_MIN_EXP__ (-1021) + #undef __FLT64_MIN_10_EXP__ + #define __FLT64_MIN_10_EXP__ (-307) + #undef __FLT16_MIN_10_EXP__ + #define __FLT16_MIN_10_EXP__ (-4) + #undef __FLT64X_DECIMAL_DIG__ + #define __FLT64X_DECIMAL_DIG__ 21 + #undef __DEC128_MIN__ + #define __DEC128_MIN__ 1E-6143DL + #undef __REGISTER_PREFIX__ + #define __REGISTER_PREFIX__ + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 0xffff + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __FLT32_MIN__ + #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __DEC_EVAL_METHOD__ + #define __DEC_EVAL_METHOD__ 2 + #undef __DEC128_MAX__ + #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL + #undef __i386 + #define __i386 1 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 21 + #undef __VERSION__ + #define __VERSION__ "12.2.1 20230201" + #undef __UINT64_C + #define __UINT64_C(c) c ## ULL + #undef _STDC_PREDEF_H + #define _STDC_PREDEF_H 1 + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 0x7fffffff + #undef __FLT128_MAX_EXP__ + #define __FLT128_MAX_EXP__ 16384 + #undef __FLT32_MANT_DIG__ + #define __FLT32_MANT_DIG__ 24 + #undef __FLOAT_WORD_ORDER__ + #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __FLT32X_MIN_EXP__ + #define __FLT32X_MIN_EXP__ (-1021) + #undef i386 + #define i386 1 + #undef __FLT128_HAS_DENORM__ + #define __FLT128_HAS_DENORM__ 1 + #undef __FLT32_DECIMAL_DIG__ + #define __FLT32_DECIMAL_DIG__ 9 + #undef __FLT128_DIG__ + #define __FLT128_DIG__ 33 + #undef __INT32_C + #define __INT32_C(c) c ## L + #undef __DEC64_EPSILON__ + #define __DEC64_EPSILON__ 1E-15DD + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __DEC128_MIN_EXP__ + #define __DEC128_MIN_EXP__ (-6142) + #undef __code_model_32__ + #define __code_model_32__ 1 + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ long + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ short unsigned int + #undef unix + #define unix 1 + #undef __i386__ + #define __i386__ 1 + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ unsigned int + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 0xffffffffffffffffULL + #undef __FLT_IS_IEC_60559__ + #define __FLT_IS_IEC_60559__ 2 + #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME + #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE" + #undef __FLT64X_DIG__ + #define __FLT64X_DIG__ 18 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __ELF__ + #define __ELF__ 1 + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ unsigned long + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ short int + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L + #undef __UINTMAX_C + #define __UINTMAX_C(c) c ## ULL + #undef __k8 + #define __k8 1 + #undef __FLT32X_MIN__ + #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 0x7fffffff + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 4 + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 18 + #undef __FLT64_IS_IEC_60559__ + #define __FLT64_IS_IEC_60559__ 2 + #undef __FLT16_IS_IEC_60559__ + #define __FLT16_IS_IEC_60559__ 2 + #undef __FLT16_MAX_EXP__ + #define __FLT16_MAX_EXP__ 16 + #undef __DEC32_SUBNORMAL_MIN__ + #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 0x7fffffff + #undef __FLT64_DIG__ + #define __FLT64_DIG__ 15 + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 0xffffffffU + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long long unsigned int + #undef __FLT16_EPSILON__ + #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16 + #undef __ILP32__ + #define __ILP32__ 1 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __LONG_MAX__ + #define __LONG_MAX__ 0x7fffffffL + #undef __FLT64X_HAS_DENORM__ + #define __FLT64X_HAS_DENORM__ 1 + #undef __DEC128_SUBNORMAL_MIN__ + #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __GNUC_EXECUTION_CHARSET_NAME + #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8" + #undef _ILP32 + #define _ILP32 1 + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ unsigned int + #undef __DEC64_MAX__ + #define __DEC64_MAX__ 9.999999999999999E384DD + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 32 + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ short unsigned int + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 32 + #undef __SEG_FS + #define __SEG_FS 1 + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 0x7fff + #undef __FLT16_NORM_MAX__ + #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __DEC64_MANT_DIG__ + #define __DEC64_MANT_DIG__ 16 + #undef __INT64_MAX__ + #define __INT64_MAX__ 0x7fffffffffffffffLL + #undef __FLT32_DENORM_MIN__ + #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 32 + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long long int + #undef __INT16_TYPE__ + #define __INT16_TYPE__ short int + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __FLT16_MAX__ + #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 4 + #undef __DEC32_MAX_EXP__ + #define __DEC32_MAX_EXP__ 97 + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 0x7f + #undef __FLT128_MAX__ + #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 0x7fffffff + #undef linux + #define linux 1 + #undef __FLT64_HAS_QUIET_NAN__ + #define __FLT64_HAS_QUIET_NAN__ 1 + #undef __FLT32_MIN_10_EXP__ + #define __FLT32_MIN_10_EXP__ (-37) + #undef __FLT32X_DIG__ + #define __FLT32X_DIG__ 15 + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 16 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 64 + #undef __FLT64_HAS_INFINITY__ + #define __FLT64_HAS_INFINITY__ 1 + #undef __FLT64X_MAX__ + #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __FLT16_HAS_INFINITY__ + #define __FLT16_HAS_INFINITY__ 1 + #undef __SIG_ATOMIC_MIN__ + #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) + #undef __DEC32_MANT_DIG__ + #define __DEC32_MANT_DIG__ 7 + #undef __FLT16_MANT_DIG__ + #define __FLT16_MANT_DIG__ 11 + #undef __k8__ + #define __k8__ 1 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ long + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ short unsigned int + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ int + #undef __pic__ + #define __pic__ 2 + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 0xffffffffU + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL + #undef __FLT_NORM_MAX__ + #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __FLT32_HAS_INFINITY__ + #define __FLT32_HAS_INFINITY__ 1 + #undef __FLT64X_MAX_EXP__ + #define __FLT64X_MAX_EXP__ 16384 + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long long unsigned int + #undef __INT_MAX__ + #define __INT_MAX__ 0x7fff + #undef __linux__ + #define __linux__ 1 + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long long int + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 53 + #undef __SIZEOF_FLOAT128__ + #define __SIZEOF_FLOAT128__ 16 + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL + #undef __DEC64_MIN__ + #define __DEC64_MIN__ 1E-383DD + #undef __WINT_TYPE__ + #define __WINT_TYPE__ unsigned long + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ unsigned long + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __FLT32_NORM_MAX__ + #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __SSE__ + #define __SSE__ 1 + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-16381) + #undef __FLT64_MAX__ + #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 32 + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 0x7f + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 16384 + #undef __FLT32X_MAX_10_EXP__ + #define __FLT32X_MAX_10_EXP__ 308 + #undef __FLT16_MIN__ + #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16 + #undef __FLT64X_IS_IEC_60559__ + #define __FLT64X_IS_IEC_60559__ 2 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 4932 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) + #undef __FLT128_MIN__ + #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128 + #undef __UINT8_C + #define __UINT8_C(c) c + #undef __FLT64_MAX_EXP__ + #define __FLT64_MAX_EXP__ 1024 + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ long + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 2 + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long long unsigned int + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __FLT128_NORM_MAX__ + #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __FLT64_NORM_MAX__ + #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __FLT128_HAS_QUIET_NAN__ + #define __FLT128_HAS_QUIET_NAN__ 1 + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 0x7fffffffffffffffLL + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __FLT64X_MIN__ + #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __FLT64_HAS_DENORM__ + #define __FLT64_HAS_DENORM__ 1 + #undef __FLT32_EPSILON__ + #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32 + #undef __FLT16_HAS_DENORM__ + #define __FLT16_HAS_DENORM__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 17 + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __FXSR__ + #define __FXSR__ 1 + #undef __FLT32X_MAX__ + #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __DBL_NORM_MAX__ + #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __UINT32_C + #define __UINT32_C(c) c ## UL + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F + #undef __INT8_MAX__ + #define __INT8_MAX__ 0x7f + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 32 + #undef __PIC__ + #define __PIC__ 2 + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ unsigned long + #undef __FLT32X_NORM_MAX__ + #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ unsigned long + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __SSE2__ + #define __SSE2__ 1 + #undef __INT32_TYPE__ + #define __INT32_TYPE__ long + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 8 + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT64_MIN__ + #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64 + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long long int + #undef __DEC128_MAX_EXP__ + #define __DEC128_MAX_EXP__ 6145 + #undef __FLT32X_HAS_QUIET_NAN__ + #define __FLT32X_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 2 + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 32 + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 0xffffffffffffffffULL + #undef __PIE__ + #define __PIE__ 2 + #undef __FLT32X_DENORM_MIN__ + #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 308 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L + #undef __INT16_C + #define __INT16_C(c) c + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ int + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __FLT32X_MIN_10_EXP__ + #define __FLT32X_MIN_10_EXP__ (-307) + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ unsigned int + #undef __DEC64_SUBNORMAL_MIN__ + #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD + #undef __DEC128_MANT_DIG__ + #define __DEC128_MANT_DIG__ 34 + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-4931) + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __FLT128_DECIMAL_DIG__ + #define __FLT128_DECIMAL_DIG__ 36 + #undef __FLT32_HAS_QUIET_NAN__ + #define __FLT32_HAS_QUIET_NAN__ 1 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 0xffffU + #undef __LDBL_NORM_MAX__ + #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 + +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotrecoverable: '131' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eownerdead: '130' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +has__builtin_va_list: true +int_fast8_t: signed char +int_fast16_t: signed int +int_fast32_t: long +int_fast64_t: long long +intptr_t: long +little_endian: true +nsig: '65' +ptrdiff_t: int +sig_atomic_t: int +size_t: unsigned int +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: -1 +sizeof_int: 2 +sizeof_long: 4 +sizeof_longdouble: 16 +sizeof_longlong: 8 +sizeof_ptr: 4 +sizeof_short: 2 +sizeof_void: -1 +ssize_t: int +time_t: long +uint_fast8_t: unsigned char +uint_fast16_t: unsigned int +uint_fast32_t: unsigned long +uint_fast64_t: unsigned long long +uintptr_t: unsigned long +version: none +wchar_t: int +weof: (0xffffffffUL) +wint_t: unsigned long +wordsize: '16' +posix_version: '200809L' +bufsiz: '8192' +eof: '(-1)' +fopen_max: '16' +filename_max: '2048' +path_max: '256' +host_name_max: '64' +tty_name_max: '32' +l_tmpnam: '2048' +tmp_max: '0xFFFFFFFF' +rand_max: '32767' +mb_cur_max: '((size_t)16)' +machdep_name: machdep_x86_16 diff --git a/share/machdeps/machdep_x86_32.yaml b/share/machdeps/machdep_x86_32.yaml new file mode 100644 index 0000000000000000000000000000000000000000..255029b4cc32a97a4d801fde4c0d7bb7c897b70b --- /dev/null +++ b/share/machdeps/machdep_x86_32.yaml @@ -0,0 +1,915 @@ +alignof_aligned: 16 +alignof_double: 4 +alignof_float: 4 +alignof_fun: -1 +alignof_int: 4 +alignof_long: 4 +alignof_longdouble: 4 +alignof_longlong: 4 +alignof_ptr: 4 +alignof_short: 2 +alignof_str: 1 +bufsiz: '8192' +char_is_unsigned: false +compiler: generic +cpp_arch_flags: +- -m32 +custom_defs: | + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-1021) + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 0xffff + #undef __FLT16_HAS_QUIET_NAN__ + #define __FLT16_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __FLT128_MAX_10_EXP__ + #define __FLT128_MAX_10_EXP__ 4932 + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __SIZEOF_FLOAT80__ + #define __SIZEOF_FLOAT80__ 12 + #undef __BFLT16_DENORM_MIN__ + #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16 + #undef __INTMAX_C + #define __INTMAX_C(c) c ## LL + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 0xff + #undef __SCHAR_WIDTH__ + #define __SCHAR_WIDTH__ 8 + #undef __WINT_MAX__ + #define __WINT_MAX__ 0xffffffffU + #undef __FLT32_MIN_EXP__ + #define __FLT32_MIN_EXP__ (-125) + #undef __BFLT16_NORM_MAX__ + #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_MIN_10_EXP__ + #define __BFLT16_MIN_10_EXP__ (-37) + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 0x7fffffffL + #undef __FLT32X_DECIMAL_DIG__ + #define __FLT32X_DECIMAL_DIG__ 17 + #undef __FLT_EVAL_METHOD__ + #define __FLT_EVAL_METHOD__ 2 + #undef __FLT64_DECIMAL_DIG__ + #define __FLT64_DECIMAL_DIG__ 17 + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 0xffffffffffffffffULL + #undef __SIG_ATOMIC_TYPE__ + #define __SIG_ATOMIC_TYPE__ int + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-307) + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT32X_MAX_EXP__ + #define __FLT32X_MAX_EXP__ 1024 + #undef __FLT32_HAS_DENORM__ + #define __FLT32_HAS_DENORM__ 1 + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 0xff + #undef __FLT32_MAX_10_EXP__ + #define __FLT32_MAX_10_EXP__ 38 + #undef __DEC64_MAX_EXP__ + #define __DEC64_MAX_EXP__ 385 + #undef __INT8_C + #define __INT8_C(c) c + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 0xffffffffffffffffULL + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 0x7fff + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __FLT64X_MAX_10_EXP__ + #define __FLT64X_MAX_10_EXP__ 4932 + #undef __BFLT16_MAX_10_EXP__ + #define __BFLT16_MAX_10_EXP__ 38 + #undef __BFLT16_MAX_EXP__ + #define __BFLT16_MAX_EXP__ 128 + #undef __LDBL_IS_IEC_60559__ + #define __LDBL_IS_IEC_60559__ 1 + #undef __FLT64X_HAS_QUIET_NAN__ + #define __FLT64X_HAS_QUIET_NAN__ 1 + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 0xff + #undef __LAHF_SAHF__ + #define __LAHF_SAHF__ 1 + #undef __FLT128_DENORM_MIN__ + #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128 + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long long unsigned int + #undef __BFLT16_DECIMAL_DIG__ + #define __BFLT16_DECIMAL_DIG__ 4 + #undef __linux + #define __linux 1 + #undef __DEC32_EPSILON__ + #define __DEC32_EPSILON__ 1E-6DF + #undef __FLT_EVAL_METHOD_TS_18661_3__ + #define __FLT_EVAL_METHOD_TS_18661_3__ 2 + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 0xffffffffU + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) + #undef __FLT128_MIN_EXP__ + #define __FLT128_MIN_EXP__ (-16381) + #undef __WINT_MIN__ + #define __WINT_MIN__ 0U + #undef __FLT128_MIN_10_EXP__ + #define __FLT128_MIN_10_EXP__ (-4931) + #undef __FLT32X_IS_IEC_60559__ + #define __FLT32X_IS_IEC_60559__ 1 + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 0x7f + #undef __FLT128_MANT_DIG__ + #define __FLT128_MANT_DIG__ 113 + #undef __WCHAR_MIN__ + #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1) + #undef __INT64_C + #define __INT64_C(c) c ## LL + #undef __SSP_STRONG__ + #define __SSP_STRONG__ 3 + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __unix + #define __unix 1 + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 0x7fffffffffffffffLL + #undef __FLT32X_MANT_DIG__ + #define __FLT32X_MANT_DIG__ 53 + #undef __FLT64X_EPSILON__ + #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x + #undef __DEC64_MIN_EXP__ + #define __DEC64_MIN_EXP__ (-382) + #undef __DBL_DIG__ + #define __DBL_DIG__ 15 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __FLT32_IS_IEC_60559__ + #define __FLT32_IS_IEC_60559__ 1 + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L + #undef __DBL_IS_IEC_60559__ + #define __DBL_IS_IEC_60559__ 1 + #undef __DEC32_MAX__ + #define __DEC32_MAX__ 9.999999E96DF + #undef __FLT64X_DENORM_MIN__ + #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x + #undef __FLT32X_HAS_INFINITY__ + #define __FLT32X_HAS_INFINITY__ 1 + #undef __unix__ + #define __unix__ 1 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 32 + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ 21 + #undef __FLT64_EPSILON__ + #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64 + #undef __gnu_linux__ + #define __gnu_linux__ 1 + #undef __FLT128_IS_IEC_60559__ + #define __FLT128_IS_IEC_60559__ 1 + #undef __FLT64X_MIN_10_EXP__ + #define __FLT64X_MIN_10_EXP__ (-4931) + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __FLT16_MIN_EXP__ + #define __FLT16_MIN_EXP__ (-13) + #undef __FLT64_MANT_DIG__ + #define __FLT64_MANT_DIG__ 53 + #undef __FLT64X_MANT_DIG__ + #define __FLT64X_MANT_DIG__ 64 + #undef __BFLT16_DIG__ + #define __BFLT16_DIG__ 2 + #undef __GNUC__ + #define __GNUC__ 13 + #undef __pie__ + #define __pie__ 2 + #undef __MMX__ + #define __MMX__ 1 + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 12 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 16 + #undef __FLT64_MAX_10_EXP__ + #define __FLT64_MAX_10_EXP__ 308 + #undef __BFLT16_IS_IEC_60559__ + #define __BFLT16_IS_IEC_60559__ 0 + #undef __FLT16_MAX_10_EXP__ + #define __FLT16_MAX_10_EXP__ 4 + #undef __DBL_MAX__ + #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 0x7fffffff + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __INT64_MAX__ + #define __INT64_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __HAVE_SPECULATION_SAFE_VALUE + #define __HAVE_SPECULATION_SAFE_VALUE 1 + #undef __DEC32_MIN_EXP__ + #define __DEC32_MIN_EXP__ (-94) + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 32 + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 0xffffffffU + #undef __FLT32X_HAS_DENORM__ + #define __FLT32X_HAS_DENORM__ 1 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ int + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __SEG_GS + #define __SEG_GS 1 + #undef __BFLT16_EPSILON__ + #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16 + #undef __FLT128_HAS_INFINITY__ + #define __FLT128_HAS_INFINITY__ 1 + #undef __DEC32_MIN__ + #define __DEC32_MIN__ 1E-95DF + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 1024 + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 32 + #undef __FLT32_MAX__ + #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __DEC128_EPSILON__ + #define __DEC128_EPSILON__ 1E-33DL + #undef __FLT16_DECIMAL_DIG__ + #define __FLT16_DECIMAL_DIG__ 5 + #undef __ATOMIC_HLE_RELEASE + #define __ATOMIC_HLE_RELEASE 131072 + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 0x7fffffff + #undef __ATOMIC_HLE_ACQUIRE + #define __ATOMIC_HLE_ACQUIRE 65536 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 4 + #undef __BFLT16_HAS_INFINITY__ + #define __BFLT16_HAS_INFINITY__ 1 + #undef __FLT64X_MIN_EXP__ + #define __FLT64X_MIN_EXP__ (-16381) + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 4 + #undef __LONG_LONG_WIDTH__ + #define __LONG_LONG_WIDTH__ 64 + #undef __FLT32_MAX_EXP__ + #define __FLT32_MAX_EXP__ 128 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1018 + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __INT16_MAX__ + #define __INT16_MAX__ 0x7fff + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long long int + #undef __BFLT16_MAX__ + #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_HAS_DENORM__ + #define __BFLT16_HAS_DENORM__ 1 + #undef __FLT64_DENORM_MIN__ + #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64 + #undef __FLT16_DENORM_MIN__ + #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16 + #undef __FLT128_EPSILON__ + #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128 + #undef __FLT64X_NORM_MAX__ + #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 4 + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ unsigned int + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __FLT32X_EPSILON__ + #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 16384 + #undef __DECIMAL_BID_FORMAT__ + #define __DECIMAL_BID_FORMAT__ 1 + #undef __FLT64_MIN_EXP__ + #define __FLT64_MIN_EXP__ (-1021) + #undef __FLT64_MIN_10_EXP__ + #define __FLT64_MIN_10_EXP__ (-307) + #undef __FLT16_MIN_10_EXP__ + #define __FLT16_MIN_10_EXP__ (-4) + #undef __FLT64X_DECIMAL_DIG__ + #define __FLT64X_DECIMAL_DIG__ 21 + #undef __DEC128_MIN__ + #define __DEC128_MIN__ 1E-6143DL + #undef __REGISTER_PREFIX__ + #define __REGISTER_PREFIX__ + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 0xffff + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __FLT32_MIN__ + #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __DEC_EVAL_METHOD__ + #define __DEC_EVAL_METHOD__ 2 + #undef __i386 + #define __i386 1 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 21 + #undef __VERSION__ + #define __VERSION__ "13.1.1 20230429" + #undef __UINT64_C + #define __UINT64_C(c) c ## ULL + #undef _STDC_PREDEF_H + #define _STDC_PREDEF_H 1 + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 0x7fffffff + #undef __FLT128_MAX_EXP__ + #define __FLT128_MAX_EXP__ 16384 + #undef __FLT32_MANT_DIG__ + #define __FLT32_MANT_DIG__ 24 + #undef __FLOAT_WORD_ORDER__ + #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __FLT32X_MIN_EXP__ + #define __FLT32X_MIN_EXP__ (-1021) + #undef i386 + #define i386 1 + #undef __BFLT16_MIN__ + #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16 + #undef __FLT128_HAS_DENORM__ + #define __FLT128_HAS_DENORM__ 1 + #undef __FLT32_DECIMAL_DIG__ + #define __FLT32_DECIMAL_DIG__ 9 + #undef __FLT128_DIG__ + #define __FLT128_DIG__ 33 + #undef __INT32_C + #define __INT32_C(c) c + #undef __DEC64_EPSILON__ + #define __DEC64_EPSILON__ 1E-15DD + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __DEC128_MIN_EXP__ + #define __DEC128_MIN_EXP__ (-6142) + #undef __code_model_32__ + #define __code_model_32__ 1 + #undef __DEC128_MAX__ + #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ int + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ short unsigned int + #undef __DEC128_MAX_EXP__ + #define __DEC128_MAX_EXP__ 6145 + #undef unix + #define unix 1 + #undef __i386__ + #define __i386__ 1 + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 0xffffffffffffffffULL + #undef __FLT_IS_IEC_60559__ + #define __FLT_IS_IEC_60559__ 1 + #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME + #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE" + #undef __FLT64X_DIG__ + #define __FLT64X_DIG__ 18 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __ELF__ + #define __ELF__ 1 + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ unsigned int + #undef __BFLT16_HAS_QUIET_NAN__ + #define __BFLT16_HAS_QUIET_NAN__ 1 + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ short int + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L + #undef __UINTMAX_C + #define __UINTMAX_C(c) c ## ULL + #undef __FLT16_DIG__ + #define __FLT16_DIG__ 3 + #undef __k8 + #define __k8 1 + #undef __FLT32X_MIN__ + #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 0x7fffffff + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 4 + #undef __FLT64X_HAS_INFINITY__ + #define __FLT64X_HAS_INFINITY__ 1 + #undef __FLT32_HAS_INFINITY__ + #define __FLT32_HAS_INFINITY__ 1 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 4 + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 18 + #undef __FLT64_IS_IEC_60559__ + #define __FLT64_IS_IEC_60559__ 1 + #undef __FLT16_IS_IEC_60559__ + #define __FLT16_IS_IEC_60559__ 1 + #undef __FLT16_MAX_EXP__ + #define __FLT16_MAX_EXP__ 16 + #undef __DEC32_SUBNORMAL_MIN__ + #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 0x7fffffff + #undef __FLT64_DIG__ + #define __FLT64_DIG__ 15 + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 0xffffffffU + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long long unsigned int + #undef __FLT16_EPSILON__ + #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16 + #undef __ILP32__ + #define __ILP32__ 1 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __LONG_MAX__ + #define __LONG_MAX__ 0x7fffffffL + #undef __FLT64X_HAS_DENORM__ + #define __FLT64X_HAS_DENORM__ 1 + #undef __DEC128_SUBNORMAL_MIN__ + #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __GNUC_EXECUTION_CHARSET_NAME + #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8" + #undef _ILP32 + #define _ILP32 1 + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ unsigned int + #undef __DEC64_MAX__ + #define __DEC64_MAX__ 9.999999999999999E384DD + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 32 + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ short unsigned int + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 32 + #undef __SEG_FS + #define __SEG_FS 1 + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 0x7fff + #undef __FLT16_NORM_MAX__ + #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __DEC64_MANT_DIG__ + #define __DEC64_MANT_DIG__ 16 + #undef __FLT32_DENORM_MIN__ + #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 32 + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long long int + #undef __INT16_TYPE__ + #define __INT16_TYPE__ short int + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __FLT16_MAX__ + #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __FLT128_MIN__ + #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 4 + #undef __DEC32_MAX_EXP__ + #define __DEC32_MAX_EXP__ 97 + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 0x7f + #undef __FLT128_MAX__ + #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 0x7fffffff + #undef linux + #define linux 1 + #undef __FLT64_HAS_QUIET_NAN__ + #define __FLT64_HAS_QUIET_NAN__ 1 + #undef __FLT32_MIN_10_EXP__ + #define __FLT32_MIN_10_EXP__ (-37) + #undef __FLT32X_DIG__ + #define __FLT32X_DIG__ 15 + #undef __UINT16_C + #define __UINT16_C(c) c + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 32 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 64 + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 32 + #undef __FLT64_HAS_INFINITY__ + #define __FLT64_HAS_INFINITY__ 1 + #undef __FLT64X_MAX__ + #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __FLT16_HAS_INFINITY__ + #define __FLT16_HAS_INFINITY__ 1 + #undef __SIG_ATOMIC_MIN__ + #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) + #undef __DEC32_MANT_DIG__ + #define __DEC32_MANT_DIG__ 7 + #undef __FLT16_MANT_DIG__ + #define __FLT16_MANT_DIG__ 11 + #undef __k8__ + #define __k8__ 1 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ int + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ short unsigned int + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ long int + #undef __pic__ + #define __pic__ 2 + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 0xffffffffU + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 0x7fffffffffffffffLL + #undef __FLT_NORM_MAX__ + #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __FLT64X_MAX_EXP__ + #define __FLT64X_MAX_EXP__ 16384 + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long long unsigned int + #undef __BFLT16_MIN_EXP__ + #define __BFLT16_MIN_EXP__ (-125) + #undef __INT_MAX__ + #define __INT_MAX__ 0x7fffffff + #undef __linux__ + #define __linux__ 1 + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long long int + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 53 + #undef __SIZEOF_FLOAT128__ + #define __SIZEOF_FLOAT128__ 16 + #undef __BFLT16_MANT_DIG__ + #define __BFLT16_MANT_DIG__ 8 + #undef __DEC64_MIN__ + #define __DEC64_MIN__ 1E-383DD + #undef __WINT_TYPE__ + #define __WINT_TYPE__ unsigned int + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ unsigned int + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __FLT32_NORM_MAX__ + #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __SSE__ + #define __SSE__ 1 + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-16381) + #undef __FLT64_MAX__ + #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 32 + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 0x7f + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __FLT32X_MAX_10_EXP__ + #define __FLT32X_MAX_10_EXP__ 308 + #undef __FLT16_MIN__ + #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16 + #undef __FLT64X_IS_IEC_60559__ + #define __FLT64X_IS_IEC_60559__ 1 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 4932 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ int + #undef __UINT8_C + #define __UINT8_C(c) c + #undef __FLT64_MAX_EXP__ + #define __FLT64_MAX_EXP__ 1024 + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 4 + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long long unsigned int + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __FLT128_NORM_MAX__ + #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __FLT64_NORM_MAX__ + #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __FLT128_HAS_QUIET_NAN__ + #define __FLT128_HAS_QUIET_NAN__ 1 + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 0x7fffffffffffffffLL + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __FLT64X_MIN__ + #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __FLT64_HAS_DENORM__ + #define __FLT64_HAS_DENORM__ 1 + #undef __FLT32_EPSILON__ + #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32 + #undef __FLT16_HAS_DENORM__ + #define __FLT16_HAS_DENORM__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 17 + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __FXSR__ + #define __FXSR__ 1 + #undef __FLT32X_MAX__ + #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __DBL_NORM_MAX__ + #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __FLT32_DIG__ + #define __FLT32_DIG__ 6 + #undef __UINT32_C + #define __UINT32_C(c) c ## U + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F + #undef __INT8_MAX__ + #define __INT8_MAX__ 0x7f + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 32 + #undef __DBL_MIN__ + #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) + #undef __PIC__ + #define __PIC__ 2 + #undef __INT32_MAX__ + #define __INT32_MAX__ 0x7fffffff + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ unsigned int + #undef __FLT32X_NORM_MAX__ + #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ unsigned int + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __SSE2__ + #define __SSE2__ 1 + #undef __INT32_TYPE__ + #define __INT32_TYPE__ int + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 8 + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT64_MIN__ + #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64 + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long long int + #undef __FLT32X_HAS_QUIET_NAN__ + #define __FLT32X_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 1 + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 0xffffffffffffffffULL + #undef __PIE__ + #define __PIE__ 2 + #undef __FLT32X_DENORM_MIN__ + #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 308 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L + #undef __INT16_C + #define __INT16_C(c) c + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ int + #undef __FLT32X_MIN_10_EXP__ + #define __FLT32X_MIN_10_EXP__ (-307) + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ unsigned int + #undef __DEC64_SUBNORMAL_MIN__ + #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD + #undef __DEC128_MANT_DIG__ + #define __DEC128_MANT_DIG__ 34 + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-4931) + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __FLT128_DECIMAL_DIG__ + #define __FLT128_DECIMAL_DIG__ 36 + #undef __FLT32_HAS_QUIET_NAN__ + #define __FLT32_HAS_QUIET_NAN__ 1 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 0xffffffffU + #undef __LDBL_NORM_MAX__ + #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 0xffffffffU + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 +eof: (-1) +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotrecoverable: '131' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eownerdead: '130' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +filename_max: '4096' +fopen_max: '16' +has__builtin_va_list: true +host_name_max: '64' +int_fast16_t: int +int_fast32_t: int +int_fast64_t: long long +int_fast8_t: signed char +intptr_t: int +l_tmpnam: '20' +little_endian: true +machdep_name: machdep_x86_32 +mb_cur_max: ((size_t) 16 ) +nsig: (64 + 1) +path_max: '4096' +posix_version: 200809L +ptrdiff_t: int +rand_max: '2147483647' +sig_atomic_t: int +size_t: unsigned int +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: -1 +sizeof_int: 4 +sizeof_long: 4 +sizeof_longdouble: 12 +sizeof_longlong: 8 +sizeof_ptr: 4 +sizeof_short: 2 +sizeof_void: -1 +ssize_t: int +time_t: long +tmp_max: '238328' +tty_name_max: '32' +uint_fast16_t: unsigned int +uint_fast32_t: unsigned int +uint_fast64_t: unsigned long long +uint_fast8_t: unsigned char +uintptr_t: unsigned int +version: gcc (GCC) 13.1.1 20230429 +wchar_t: long +weof: (0xffffffffu) +wint_t: unsigned int +wordsize: '32' diff --git a/share/machdeps/machdep_x86_64.yaml b/share/machdeps/machdep_x86_64.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4bea3f923dd78d231b2831b93e8d462d6ad246f3 --- /dev/null +++ b/share/machdeps/machdep_x86_64.yaml @@ -0,0 +1,923 @@ +alignof_aligned: 16 +alignof_double: 8 +alignof_float: 4 +alignof_fun: -1 +alignof_int: 4 +alignof_long: 8 +alignof_longdouble: 16 +alignof_longlong: 8 +alignof_ptr: 8 +alignof_short: 2 +alignof_str: 1 +bufsiz: '8192' +char_is_unsigned: false +compiler: generic +cpp_arch_flags: +- -m64 +custom_defs: | + #undef __DBL_MIN_EXP__ + #define __DBL_MIN_EXP__ (-1021) + #undef __UINT_LEAST16_MAX__ + #define __UINT_LEAST16_MAX__ 0xffff + #undef __FLT16_HAS_QUIET_NAN__ + #define __FLT16_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_ACQUIRE + #define __ATOMIC_ACQUIRE 2 + #undef __FLT128_MAX_10_EXP__ + #define __FLT128_MAX_10_EXP__ 4932 + #undef __FLT_MIN__ + #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F + #undef __UINT_LEAST8_TYPE__ + #define __UINT_LEAST8_TYPE__ unsigned char + #undef __SIZEOF_FLOAT80__ + #define __SIZEOF_FLOAT80__ 16 + #undef __BFLT16_DENORM_MIN__ + #define __BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16 + #undef __INTMAX_C + #define __INTMAX_C(c) c ## L + #undef __CHAR_BIT__ + #define __CHAR_BIT__ 8 + #undef __UINT8_MAX__ + #define __UINT8_MAX__ 0xff + #undef __SCHAR_WIDTH__ + #define __SCHAR_WIDTH__ 8 + #undef __WINT_MAX__ + #define __WINT_MAX__ 0xffffffffU + #undef __FLT32_MIN_EXP__ + #define __FLT32_MIN_EXP__ (-125) + #undef __BFLT16_NORM_MAX__ + #define __BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_MIN_10_EXP__ + #define __BFLT16_MIN_10_EXP__ (-37) + #undef __ORDER_LITTLE_ENDIAN__ + #define __ORDER_LITTLE_ENDIAN__ 1234 + #undef __WCHAR_MAX__ + #define __WCHAR_MAX__ 0x7fffffff + #undef __FLT32X_DECIMAL_DIG__ + #define __FLT32X_DECIMAL_DIG__ 17 + #undef __FLT_EVAL_METHOD__ + #define __FLT_EVAL_METHOD__ 0 + #undef __FLT64_DECIMAL_DIG__ + #define __FLT64_DECIMAL_DIG__ 17 + #undef __UINT_FAST64_MAX__ + #define __UINT_FAST64_MAX__ 0xffffffffffffffffUL + #undef __SIG_ATOMIC_TYPE__ + #define __SIG_ATOMIC_TYPE__ int + #undef __DBL_MIN_10_EXP__ + #define __DBL_MIN_10_EXP__ (-307) + #undef __FINITE_MATH_ONLY__ + #define __FINITE_MATH_ONLY__ 0 + #undef __FLT32X_MAX_EXP__ + #define __FLT32X_MAX_EXP__ 1024 + #undef __FLT32_HAS_DENORM__ + #define __FLT32_HAS_DENORM__ 1 + #undef __UINT_FAST8_MAX__ + #define __UINT_FAST8_MAX__ 0xff + #undef __FLT32_MAX_10_EXP__ + #define __FLT32_MAX_10_EXP__ 38 + #undef __DEC64_MAX_EXP__ + #define __DEC64_MAX_EXP__ 385 + #undef __INT8_C + #define __INT8_C(c) c + #undef __INT_LEAST8_WIDTH__ + #define __INT_LEAST8_WIDTH__ 8 + #undef __UINT_LEAST64_MAX__ + #define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL + #undef __SHRT_MAX__ + #define __SHRT_MAX__ 0x7fff + #undef __LDBL_MAX__ + #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __FLT64X_MAX_10_EXP__ + #define __FLT64X_MAX_10_EXP__ 4932 + #undef __BFLT16_MAX_10_EXP__ + #define __BFLT16_MAX_10_EXP__ 38 + #undef __BFLT16_MAX_EXP__ + #define __BFLT16_MAX_EXP__ 128 + #undef __LDBL_IS_IEC_60559__ + #define __LDBL_IS_IEC_60559__ 1 + #undef __FLT64X_HAS_QUIET_NAN__ + #define __FLT64X_HAS_QUIET_NAN__ 1 + #undef __UINT_LEAST8_MAX__ + #define __UINT_LEAST8_MAX__ 0xff + #undef __FLT128_DENORM_MIN__ + #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128 + #undef __UINTMAX_TYPE__ + #define __UINTMAX_TYPE__ long unsigned int + #undef __BFLT16_DECIMAL_DIG__ + #define __BFLT16_DECIMAL_DIG__ 4 + #undef __linux + #define __linux 1 + #undef __DEC32_EPSILON__ + #define __DEC32_EPSILON__ 1E-6DF + #undef __FLT_EVAL_METHOD_TS_18661_3__ + #define __FLT_EVAL_METHOD_TS_18661_3__ 0 + #undef __UINT32_MAX__ + #define __UINT32_MAX__ 0xffffffffU + #undef __DBL_DENORM_MIN__ + #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) + #undef __FLT128_MIN_EXP__ + #define __FLT128_MIN_EXP__ (-16381) + #undef __WINT_MIN__ + #define __WINT_MIN__ 0U + #undef __FLT128_MIN_10_EXP__ + #define __FLT128_MIN_10_EXP__ (-4931) + #undef __FLT32X_IS_IEC_60559__ + #define __FLT32X_IS_IEC_60559__ 1 + #undef __INT_LEAST16_WIDTH__ + #define __INT_LEAST16_WIDTH__ 16 + #undef __SCHAR_MAX__ + #define __SCHAR_MAX__ 0x7f + #undef __FLT128_MANT_DIG__ + #define __FLT128_MANT_DIG__ 113 + #undef __WCHAR_MIN__ + #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1) + #undef __INT64_C + #define __INT64_C(c) c ## L + #undef __SSP_STRONG__ + #define __SSP_STRONG__ 3 + #undef __ATOMIC_SEQ_CST + #define __ATOMIC_SEQ_CST 5 + #undef __unix + #define __unix 1 + #undef __INT_LEAST64_MAX__ + #define __INT_LEAST64_MAX__ 0x7fffffffffffffffL + #undef __FLT32X_MANT_DIG__ + #define __FLT32X_MANT_DIG__ 53 + #undef __FLT64X_EPSILON__ + #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x + #undef __DEC64_MIN_EXP__ + #define __DEC64_MIN_EXP__ (-382) + #undef __DBL_DIG__ + #define __DBL_DIG__ 15 + #undef __FLT_EPSILON__ + #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F + #undef __SHRT_WIDTH__ + #define __SHRT_WIDTH__ 16 + #undef __FLT32_IS_IEC_60559__ + #define __FLT32_IS_IEC_60559__ 1 + #undef __LDBL_MIN__ + #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L + #undef __DBL_IS_IEC_60559__ + #define __DBL_IS_IEC_60559__ 1 + #undef __DEC32_MAX__ + #define __DEC32_MAX__ 9.999999E96DF + #undef __FLT64X_DENORM_MIN__ + #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x + #undef __FLT32X_HAS_INFINITY__ + #define __FLT32X_HAS_INFINITY__ 1 + #undef __unix__ + #define __unix__ 1 + #undef __INT_WIDTH__ + #define __INT_WIDTH__ 32 + #undef __DECIMAL_DIG__ + #define __DECIMAL_DIG__ 21 + #undef __FLT64_EPSILON__ + #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64 + #undef __gnu_linux__ + #define __gnu_linux__ 1 + #undef __FLT128_IS_IEC_60559__ + #define __FLT128_IS_IEC_60559__ 1 + #undef __FLT64X_MIN_10_EXP__ + #define __FLT64X_MIN_10_EXP__ (-4931) + #undef __LDBL_HAS_QUIET_NAN__ + #define __LDBL_HAS_QUIET_NAN__ 1 + #undef __FLT16_MIN_EXP__ + #define __FLT16_MIN_EXP__ (-13) + #undef __FLT64_MANT_DIG__ + #define __FLT64_MANT_DIG__ 53 + #undef __FLT64X_MANT_DIG__ + #define __FLT64X_MANT_DIG__ 64 + #undef __BFLT16_DIG__ + #define __BFLT16_DIG__ 2 + #undef __GNUC__ + #define __GNUC__ 13 + #undef __pie__ + #define __pie__ 2 + #undef __MMX__ + #define __MMX__ 1 + #undef __FLT_HAS_DENORM__ + #define __FLT_HAS_DENORM__ 1 + #undef __SIZEOF_LONG_DOUBLE__ + #define __SIZEOF_LONG_DOUBLE__ 16 + #undef __BIGGEST_ALIGNMENT__ + #define __BIGGEST_ALIGNMENT__ 16 + #undef __FLT64_MAX_10_EXP__ + #define __FLT64_MAX_10_EXP__ 308 + #undef __BFLT16_IS_IEC_60559__ + #define __BFLT16_IS_IEC_60559__ 0 + #undef __FLT16_MAX_10_EXP__ + #define __FLT16_MAX_10_EXP__ 4 + #undef __DBL_MAX__ + #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __INT_FAST32_MAX__ + #define __INT_FAST32_MAX__ 0x7fffffffffffffffL + #undef __DBL_HAS_INFINITY__ + #define __DBL_HAS_INFINITY__ 1 + #undef __INT64_MAX__ + #define __INT64_MAX__ 0x7fffffffffffffffL + #undef __SIZEOF_FLOAT__ + #define __SIZEOF_FLOAT__ 4 + #undef __HAVE_SPECULATION_SAFE_VALUE + #define __HAVE_SPECULATION_SAFE_VALUE 1 + #undef __DEC32_MIN_EXP__ + #define __DEC32_MIN_EXP__ (-94) + #undef __INTPTR_WIDTH__ + #define __INTPTR_WIDTH__ 64 + #undef __UINT_LEAST32_MAX__ + #define __UINT_LEAST32_MAX__ 0xffffffffU + #undef __FLT32X_HAS_DENORM__ + #define __FLT32X_HAS_DENORM__ 1 + #undef __INT_FAST16_TYPE__ + #define __INT_FAST16_TYPE__ long int + #undef __MMX_WITH_SSE__ + #define __MMX_WITH_SSE__ 1 + #undef __LDBL_HAS_DENORM__ + #define __LDBL_HAS_DENORM__ 1 + #undef __SEG_GS + #define __SEG_GS 1 + #undef __BFLT16_EPSILON__ + #define __BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16 + #undef __FLT128_HAS_INFINITY__ + #define __FLT128_HAS_INFINITY__ 1 + #undef __DEC32_MIN__ + #define __DEC32_MIN__ 1E-95DF + #undef __DBL_MAX_EXP__ + #define __DBL_MAX_EXP__ 1024 + #undef __WCHAR_WIDTH__ + #define __WCHAR_WIDTH__ 32 + #undef __FLT32_MAX__ + #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __DEC128_EPSILON__ + #define __DEC128_EPSILON__ 1E-33DL + #undef __FLT16_DECIMAL_DIG__ + #define __FLT16_DECIMAL_DIG__ 5 + #undef __SSE2_MATH__ + #define __SSE2_MATH__ 1 + #undef __ATOMIC_HLE_RELEASE + #define __ATOMIC_HLE_RELEASE 131072 + #undef __PTRDIFF_MAX__ + #define __PTRDIFF_MAX__ 0x7fffffffffffffffL + #undef __amd64 + #define __amd64 1 + #undef __ATOMIC_HLE_ACQUIRE + #define __ATOMIC_HLE_ACQUIRE 65536 + #undef __LONG_LONG_MAX__ + #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL + #undef __SIZEOF_SIZE_T__ + #define __SIZEOF_SIZE_T__ 8 + #undef __BFLT16_HAS_INFINITY__ + #define __BFLT16_HAS_INFINITY__ 1 + #undef __FLT64X_MIN_EXP__ + #define __FLT64X_MIN_EXP__ (-16381) + #undef __SIZEOF_WINT_T__ + #define __SIZEOF_WINT_T__ 4 + #undef __LONG_LONG_WIDTH__ + #define __LONG_LONG_WIDTH__ 64 + #undef __FLT32_MAX_EXP__ + #define __FLT32_MAX_EXP__ 128 + #undef __GXX_ABI_VERSION + #define __GXX_ABI_VERSION 1018 + #undef __FLT_MIN_EXP__ + #define __FLT_MIN_EXP__ (-125) + #undef __INT16_MAX__ + #define __INT16_MAX__ 0x7fff + #undef __x86_64 + #define __x86_64 1 + #undef __INT_FAST64_TYPE__ + #define __INT_FAST64_TYPE__ long int + #undef __BFLT16_MAX__ + #define __BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16 + #undef __BFLT16_HAS_DENORM__ + #define __BFLT16_HAS_DENORM__ 1 + #undef __FLT64_DENORM_MIN__ + #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64 + #undef __FLT16_DENORM_MIN__ + #define __FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16 + #undef __FLT128_EPSILON__ + #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128 + #undef __FLT64X_NORM_MAX__ + #define __FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __SIZEOF_POINTER__ + #define __SIZEOF_POINTER__ 8 + #undef __SIZE_TYPE__ + #define __SIZE_TYPE__ long unsigned int + #undef __LP64__ + #define __LP64__ 1 + #undef __DBL_HAS_QUIET_NAN__ + #define __DBL_HAS_QUIET_NAN__ 1 + #undef __FLT32X_EPSILON__ + #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x + #undef __LDBL_MAX_EXP__ + #define __LDBL_MAX_EXP__ 16384 + #undef __DECIMAL_BID_FORMAT__ + #define __DECIMAL_BID_FORMAT__ 1 + #undef __FLT64_MIN_EXP__ + #define __FLT64_MIN_EXP__ (-1021) + #undef __FLT64_MIN_10_EXP__ + #define __FLT64_MIN_10_EXP__ (-307) + #undef __FLT16_MIN_10_EXP__ + #define __FLT16_MIN_10_EXP__ (-4) + #undef __FLT64X_DECIMAL_DIG__ + #define __FLT64X_DECIMAL_DIG__ 21 + #undef __DEC128_MIN__ + #define __DEC128_MIN__ 1E-6143DL + #undef __REGISTER_PREFIX__ + #define __REGISTER_PREFIX__ + #undef __UINT16_MAX__ + #define __UINT16_MAX__ 0xffff + #undef __DBL_HAS_DENORM__ + #define __DBL_HAS_DENORM__ 1 + #undef __FLT32_MIN__ + #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32 + #undef __UINT8_TYPE__ + #define __UINT8_TYPE__ unsigned char + #undef __FLT_DIG__ + #define __FLT_DIG__ 6 + #undef __NO_INLINE__ + #define __NO_INLINE__ 1 + #undef __DEC_EVAL_METHOD__ + #define __DEC_EVAL_METHOD__ 2 + #undef __FLT_MANT_DIG__ + #define __FLT_MANT_DIG__ 24 + #undef __LDBL_DECIMAL_DIG__ + #define __LDBL_DECIMAL_DIG__ 21 + #undef __VERSION__ + #define __VERSION__ "13.1.1 20230429" + #undef __UINT64_C + #define __UINT64_C(c) c ## UL + #undef _STDC_PREDEF_H + #define _STDC_PREDEF_H 1 + #undef __INT_LEAST32_MAX__ + #define __INT_LEAST32_MAX__ 0x7fffffff + #undef __FLT128_MAX_EXP__ + #define __FLT128_MAX_EXP__ 16384 + #undef __FLT32_MANT_DIG__ + #define __FLT32_MANT_DIG__ 24 + #undef __FLOAT_WORD_ORDER__ + #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __FLT32X_MIN_EXP__ + #define __FLT32X_MIN_EXP__ (-1021) + #undef __BFLT16_MIN__ + #define __BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16 + #undef __FLT128_HAS_DENORM__ + #define __FLT128_HAS_DENORM__ 1 + #undef __FLT32_DECIMAL_DIG__ + #define __FLT32_DECIMAL_DIG__ 9 + #undef __FLT128_DIG__ + #define __FLT128_DIG__ 33 + #undef __INT32_C + #define __INT32_C(c) c + #undef __DEC64_EPSILON__ + #define __DEC64_EPSILON__ 1E-15DD + #undef __ORDER_PDP_ENDIAN__ + #define __ORDER_PDP_ENDIAN__ 3412 + #undef __DEC128_MIN_EXP__ + #define __DEC128_MIN_EXP__ (-6142) + #undef __DEC128_MAX__ + #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL + #undef __INT_FAST32_TYPE__ + #define __INT_FAST32_TYPE__ long int + #undef __UINT_LEAST16_TYPE__ + #define __UINT_LEAST16_TYPE__ short unsigned int + #undef __DEC128_MAX_EXP__ + #define __DEC128_MAX_EXP__ 6145 + #undef unix + #define unix 1 + #undef __UINT64_MAX__ + #define __UINT64_MAX__ 0xffffffffffffffffUL + #undef __FLT_IS_IEC_60559__ + #define __FLT_IS_IEC_60559__ 1 + #undef __GNUC_WIDE_EXECUTION_CHARSET_NAME + #define __GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE" + #undef __FLT64X_DIG__ + #define __FLT64X_DIG__ 18 + #undef __INT8_TYPE__ + #define __INT8_TYPE__ signed char + #undef __ELF__ + #define __ELF__ 1 + #undef __UINT32_TYPE__ + #define __UINT32_TYPE__ unsigned int + #undef __BFLT16_HAS_QUIET_NAN__ + #define __BFLT16_HAS_QUIET_NAN__ 1 + #undef __FLT_RADIX__ + #define __FLT_RADIX__ 2 + #undef __INT_LEAST16_TYPE__ + #define __INT_LEAST16_TYPE__ short int + #undef __LDBL_EPSILON__ + #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L + #undef __UINTMAX_C + #define __UINTMAX_C(c) c ## UL + #undef __FLT16_DIG__ + #define __FLT16_DIG__ 3 + #undef __SSE_MATH__ + #define __SSE_MATH__ 1 + #undef __k8 + #define __k8 1 + #undef __FLT32X_MIN__ + #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x + #undef __SIG_ATOMIC_MAX__ + #define __SIG_ATOMIC_MAX__ 0x7fffffff + #undef __USER_LABEL_PREFIX__ + #define __USER_LABEL_PREFIX__ + #undef __SIZEOF_PTRDIFF_T__ + #define __SIZEOF_PTRDIFF_T__ 8 + #undef __FLT64X_HAS_INFINITY__ + #define __FLT64X_HAS_INFINITY__ 1 + #undef __FLT32_HAS_INFINITY__ + #define __FLT32_HAS_INFINITY__ 1 + #undef __SIZEOF_LONG__ + #define __SIZEOF_LONG__ 8 + #undef __LDBL_DIG__ + #define __LDBL_DIG__ 18 + #undef __FLT64_IS_IEC_60559__ + #define __FLT64_IS_IEC_60559__ 1 + #undef __x86_64__ + #define __x86_64__ 1 + #undef __FLT16_IS_IEC_60559__ + #define __FLT16_IS_IEC_60559__ 1 + #undef __FLT16_MAX_EXP__ + #define __FLT16_MAX_EXP__ 16 + #undef __DEC32_SUBNORMAL_MIN__ + #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF + #undef __INT_FAST16_MAX__ + #define __INT_FAST16_MAX__ 0x7fffffffffffffffL + #undef __FLT64_DIG__ + #define __FLT64_DIG__ 15 + #undef __UINT_FAST32_MAX__ + #define __UINT_FAST32_MAX__ 0xffffffffffffffffUL + #undef __UINT_LEAST64_TYPE__ + #define __UINT_LEAST64_TYPE__ long unsigned int + #undef __FLT16_EPSILON__ + #define __FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16 + #undef __FLT_HAS_QUIET_NAN__ + #define __FLT_HAS_QUIET_NAN__ 1 + #undef __FLT_MAX_10_EXP__ + #define __FLT_MAX_10_EXP__ 38 + #undef __LONG_MAX__ + #define __LONG_MAX__ 0x7fffffffffffffffL + #undef __FLT64X_HAS_DENORM__ + #define __FLT64X_HAS_DENORM__ 1 + #undef __DEC128_SUBNORMAL_MIN__ + #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL + #undef __FLT_HAS_INFINITY__ + #define __FLT_HAS_INFINITY__ 1 + #undef __GNUC_EXECUTION_CHARSET_NAME + #define __GNUC_EXECUTION_CHARSET_NAME "UTF-8" + #undef __UINT_FAST16_TYPE__ + #define __UINT_FAST16_TYPE__ long unsigned int + #undef __DEC64_MAX__ + #define __DEC64_MAX__ 9.999999999999999E384DD + #undef __INT_FAST32_WIDTH__ + #define __INT_FAST32_WIDTH__ 64 + #undef __CHAR16_TYPE__ + #define __CHAR16_TYPE__ short unsigned int + #undef __PRAGMA_REDEFINE_EXTNAME + #define __PRAGMA_REDEFINE_EXTNAME 1 + #undef __SIZE_WIDTH__ + #define __SIZE_WIDTH__ 64 + #undef __SEG_FS + #define __SEG_FS 1 + #undef __INT_LEAST16_MAX__ + #define __INT_LEAST16_MAX__ 0x7fff + #undef __FLT16_NORM_MAX__ + #define __FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __DEC64_MANT_DIG__ + #define __DEC64_MANT_DIG__ 16 + #undef __FLT32_DENORM_MIN__ + #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32 + #undef __SIG_ATOMIC_WIDTH__ + #define __SIG_ATOMIC_WIDTH__ 32 + #undef __INT_LEAST64_TYPE__ + #define __INT_LEAST64_TYPE__ long int + #undef __INT16_TYPE__ + #define __INT16_TYPE__ short int + #undef __INT_LEAST8_TYPE__ + #define __INT_LEAST8_TYPE__ signed char + #undef __FLT16_MAX__ + #define __FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16 + #undef __FLT128_MIN__ + #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128 + #undef __SIZEOF_INT__ + #define __SIZEOF_INT__ 4 + #undef __DEC32_MAX_EXP__ + #define __DEC32_MAX_EXP__ 97 + #undef __INT_FAST8_MAX__ + #define __INT_FAST8_MAX__ 0x7f + #undef __FLT128_MAX__ + #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __INTPTR_MAX__ + #define __INTPTR_MAX__ 0x7fffffffffffffffL + #undef linux + #define linux 1 + #undef __FLT64_HAS_QUIET_NAN__ + #define __FLT64_HAS_QUIET_NAN__ 1 + #undef __FLT32_MIN_10_EXP__ + #define __FLT32_MIN_10_EXP__ (-37) + #undef __FLT32X_DIG__ + #define __FLT32X_DIG__ 15 + #undef __UINT16_C + #define __UINT16_C(c) c + #undef __PTRDIFF_WIDTH__ + #define __PTRDIFF_WIDTH__ 64 + #undef __LDBL_MANT_DIG__ + #define __LDBL_MANT_DIG__ 64 + #undef __INT_FAST16_WIDTH__ + #define __INT_FAST16_WIDTH__ 64 + #undef __FLT64_HAS_INFINITY__ + #define __FLT64_HAS_INFINITY__ 1 + #undef __FLT64X_MAX__ + #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x + #undef __FLT16_HAS_INFINITY__ + #define __FLT16_HAS_INFINITY__ 1 + #undef __SIG_ATOMIC_MIN__ + #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) + #undef __code_model_small__ + #define __code_model_small__ 1 + #undef __DEC32_MANT_DIG__ + #define __DEC32_MANT_DIG__ 7 + #undef __FLT16_MANT_DIG__ + #define __FLT16_MANT_DIG__ 11 + #undef __k8__ + #define __k8__ 1 + #undef __INTPTR_TYPE__ + #define __INTPTR_TYPE__ long int + #undef __UINT16_TYPE__ + #define __UINT16_TYPE__ short unsigned int + #undef __WCHAR_TYPE__ + #define __WCHAR_TYPE__ int + #undef __pic__ + #define __pic__ 2 + #undef __UINTPTR_MAX__ + #define __UINTPTR_MAX__ 0xffffffffffffffffUL + #undef __INT_FAST64_WIDTH__ + #define __INT_FAST64_WIDTH__ 64 + #undef __LDBL_HAS_INFINITY__ + #define __LDBL_HAS_INFINITY__ 1 + #undef __INT_FAST64_MAX__ + #define __INT_FAST64_MAX__ 0x7fffffffffffffffL + #undef __FLT_NORM_MAX__ + #define __FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __FLT64X_MAX_EXP__ + #define __FLT64X_MAX_EXP__ 16384 + #undef __UINT_FAST64_TYPE__ + #define __UINT_FAST64_TYPE__ long unsigned int + #undef __BFLT16_MIN_EXP__ + #define __BFLT16_MIN_EXP__ (-125) + #undef __INT_MAX__ + #define __INT_MAX__ 0x7fffffff + #undef __linux__ + #define __linux__ 1 + #undef __INT64_TYPE__ + #define __INT64_TYPE__ long int + #undef __FLT_MAX_EXP__ + #define __FLT_MAX_EXP__ 128 + #undef __ORDER_BIG_ENDIAN__ + #define __ORDER_BIG_ENDIAN__ 4321 + #undef __DBL_MANT_DIG__ + #define __DBL_MANT_DIG__ 53 + #undef __SIZEOF_FLOAT128__ + #define __SIZEOF_FLOAT128__ 16 + #undef __BFLT16_MANT_DIG__ + #define __BFLT16_MANT_DIG__ 8 + #undef __DEC64_MIN__ + #define __DEC64_MIN__ 1E-383DD + #undef __WINT_TYPE__ + #define __WINT_TYPE__ unsigned int + #undef __UINT_LEAST32_TYPE__ + #define __UINT_LEAST32_TYPE__ unsigned int + #undef __SIZEOF_SHORT__ + #define __SIZEOF_SHORT__ 2 + #undef __FLT32_NORM_MAX__ + #define __FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32 + #undef __SSE__ + #define __SSE__ 1 + #undef __LDBL_MIN_EXP__ + #define __LDBL_MIN_EXP__ (-16381) + #undef __FLT64_MAX__ + #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __amd64__ + #define __amd64__ 1 + #undef __WINT_WIDTH__ + #define __WINT_WIDTH__ 32 + #undef __INT_LEAST8_MAX__ + #define __INT_LEAST8_MAX__ 0x7f + #undef __INT_LEAST64_WIDTH__ + #define __INT_LEAST64_WIDTH__ 64 + #undef __FLT32X_MAX_10_EXP__ + #define __FLT32X_MAX_10_EXP__ 308 + #undef __SIZEOF_INT128__ + #define __SIZEOF_INT128__ 16 + #undef __FLT16_MIN__ + #define __FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16 + #undef __FLT64X_IS_IEC_60559__ + #define __FLT64X_IS_IEC_60559__ 1 + #undef __LDBL_MAX_10_EXP__ + #define __LDBL_MAX_10_EXP__ 4932 + #undef __ATOMIC_RELAXED + #define __ATOMIC_RELAXED 0 + #undef __DBL_EPSILON__ + #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) + #undef __INT_LEAST32_TYPE__ + #define __INT_LEAST32_TYPE__ int + #undef _LP64 + #define _LP64 1 + #undef __UINT8_C + #define __UINT8_C(c) c + #undef __FLT64_MAX_EXP__ + #define __FLT64_MAX_EXP__ 1024 + #undef __SIZEOF_WCHAR_T__ + #define __SIZEOF_WCHAR_T__ 4 + #undef __UINT64_TYPE__ + #define __UINT64_TYPE__ long unsigned int + #undef __GNUC_PATCHLEVEL__ + #define __GNUC_PATCHLEVEL__ 1 + #undef __FLT128_NORM_MAX__ + #define __FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128 + #undef __FLT64_NORM_MAX__ + #define __FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64 + #undef __FLT128_HAS_QUIET_NAN__ + #define __FLT128_HAS_QUIET_NAN__ 1 + #undef __INTMAX_MAX__ + #define __INTMAX_MAX__ 0x7fffffffffffffffL + #undef __INT_FAST8_TYPE__ + #define __INT_FAST8_TYPE__ signed char + #undef __FLT64X_MIN__ + #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x + #undef __GNUC_STDC_INLINE__ + #define __GNUC_STDC_INLINE__ 1 + #undef __FLT64_HAS_DENORM__ + #define __FLT64_HAS_DENORM__ 1 + #undef __FLT32_EPSILON__ + #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32 + #undef __FLT16_HAS_DENORM__ + #define __FLT16_HAS_DENORM__ 1 + #undef __DBL_DECIMAL_DIG__ + #define __DBL_DECIMAL_DIG__ 17 + #undef __INT_FAST8_WIDTH__ + #define __INT_FAST8_WIDTH__ 8 + #undef __FXSR__ + #define __FXSR__ 1 + #undef __FLT32X_MAX__ + #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __DBL_NORM_MAX__ + #define __DBL_NORM_MAX__ ((double)1.79769313486231570814527423731704357e+308L) + #undef __BYTE_ORDER__ + #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ + #undef __INTMAX_WIDTH__ + #define __INTMAX_WIDTH__ 64 + #undef __FLT32_DIG__ + #define __FLT32_DIG__ 6 + #undef __UINT32_C + #define __UINT32_C(c) c ## U + #undef __FLT_DENORM_MIN__ + #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F + #undef __INT8_MAX__ + #define __INT8_MAX__ 0x7f + #undef __LONG_WIDTH__ + #define __LONG_WIDTH__ 64 + #undef __DBL_MIN__ + #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) + #undef __PIC__ + #define __PIC__ 2 + #undef __INT32_MAX__ + #define __INT32_MAX__ 0x7fffffff + #undef __UINT_FAST32_TYPE__ + #define __UINT_FAST32_TYPE__ long unsigned int + #undef __FLT32X_NORM_MAX__ + #define __FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x + #undef __CHAR32_TYPE__ + #define __CHAR32_TYPE__ unsigned int + #undef __FLT_MAX__ + #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F + #undef __SSE2__ + #define __SSE2__ 1 + #undef __INT32_TYPE__ + #define __INT32_TYPE__ int + #undef __SIZEOF_DOUBLE__ + #define __SIZEOF_DOUBLE__ 8 + #undef __FLT_MIN_10_EXP__ + #define __FLT_MIN_10_EXP__ (-37) + #undef __FLT64_MIN__ + #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64 + #undef __INT_LEAST32_WIDTH__ + #define __INT_LEAST32_WIDTH__ 32 + #undef __INTMAX_TYPE__ + #define __INTMAX_TYPE__ long int + #undef __FLT32X_HAS_QUIET_NAN__ + #define __FLT32X_HAS_QUIET_NAN__ 1 + #undef __ATOMIC_CONSUME + #define __ATOMIC_CONSUME 1 + #undef __GNUC_MINOR__ + #define __GNUC_MINOR__ 1 + #undef __UINTMAX_MAX__ + #define __UINTMAX_MAX__ 0xffffffffffffffffUL + #undef __PIE__ + #define __PIE__ 2 + #undef __FLT32X_DENORM_MIN__ + #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x + #undef __DBL_MAX_10_EXP__ + #define __DBL_MAX_10_EXP__ 308 + #undef __LDBL_DENORM_MIN__ + #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L + #undef __INT16_C + #define __INT16_C(c) c + #undef __PTRDIFF_TYPE__ + #define __PTRDIFF_TYPE__ long int + #undef __FLT32X_MIN_10_EXP__ + #define __FLT32X_MIN_10_EXP__ (-307) + #undef __UINTPTR_TYPE__ + #define __UINTPTR_TYPE__ long unsigned int + #undef __DEC64_SUBNORMAL_MIN__ + #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD + #undef __DEC128_MANT_DIG__ + #define __DEC128_MANT_DIG__ 34 + #undef __LDBL_MIN_10_EXP__ + #define __LDBL_MIN_10_EXP__ (-4931) + #undef __SIZEOF_LONG_LONG__ + #define __SIZEOF_LONG_LONG__ 8 + #undef __FLT128_DECIMAL_DIG__ + #define __FLT128_DECIMAL_DIG__ 36 + #undef __FLT32_HAS_QUIET_NAN__ + #define __FLT32_HAS_QUIET_NAN__ 1 + #undef __FLT_DECIMAL_DIG__ + #define __FLT_DECIMAL_DIG__ 9 + #undef __UINT_FAST16_MAX__ + #define __UINT_FAST16_MAX__ 0xffffffffffffffffUL + #undef __LDBL_NORM_MAX__ + #define __LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L + #undef __SIZE_MAX__ + #define __SIZE_MAX__ 0xffffffffffffffffUL + #undef __UINT_FAST8_TYPE__ + #define __UINT_FAST8_TYPE__ unsigned char + #undef __ATOMIC_ACQ_REL + #define __ATOMIC_ACQ_REL 4 + #undef __ATOMIC_RELEASE + #define __ATOMIC_RELEASE 3 +eof: (-1) +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotrecoverable: '131' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eownerdead: '130' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +filename_max: '4096' +fopen_max: '16' +has__builtin_va_list: true +host_name_max: '64' +int_fast16_t: long +int_fast32_t: long +int_fast64_t: long +int_fast8_t: signed char +intptr_t: long +l_tmpnam: '20' +little_endian: true +machdep_name: machdep_x86_64 +mb_cur_max: ((size_t) 16 ) +nsig: (64 + 1) +path_max: '4096' +posix_version: 200809L +ptrdiff_t: long +rand_max: '2147483647' +sig_atomic_t: int +size_t: unsigned long +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: -1 +sizeof_int: 4 +sizeof_long: 8 +sizeof_longdouble: 16 +sizeof_longlong: 8 +sizeof_ptr: 8 +sizeof_short: 2 +sizeof_void: -1 +ssize_t: long +time_t: long +tmp_max: '238328' +tty_name_max: '32' +uint_fast16_t: unsigned long +uint_fast32_t: unsigned long +uint_fast64_t: unsigned long +uint_fast8_t: unsigned char +uintptr_t: unsigned long +version: gcc (GCC) 13.1.1 20230429 +wchar_t: int +weof: (0xffffffffu) +wint_t: unsigned int +wordsize: '64' diff --git a/share/machdeps/make_machdep/.gitignore b/share/machdeps/make_machdep/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5761abcfdf0c26a75374c945dfe366eaeee04285 --- /dev/null +++ b/share/machdeps/make_machdep/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/share/machdeps/make_machdep/alignof_aligned.c b/share/machdeps/make_machdep/alignof_aligned.c new file mode 100644 index 0000000000000000000000000000000000000000..8d37ca3c5f94b8f0343dc16b4499710dcd023172 --- /dev/null +++ b/share/machdeps/make_machdep/alignof_aligned.c @@ -0,0 +1,42 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" + +typedef char array[1] __attribute__((__aligned__)); + +_Static_assert(ALIGNOF(array)!=1, "alignof_aligned is 1"); +_Static_assert(ALIGNOF(array)!=2, "alignof_aligned is 2"); +_Static_assert(ALIGNOF(array)!=3, "alignof_aligned is 3"); +_Static_assert(ALIGNOF(array)!=4, "alignof_aligned is 4"); +_Static_assert(ALIGNOF(array)!=5, "alignof_aligned is 5"); +_Static_assert(ALIGNOF(array)!=6, "alignof_aligned is 6"); +_Static_assert(ALIGNOF(array)!=7, "alignof_aligned is 7"); +_Static_assert(ALIGNOF(array)!=8, "alignof_aligned is 8"); +_Static_assert(ALIGNOF(array)!=9, "alignof_aligned is 9"); +_Static_assert(ALIGNOF(array)!=10, "alignof_aligned is 10"); +_Static_assert(ALIGNOF(array)!=11, "alignof_aligned is 11"); +_Static_assert(ALIGNOF(array)!=12, "alignof_aligned is 12"); +_Static_assert(ALIGNOF(array)!=13, "alignof_aligned is 13"); +_Static_assert(ALIGNOF(array)!=14, "alignof_aligned is 14"); +_Static_assert(ALIGNOF(array)!=15, "alignof_aligned is 15"); +_Static_assert(ALIGNOF(array)!=16, "alignof_aligned is 16"); diff --git a/share/machdeps/make_machdep/alignof_double.c b/share/machdeps/make_machdep/alignof_double.c new file mode 100644 index 0000000000000000000000000000000000000000..3ad3c9526be103cbb5f4ce11a6ae5d7b83174d13 --- /dev/null +++ b/share/machdeps/make_machdep/alignof_double.c @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" + +_Static_assert(ALIGNOF(double) != 1, "alignof_double is 1"); +_Static_assert(ALIGNOF(double) != 2, "alignof_double is 2"); +_Static_assert(ALIGNOF(double) != 3, "alignof_double is 3"); +_Static_assert(ALIGNOF(double) != 4, "alignof_double is 4"); +_Static_assert(ALIGNOF(double) != 5, "alignof_double is 5"); +_Static_assert(ALIGNOF(double) != 6, "alignof_double is 6"); +_Static_assert(ALIGNOF(double) != 7, "alignof_double is 7"); +_Static_assert(ALIGNOF(double) != 8, "alignof_double is 8"); diff --git a/share/machdeps/make_machdep/alignof_float.c b/share/machdeps/make_machdep/alignof_float.c new file mode 100644 index 0000000000000000000000000000000000000000..2bbb0bf8967db1baa1a3889a27041d123d5f4e7f --- /dev/null +++ b/share/machdeps/make_machdep/alignof_float.c @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" + +_Static_assert(ALIGNOF(float) != 1, "alignof_float is 1"); +_Static_assert(ALIGNOF(float) != 2, "alignof_float is 2"); +_Static_assert(ALIGNOF(float) != 3, "alignof_float is 3"); +_Static_assert(ALIGNOF(float) != 4, "alignof_float is 4"); +_Static_assert(ALIGNOF(float) != 5, "alignof_float is 5"); +_Static_assert(ALIGNOF(float) != 6, "alignof_float is 6"); +_Static_assert(ALIGNOF(float) != 7, "alignof_float is 7"); +_Static_assert(ALIGNOF(float) != 8, "alignof_float is 8"); diff --git a/share/machdeps/make_machdep/alignof_fun.c b/share/machdeps/make_machdep/alignof_fun.c new file mode 100644 index 0000000000000000000000000000000000000000..0d26a6404280d6eecfe27e0f8eba5c758df8a688 --- /dev/null +++ b/share/machdeps/make_machdep/alignof_fun.c @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" + +_Static_assert(ALIGNOF(void()) != 1, "alignof_fun is 1"); +_Static_assert(ALIGNOF(void()) != 2, "alignof_fun is 2"); +_Static_assert(ALIGNOF(void()) != 3, "alignof_fun is 3"); +_Static_assert(ALIGNOF(void()) != 4, "alignof_fun is 4"); +_Static_assert(ALIGNOF(void()) != 5, "alignof_fun is 5"); +_Static_assert(ALIGNOF(void()) != 6, "alignof_fun is 6"); +_Static_assert(ALIGNOF(void()) != 7, "alignof_fun is 7"); +_Static_assert(ALIGNOF(void()) != 8, "alignof_fun is 8"); diff --git a/share/machdeps/make_machdep/alignof_int.c b/share/machdeps/make_machdep/alignof_int.c new file mode 100644 index 0000000000000000000000000000000000000000..a83f429cd061be487e130f0fc69330cdb8e563a5 --- /dev/null +++ b/share/machdeps/make_machdep/alignof_int.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +_Static_assert(ALIGNOF(int) != 1, "alignof_int is 1"); +_Static_assert(ALIGNOF(int) != 2, "alignof_int is 2"); +_Static_assert(ALIGNOF(int) != 3, "alignof_int is 3"); +_Static_assert(ALIGNOF(int) != 4, "alignof_int is 4"); +_Static_assert(ALIGNOF(int) != 5, "alignof_int is 5"); +_Static_assert(ALIGNOF(int) != 6, "alignof_int is 6"); +_Static_assert(ALIGNOF(int) != 7, "alignof_int is 7"); +_Static_assert(ALIGNOF(int) != 8, "alignof_int is 8"); diff --git a/share/machdeps/make_machdep/alignof_long.c b/share/machdeps/make_machdep/alignof_long.c new file mode 100644 index 0000000000000000000000000000000000000000..f34ec3ca89f349404fbe181edf9c90adc78fb85f --- /dev/null +++ b/share/machdeps/make_machdep/alignof_long.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +_Static_assert(ALIGNOF(long) != 1, "alignof_long is 1"); +_Static_assert(ALIGNOF(long) != 2, "alignof_long is 2"); +_Static_assert(ALIGNOF(long) != 3, "alignof_long is 3"); +_Static_assert(ALIGNOF(long) != 4, "alignof_long is 4"); +_Static_assert(ALIGNOF(long) != 5, "alignof_long is 5"); +_Static_assert(ALIGNOF(long) != 6, "alignof_long is 6"); +_Static_assert(ALIGNOF(long) != 7, "alignof_long is 7"); +_Static_assert(ALIGNOF(long) != 8, "alignof_long is 8"); diff --git a/share/machdeps/make_machdep/alignof_longdouble.c b/share/machdeps/make_machdep/alignof_longdouble.c new file mode 100644 index 0000000000000000000000000000000000000000..0cd52668fe54cad32a0b0d26429259927365b5e7 --- /dev/null +++ b/share/machdeps/make_machdep/alignof_longdouble.c @@ -0,0 +1,40 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" + +_Static_assert(ALIGNOF(long double) != 1, "alignof_longdouble is 1"); +_Static_assert(ALIGNOF(long double) != 2, "alignof_longdouble is 2"); +_Static_assert(ALIGNOF(long double) != 3, "alignof_longdouble is 3"); +_Static_assert(ALIGNOF(long double) != 4, "alignof_longdouble is 4"); +_Static_assert(ALIGNOF(long double) != 5, "alignof_longdouble is 5"); +_Static_assert(ALIGNOF(long double) != 6, "alignof_longdouble is 6"); +_Static_assert(ALIGNOF(long double) != 7, "alignof_longdouble is 7"); +_Static_assert(ALIGNOF(long double) != 8, "alignof_longdouble is 8"); +_Static_assert(ALIGNOF(long double) != 9, "alignof_longdouble is 9"); +_Static_assert(ALIGNOF(long double) != 10, "alignof_longdouble is 10"); +_Static_assert(ALIGNOF(long double) != 11, "alignof_longdouble is 11"); +_Static_assert(ALIGNOF(long double) != 12, "alignof_longdouble is 12"); +_Static_assert(ALIGNOF(long double) != 13, "alignof_longdouble is 13"); +_Static_assert(ALIGNOF(long double) != 14, "alignof_longdouble is 14"); +_Static_assert(ALIGNOF(long double) != 15, "alignof_longdouble is 15"); +_Static_assert(ALIGNOF(long double) != 16, "alignof_longdouble is 16"); diff --git a/share/machdeps/make_machdep/alignof_longlong.c b/share/machdeps/make_machdep/alignof_longlong.c new file mode 100644 index 0000000000000000000000000000000000000000..222eba81362a4089b7af59a5ff0891817be497be --- /dev/null +++ b/share/machdeps/make_machdep/alignof_longlong.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +_Static_assert(ALIGNOF(long long) != 1, "alignof_longlong is 1"); +_Static_assert(ALIGNOF(long long) != 2, "alignof_longlong is 2"); +_Static_assert(ALIGNOF(long long) != 3, "alignof_longlong is 3"); +_Static_assert(ALIGNOF(long long) != 4, "alignof_longlong is 4"); +_Static_assert(ALIGNOF(long long) != 5, "alignof_longlong is 5"); +_Static_assert(ALIGNOF(long long) != 6, "alignof_longlong is 6"); +_Static_assert(ALIGNOF(long long) != 7, "alignof_longlong is 7"); +_Static_assert(ALIGNOF(long long) != 8, "alignof_longlong is 8"); diff --git a/share/machdeps/make_machdep/alignof_ptr.c b/share/machdeps/make_machdep/alignof_ptr.c new file mode 100644 index 0000000000000000000000000000000000000000..babe1cd560d7277132648ee2a6396bd2910768a9 --- /dev/null +++ b/share/machdeps/make_machdep/alignof_ptr.c @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" + +_Static_assert(ALIGNOF(void *) != 1, "alignof_ptr is 1"); +_Static_assert(ALIGNOF(void *) != 2, "alignof_ptr is 2"); +_Static_assert(ALIGNOF(void *) != 3, "alignof_ptr is 3"); +_Static_assert(ALIGNOF(void *) != 4, "alignof_ptr is 4"); +_Static_assert(ALIGNOF(void *) != 5, "alignof_ptr is 5"); +_Static_assert(ALIGNOF(void *) != 6, "alignof_ptr is 6"); +_Static_assert(ALIGNOF(void *) != 7, "alignof_ptr is 7"); +_Static_assert(ALIGNOF(void *) != 8, "alignof_ptr is 8"); diff --git a/share/machdeps/make_machdep/alignof_short.c b/share/machdeps/make_machdep/alignof_short.c new file mode 100644 index 0000000000000000000000000000000000000000..7e1c66cfa417d6a94081d640443911add7c316fa --- /dev/null +++ b/share/machdeps/make_machdep/alignof_short.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +_Static_assert(ALIGNOF(short) != 1, "alignof_short is 1"); +_Static_assert(ALIGNOF(short) != 2, "alignof_short is 2"); +_Static_assert(ALIGNOF(short) != 3, "alignof_short is 3"); +_Static_assert(ALIGNOF(short) != 4, "alignof_short is 4"); +_Static_assert(ALIGNOF(short) != 5, "alignof_short is 5"); +_Static_assert(ALIGNOF(short) != 6, "alignof_short is 6"); +_Static_assert(ALIGNOF(short) != 7, "alignof_short is 7"); +_Static_assert(ALIGNOF(short) != 8, "alignof_short is 8"); diff --git a/share/machdeps/make_machdep/alignof_str.c b/share/machdeps/make_machdep/alignof_str.c new file mode 100644 index 0000000000000000000000000000000000000000..51ba68521cd21c26e24fcd5f362f4e4c1cb2cb5b --- /dev/null +++ b/share/machdeps/make_machdep/alignof_str.c @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" + +_Static_assert(ALIGNOF("test string") != 1, "alignof_str is 1"); +_Static_assert(ALIGNOF("test string") != 2, "alignof_str is 2"); +_Static_assert(ALIGNOF("test string") != 3, "alignof_str is 3"); +_Static_assert(ALIGNOF("test string") != 4, "alignof_str is 4"); +_Static_assert(ALIGNOF("test string") != 5, "alignof_str is 5"); +_Static_assert(ALIGNOF("test string") != 6, "alignof_str is 6"); +_Static_assert(ALIGNOF("test string") != 7, "alignof_str is 7"); +_Static_assert(ALIGNOF("test string") != 8, "alignof_str is 8"); diff --git a/share/machdeps/make_machdep/char_is_unsigned.c b/share/machdeps/make_machdep/char_is_unsigned.c new file mode 100644 index 0000000000000000000000000000000000000000..46ad63d750231360d7f276aa2d62e04f31e5cfd5 --- /dev/null +++ b/share/machdeps/make_machdep/char_is_unsigned.c @@ -0,0 +1,24 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert((char)-1 >= 0 ? 1 : 0, "char_is_unsigned is False"); +_Static_assert((char)-1 >= 0 ? 0 : 1, "char_is_unsigned is True"); diff --git a/share/machdeps/make_machdep/const_string_literals.c b/share/machdeps/make_machdep/const_string_literals.c new file mode 100644 index 0000000000000000000000000000000000000000..35fb4e651ec1e4c5ba3f07033d19e1085bb37137 --- /dev/null +++ b/share/machdeps/make_machdep/const_string_literals.c @@ -0,0 +1,23 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +char *const_string_literals = "%$#!"; diff --git a/share/machdeps/make_machdep/errno.c b/share/machdeps/make_machdep/errno.c new file mode 100644 index 0000000000000000000000000000000000000000..a6c2829d87f7e686c129f4f7c691abc9df57d0c8 --- /dev/null +++ b/share/machdeps/make_machdep/errno.c @@ -0,0 +1,393 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <errno.h> + +/* Mandatory */ +#ifdef EDOM +int edom_is = EDOM; +#endif +#ifdef EILSEQ +int eilseq_is = EILSEQ; +#endif +#ifdef ERANGE +int erange_is = ERANGE; +#endif + +/* Implementation defined by POSIX and GNU Linux */ +#ifdef E2BIG +int e2big_is = E2BIG; +#endif +#ifdef EACCES +int eacces_is = EACCES; +#endif +#ifdef EADDRINUSE +int eaddrinuse_is = EADDRINUSE; +#endif +#ifdef EADDRNOTAVAIL +int eaddrnotavail_is = EADDRNOTAVAIL; +#endif +#ifdef EAFNOSUPPORT +int eafnosupport_is = EAFNOSUPPORT; +#endif +#ifdef EAGAIN +int eagain_is = EAGAIN; +#endif +#ifdef EALREADY +int ealready_is = EALREADY; +#endif +#ifdef EBADE +int ebade_is = EBADE; +#endif +#ifdef EBADF +int ebadf_is = EBADF; +#endif +#ifdef EBADFD +int ebadfd_is = EBADFD; +#endif +#ifdef EBADMSG +int ebadmsg_is = EBADMSG; +#endif +#ifdef EBADR +int ebadr_is = EBADR; +#endif +#ifdef EBADRQC +int ebadrqc_is = EBADRQC; +#endif +#ifdef EBADSLT +int ebadslt_is = EBADSLT; +#endif +#ifdef EBUSY +int ebusy_is = EBUSY; +#endif +#ifdef ECANCELED +int ecanceled_is = ECANCELED; +#endif +#ifdef ECHILD +int echild_is = ECHILD; +#endif +#ifdef ECHRNG +int echrng_is = ECHRNG; +#endif +#ifdef ECOMM +int ecomm_is = ECOMM; +#endif +#ifdef ECONNABORTED +int econnaborted_is = ECONNABORTED; +#endif +#ifdef ECONNREFUSED +int econnrefused_is = ECONNREFUSED; +#endif +#ifdef ECONNRESET +int econnreset_is = ECONNRESET; +#endif +#ifdef EDEADLK +int edeadlk_is = EDEADLK; +#endif +#ifdef EDEADLOCK +int edeadlock_is = EDEADLOCK; +#endif +#ifdef EDESTADDRREQ +int edestaddrreq_is = EDESTADDRREQ; +#endif +#ifdef EDQUOT +int edquot_is = EDQUOT; +#endif +#ifdef EEXIST +int eexist_is = EEXIST; +#endif +#ifdef EFAULT +int efault_is = EFAULT; +#endif +#ifdef EFBIG +int efbig_is = EFBIG; +#endif +#ifdef EHOSTDOWN +int ehostdown_is = EHOSTDOWN; +#endif +#ifdef EHOSTUNREACH +int ehostunreach_is = EHOSTUNREACH; +#endif +#ifdef EIDRM +int eidrm_is = EIDRM; +#endif +#ifdef EINPROGRESS +int einprogress_is = EINPROGRESS; +#endif +#ifdef EINTR +int eintr_is = EINTR; +#endif +#ifdef EINVAL +int einval_is = EINVAL; +#endif +#ifdef EIO +int eio_is = EIO; +#endif +#ifdef EISCONN +int eisconn_is = EISCONN; +#endif +#ifdef EISDIR +int eisdir_is = EISDIR; +#endif +#ifdef EISNAM +int eisnam_is = EISNAM; +#endif +#ifdef EKEYEXPIRED +int ekeyexpired_is = EKEYEXPIRED; +#endif +#ifdef EKEYREJECTED +int ekeyrejected_is = EKEYREJECTED; +#endif +#ifdef EKEYREVOKED +int ekeyrevoked_is = EKEYREVOKED; +#endif +#ifdef EL2HLT +int el2hlt_is = EL2HLT; +#endif +#ifdef EL2NSYNC +int el2nsync_is = EL2NSYNC; +#endif +#ifdef EL3HLT +int el3hlt_is = EL3HLT; +#endif +#ifdef EL3RST +int el3rst_is = EL3RST; +#endif +#ifdef ELIBACC +int elibacc_is = ELIBACC; +#endif +#ifdef ELIBBAD +int elibbad_is = ELIBBAD; +#endif +#ifdef ELIBMAX +int elibmax_is = ELIBMAX; +#endif +#ifdef ELIBSCN +int elibscn_is = ELIBSCN; +#endif +#ifdef ELIBEXEC +int elibexec_is = ELIBEXEC; +#endif +#ifdef ELOOP +int eloop_is = ELOOP; +#endif +#ifdef EMEDIUMTYPE +int emediumtype_is = EMEDIUMTYPE; +#endif +#ifdef EMFILE +int emfile_is = EMFILE; +#endif +#ifdef EMLINK +int emlink_is = EMLINK; +#endif +#ifdef EMSGSIZE +int emsgsize_is = EMSGSIZE; +#endif +#ifdef EMULTIHOP +int emultihop_is = EMULTIHOP; +#endif +#ifdef ENAMETOOLONG +int enametoolong_is = ENAMETOOLONG; +#endif +#ifdef ENETDOWN +int enetdown_is = ENETDOWN; +#endif +#ifdef ENETRESET +int enetreset_is = ENETRESET; +#endif +#ifdef ENETUNREACH +int enetunreach_is = ENETUNREACH; +#endif +#ifdef ENFILE +int enfile_is = ENFILE; +#endif +#ifdef ENOBUFS +int enobufs_is = ENOBUFS; +#endif +#ifdef ENODATA +int enodata_is = ENODATA; +#endif +#ifdef ENODEV +int enodev_is = ENODEV; +#endif +#ifdef ENOENT +int enoent_is = ENOENT; +#endif +#ifdef ENOEXEC +int enoexec_is = ENOEXEC; +#endif +#ifdef ENOKEY +int enokey_is = ENOKEY; +#endif +#ifdef ENOLCK +int enolck_is = ENOLCK; +#endif +#ifdef ENOLINK +int enolink_is = ENOLINK; +#endif +#ifdef ENOMEDIUM +int enomedium_is = ENOMEDIUM; +#endif +#ifdef ENOMEM +int enomem_is = ENOMEM; +#endif +#ifdef ENOMSG +int enomsg_is = ENOMSG; +#endif +#ifdef ENONET +int enonet_is = ENONET; +#endif +#ifdef ENOPKG +int enopkg_is = ENOPKG; +#endif +#ifdef ENOPROTOOPT +int enoprotoopt_is = ENOPROTOOPT; +#endif +#ifdef ENOSPC +int enospc_is = ENOSPC; +#endif +#ifdef ENOSR +int enosr_is = ENOSR; +#endif +#ifdef ENOSTR +int enostr_is = ENOSTR; +#endif +#ifdef ENOSYS +int enosys_is = ENOSYS; +#endif +#ifdef ENOTBLK +int enotblk_is = ENOTBLK; +#endif +#ifdef ENOTCONN +int enotconn_is = ENOTCONN; +#endif +#ifdef ENOTDIR +int enotdir_is = ENOTDIR; +#endif +#ifdef ENOTEMPTY +int enotempty_is = ENOTEMPTY; +#endif +#ifdef ENOTRECOVERABLE +int enotrecoverable_is = ENOTRECOVERABLE; +#endif +#ifdef ENOTSOCK +int enotsock_is = ENOTSOCK; +#endif +#ifdef ENOTSUP +int enotsup_is = ENOTSUP; +#endif +#ifdef ENOTTY +int enotty_is = ENOTTY; +#endif +#ifdef ENOTUNIQ +int enotuniq_is = ENOTUNIQ; +#endif +#ifdef ENXIO +int enxio_is = ENXIO; +#endif +#ifdef EOPNOTSUPP +int eopnotsupp_is = EOPNOTSUPP; +#endif +#ifdef EOVERFLOW +int eoverflow_is = EOVERFLOW; +#endif +#ifdef EOWNERDEAD +int eownerdead_is = EOWNERDEAD; +#endif +#ifdef EPERM +int eperm_is = EPERM; +#endif +#ifdef EPFNOSUPPORT +int epfnosupport_is = EPFNOSUPPORT; +#endif +#ifdef EPIPE +int epipe_is = EPIPE; +#endif +#ifdef EPROTO +int eproto_is = EPROTO; +#endif +#ifdef EPROTONOSUPPORT +int eprotonosupport_is = EPROTONOSUPPORT; +#endif +#ifdef EPROTOTYPE +int eprototype_is = EPROTOTYPE; +#endif +#ifdef EREMCHG +int eremchg_is = EREMCHG; +#endif +#ifdef EREMOTE +int eremote_is = EREMOTE; +#endif +#ifdef EREMOTEIO +int eremoteio_is = EREMOTEIO; +#endif +#ifdef ERESTART +int erestart_is = ERESTART; +#endif +#ifdef EROFS +int erofs_is = EROFS; +#endif +#ifdef ESHUTDOWN +int eshutdown_is = ESHUTDOWN; +#endif +#ifdef ESPIPE +int espipe_is = ESPIPE; +#endif +#ifdef ESOCKTNOSUPPORT +int esocktnosupport_is = ESOCKTNOSUPPORT; +#endif +#ifdef ESRCH +int esrch_is = ESRCH; +#endif +#ifdef ESTALE +int estale_is = ESTALE; +#endif +#ifdef ESTRPIPE +int estrpipe_is = ESTRPIPE; +#endif +#ifdef ETIME +int etime_is = ETIME; +#endif +#ifdef ETIMEDOUT +int etimedout_is = ETIMEDOUT; +#endif +#ifdef ETXTBSY +int etxtbsy_is = ETXTBSY; +#endif +#ifdef EUCLEAN +int euclean_is = EUCLEAN; +#endif +#ifdef EUNATCH +int eunatch_is = EUNATCH; +#endif +#ifdef EUSERS +int eusers_is = EUSERS; +#endif +#ifdef EWOULDBLOCK +int ewouldblock_is = EWOULDBLOCK; +#endif +#ifdef EXDEV +int exdev_is = EXDEV; +#endif +#ifdef EXFULL +int exfull_is = EXFULL; +#endif diff --git a/share/machdeps/make_machdep/has__builtin_va_list.c b/share/machdeps/make_machdep/has__builtin_va_list.c new file mode 100644 index 0000000000000000000000000000000000000000..4f2420598eca140e508b6f6259185edadea87388 --- /dev/null +++ b/share/machdeps/make_machdep/has__builtin_va_list.c @@ -0,0 +1,24 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +/* If this compiles, we assume the compiler has __builtin_va_list. */ +__builtin_va_list l = {0}; diff --git a/share/machdeps/make_machdep/int_fast16_t.c b/share/machdeps/make_machdep/int_fast16_t.c new file mode 100644 index 0000000000000000000000000000000000000000..77a451ab2da7c881ce840e8e679aabb89f874444 --- /dev/null +++ b/share/machdeps/make_machdep/int_fast16_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE int_fast16_t + +TEST_TYPE_IS(signed char); +TEST_TYPE_IS(short); +TEST_TYPE_IS(int); +TEST_TYPE_IS(long); +TEST_TYPE_IS(long long); diff --git a/share/machdeps/make_machdep/int_fast32_t.c b/share/machdeps/make_machdep/int_fast32_t.c new file mode 100644 index 0000000000000000000000000000000000000000..fbbfee3a162b972732022954b08a3bd57bcee3ba --- /dev/null +++ b/share/machdeps/make_machdep/int_fast32_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE int_fast32_t + +TEST_TYPE_IS(signed char); +TEST_TYPE_IS(short); +TEST_TYPE_IS(int); +TEST_TYPE_IS(long); +TEST_TYPE_IS(long long); diff --git a/share/machdeps/make_machdep/int_fast64_t.c b/share/machdeps/make_machdep/int_fast64_t.c new file mode 100644 index 0000000000000000000000000000000000000000..43b3ce1797a450aa87a14a06646c4a0eb50cbd29 --- /dev/null +++ b/share/machdeps/make_machdep/int_fast64_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE int_fast64_t + +TEST_TYPE_IS(signed char); +TEST_TYPE_IS(short); +TEST_TYPE_IS(int); +TEST_TYPE_IS(long); +TEST_TYPE_IS(long long); diff --git a/share/machdeps/make_machdep/int_fast8_t.c b/share/machdeps/make_machdep/int_fast8_t.c new file mode 100644 index 0000000000000000000000000000000000000000..6d572f914dee75cba1307076181000cea8495ca1 --- /dev/null +++ b/share/machdeps/make_machdep/int_fast8_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE int_fast8_t + +TEST_TYPE_IS(signed char); +TEST_TYPE_IS(short); +TEST_TYPE_IS(int); +TEST_TYPE_IS(long); +TEST_TYPE_IS(long long); diff --git a/share/machdeps/make_machdep/intptr_t.c b/share/machdeps/make_machdep/intptr_t.c new file mode 100644 index 0000000000000000000000000000000000000000..ec1f36e633d82dd9609870cfc937498a15cf661c --- /dev/null +++ b/share/machdeps/make_machdep/intptr_t.c @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE intptr_t + +TEST_TYPE_IS(int); +TEST_TYPE_IS(long); +TEST_TYPE_IS(long long); diff --git a/share/machdeps/make_machdep/limits_macros.c b/share/machdeps/make_machdep/limits_macros.c new file mode 100644 index 0000000000000000000000000000000000000000..e6d7abd64c4d6b24b10dfc605bd47da2704f9009 --- /dev/null +++ b/share/machdeps/make_machdep/limits_macros.c @@ -0,0 +1,35 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <limits.h> + +#if defined(PATH_MAX) +int path_max_is = PATH_MAX; +#endif + +#if defined(TTY_NAME_MAX) +int tty_name_max_is = TTY_NAME_MAX; +#endif + +#if defined(HOST_NAME_MAX) +int host_name_max_is = HOST_NAME_MAX; +#endif diff --git a/share/machdeps/make_machdep/little_endian.c b/share/machdeps/make_machdep/little_endian.c new file mode 100644 index 0000000000000000000000000000000000000000..2e1404de7a3f0595bab45fd9cdb20dbbbe91ba98 --- /dev/null +++ b/share/machdeps/make_machdep/little_endian.c @@ -0,0 +1,33 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +#if defined(__BYTE_ORDER__) +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +_Static_assert(0, "little_endian is False"); +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +_Static_assert(0, "little_endian is True"); +#else +#error Unexpected __BYTE_ORDER__ +#endif +#else +#error __BYTE_ORDER__ undefined +#endif diff --git a/share/machdeps/make_machdep/make_machdep.py b/share/machdeps/make_machdep/make_machdep.py new file mode 100755 index 0000000000000000000000000000000000000000..bd0b6cefa82eeebfdbf575326681d26122018c34 --- /dev/null +++ b/share/machdeps/make_machdep/make_machdep.py @@ -0,0 +1,438 @@ +#!/usr/bin/env python +########################################################################## +# # +# This file is part of Frama-C. # +# # +# Copyright (C) 2007-2023 # +# 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). # +# # +########################################################################## + +""" +Produces a machdep.yaml file for a given architecture. + +Prerequisites: + +- A C11-compatible (cross-)compiler (with support for _Generic), +- A (cross-)compiler supporting _Static_assert +- A (cross-)compiler supporting _Alignof or alignof + +This script tries to compile several source files to extract the +information we need in terms of sizeof, alignof and representation +of the various types defined by the standard (e.g. size_t, wchar_t, ...) + +In case some values are not identified, the YAML format can be edited +by hand afterwards. +""" + +import argparse +from pathlib import Path +import re +import subprocess +import sys +import logging +import yaml +from yaml.representer import Representer + +my_path = Path(sys.argv[0]).parent + +logging.basicConfig(format="%(levelname)s: %(message)s") + +parser = argparse.ArgumentParser(prog="make_machdep") +parser.add_argument("-v", "--verbose", action="store_true") +parser.add_argument("-o", type=argparse.FileType("w"), dest="dest_file") +parser.add_argument("--compiler", default="cc", help="which compiler to use; default is 'cc'") +parser.add_argument( + "--compiler-version", + default="--version", + help="option to pass to the compiler to obtain its version; default is --version", +) + +parser.add_argument( + "--from-file", + help="reads compiler and arch flags from existing yaml file. Use -i to update it in place", +) +parser.add_argument( + "-i", + "--in-place", + action="store_true", + help="when reading compiler config from yaml, update the file in place. unused otherwise", +) + +parser.add_argument( + "--cpp-arch-flags", + nargs="+", + action="extend", + help="architecture-specific flags needed for preprocessing, e.g. '-m32'", +) +parser.add_argument( + "--compiler-flags", + nargs="+", + action="extend", + type=str, + help="flags to be given to the compiler (other than those set by --cpp-arch-flags); default is '-c'", +) +parser.add_argument( + "--check", + action="store_true", + help="checks that the generated machdep is conforming to the schema", +) +parser.add_argument( + "--check-only", + action="store_true", + help="must be used in conjunction with --from-file to check that the provided input file is conforming to the schema", +) + +args, other_args = parser.parse_known_args() + +if not args.compiler_flags: + args.compiler_flags = ["-c"] + +if not args.cpp_arch_flags: + args.cpp_arch_flags = [] + + +def make_schema(): + schema_filename = my_path.parent / "machdep-schema.yaml" + with open(schema_filename, "r") as schema: + return yaml.safe_load(schema) + + +schema = make_schema() + + +def check_machdep(machdep): + try: + from jsonschema import validate, ValidationError + + validate(machdep, schema) + return True + except ImportError: + logging.warning("jsonschema is not available: no validation will be performed") + return True + except ValidationError: + logging.warning("machdep object is not conforming to machdep schema") + return False + + +if args.from_file: + orig_file = open(args.from_file, "r") + orig_machdep = yaml.safe_load(orig_file) + orig_file.close() + if args.check_only: + if check_machdep(orig_machdep): + sys.exit(0) + else: + sys.exit(1) + if not "compiler" in orig_machdep or not "cpp_arch_flags" in orig_machdep: + raise Exception("Missing fields in yaml file") + args.compiler = orig_machdep["compiler"] + if isinstance(orig_machdep["cpp_arch_flags"], list): + args.cpp_arch_flags = orig_machdep["cpp_arch_flags"] + else: # old version of the schema used a single string + args.cpp_arch_flags = orig_machdep["cpp_arch_flags"].split() + + +def print_machdep(machdep): + if args.from_file and args.in_place: + args.dest_file = open(args.from_file, "w") + elif args.dest_file is None: + args.dest_file = sys.stdout + yaml.dump(machdep, args.dest_file, indent=4, sort_keys=True) + + +def default_value(typ): + if typ == "integer": + return -1 + if typ == "boolean": + return False + if typ == "string": + return "" + if typ == "list": + return {} + logging.warning(f"Unexpected type {typ} in YAML schema") + return None + + +def make_machdep(): + machdep = {} + for key in schema: + machdep[key] = None + return machdep + + +machdep = make_machdep() + +compilation_command = [args.compiler] + +for flag in args.cpp_arch_flags + args.compiler_flags: + compilation_command = compilation_command + flag.split(" ") + +source_files = [ + # sanity_check is juste here to ensure that the given compiler + # and flags are coherent. It must be kept at the top of the list. + ("sanity_check.c", "none"), + ("sizeof_short.c", "number"), + ("sizeof_int.c", "number"), + ("sizeof_long.c", "number"), + ("sizeof_longlong.c", "number"), + ("sizeof_ptr.c", "number"), + ("sizeof_float.c", "number"), + ("sizeof_double.c", "number"), + ("sizeof_longdouble.c", "number"), + ("sizeof_void.c", "number"), + ("sizeof_fun.c", "number"), + ("alignof_short.c", "number"), + ("alignof_int.c", "number"), + ("alignof_long.c", "number"), + ("alignof_longlong.c", "number"), + ("alignof_ptr.c", "number"), + ("alignof_float.c", "number"), + ("alignof_double.c", "number"), + ("alignof_longdouble.c", "number"), + ("alignof_fun.c", "number"), + ("alignof_str.c", "number"), + ("alignof_aligned.c", "number"), + ("size_t.c", "type"), + ("ssize_t.c", "type"), + ("wchar_t.c", "type"), + ("ptrdiff_t.c", "type"), + ("intptr_t.c", "type"), + ("uintptr_t.c", "type"), + ("int_fast8_t.c", "type"), + ("int_fast16_t.c", "type"), + ("int_fast32_t.c", "type"), + ("int_fast64_t.c", "type"), + ("uint_fast8_t.c", "type"), + ("uint_fast16_t.c", "type"), + ("uint_fast32_t.c", "type"), + ("uint_fast64_t.c", "type"), + ("wint_t.c", "type"), + ("sig_atomic_t.c", "type"), + ("time_t.c", "type"), + ("char_is_unsigned.c", "bool"), + ("little_endian.c", "bool"), + ("has__builtin_va_list.c", "has__builtin_va_list"), + ("weof.c", "macro"), + ("wordsize.c", "macro"), + ("posix_version.c", "macro"), + ("limits_macros.c", "macro"), + ("stdio_macros.c", "macro"), + ("stdlib_macros.c", "macro"), + ("nsig.c", "macro"), + ("errno.c", "macrolist"), +] + + +def find_value(name, typ, output): + if typ == "bool": + expected = "(True|False)" + + def conversion(x): + return x == "True" + + default = False + + elif typ == "number": + expected = "([0-9]+)" + + def conversion(x): + return int(x) + + default = -1 + + elif typ == "type": + expected = "`([^`]+)`" + + def conversion(x): + return x + + default = "" + + else: + logging.warning(f"unexpected type '{typ}' for field '{name}', skipping") + return + if name in machdep: + msg = re.compile(name + " is " + expected) + res = re.search(msg, output) + if res: + value = conversion(res.group(1)) + if args.verbose: + print(f"[INFO] setting {name} to {value}") + machdep[name] = value + else: + logging.warning( + f"cannot find value of field '{name}', using default value: '{default}'" + ) + machdep[name] = default + if args.verbose: + print(f"compiler output is:{output}") + else: + logging.warning(f"unexpected symbol '{name}', ignoring") + + +def cleanup_cpp(output): + lines = output.splitlines() + macro = filter(lambda s: s != "" and s[0] != "#", lines) + macro = map(lambda s: s.strip(), macro) + return " ".join(macro) + + +def find_macros_value(output, is_list=False, entry=None): + msg = re.compile(r"(\w+)_is = ([^;]+);") + if is_list: + assert entry + machdep[entry] = {} + for res in re.finditer(msg, output): + name = res.group(1) + value = res.group(2).strip() + if is_list: + machdep[entry][name] = value + else: + if name in machdep: + if args.verbose: + print(f"[INFO] setting {name} to {value}") + machdep[name] = value + else: + logging.warning(f"unexpected symbol '{name}', ignoring") + if args.verbose: + print(f"compiler output is:{output}") + + +for f, typ in source_files: + p = my_path / f + cmd = compilation_command + [str(p)] + if typ in ("macro", "macrolist"): + # We're just interested in expanding a macro, + # treatment is a bit different than the rest. + cmd = cmd + ["-E"] + if args.verbose: + print(f"[INFO] running command: {' '.join(cmd)}") + proc = subprocess.run(cmd, capture_output=True) + Path(f).with_suffix(".o").unlink(missing_ok=True) + if typ == "none": + if proc.returncode != 0: + logging.critical("cannot compile sample C file with provided compiler and flags.") + logging.info(f"compiler output is:{proc.stderr.decode()}") + sys.exit(1) + continue + if typ == "macro": + if proc.returncode != 0: + logging.warning(f"error in preprocessing value '{p}', some values won't be filled") + if args.verbose: + print(f"compiler output is:{proc.stderr.decode()}") + name = p.stem + if name in machdep: + machdep[name] = "" + continue + find_macros_value(cleanup_cpp(proc.stdout.decode())) + continue + if typ == "macrolist": + name = p.stem + if proc.returncode != 0: + logging.warning(f"error in preprocessing value '{p}', some value might not be filled") + if args.verbose: + print(f"compiler output is:{proc.stderr.decode()}") + if name in machdep: + machdep[name] = {} + continue + find_macros_value(cleanup_cpp(proc.stdout.decode()), is_list=True, entry=name) + continue + if typ == "has__builtin_va_list": + # Special case: compilation success determines presence or absence + machdep["has__builtin_va_list"] = proc.returncode == 0 + continue + if proc.returncode == 0: + # all tests should fail on an appropriate _Static_assert + # if compilation succeeds, we have a problem + logging.warning(f"WARNING: could not identify value of '{p.stem}', skipping") + continue + find_value(p.stem, typ, proc.stderr.decode()) + +version_output = subprocess.run( + [args.compiler, args.compiler_version], capture_output=True, text=True +) +version = version_output.stdout.splitlines()[0] + +machdep["compiler"] = args.compiler +machdep["cpp_arch_flags"] = args.cpp_arch_flags +machdep["version"] = version + +machdep["custom_defs"] = "" + +# Extract predefined macros; we're assuming a gcc-like compiler here. +# Leave custom_defs empty if this fails. + +# in case we have all the predefined macros, custom_defs will be very long. +# we thus want to output it as a literal block, not a simple string. +# For that, use a custom object and tell PyYaml to output it in a particular way +# Based on SO's answer: + + +class custom_defs(str): + pass + + +def change_style(style, representer): + def new_representer(dumper, data): + scalar = representer(dumper, data) + scalar.style = style + return scalar + + return new_representer + + +custom_defs_representer = change_style("|", Representer.represent_str) + +yaml.add_representer(custom_defs, custom_defs_representer) + +cmd = compilation_command + ["-dM", "-E", "-"] +if args.verbose: + print(f"[INFO] running command: {' '.join(cmd)}") +proc = subprocess.run(cmd, stdin=subprocess.DEVNULL, capture_output=True, text=True) +if proc.returncode == 0: + lines = "" + for line in proc.stdout.splitlines(): + # Preprocessor emits a warning if we're trying to #undef + # standard macros. Leave them alone. + if re.match(r"#define *__STDC", line): + continue + macro = re.match(r"#define *(\w+)", line) + if macro: + lines += f"#undef {macro.group(1)}\n" + lines += f"{line.strip()}\n" + machdep["custom_defs"] = custom_defs(lines) +else: + logging.warning("could not determine predefined macros") + if args.verbose: + print(f"compiler output is:{proc.stderr}") + +if args.from_file and args.in_place: + machdep["machdep_name"] = Path(args.from_file).stem +elif args.dest_file: + machdep["machdep_name"] = Path(args.dest_file.name).stem +else: + machdep["machdep_name"] = "anonymous_machdep" + +missing_fields = [f for [f, v] in machdep.items() if v is None] + +if missing_fields: + msg = ", ".join(missing_fields) + logging.warning(f"the following fields are missing from the machdep definition: {msg}") + for field in missing_fields: + machdep[field] = default_value(schema[field]["type"]) + +print_machdep(machdep) diff --git a/share/machdeps/make_machdep/make_machdep_common.h b/share/machdeps/make_machdep/make_machdep_common.h new file mode 100644 index 0000000000000000000000000000000000000000..8688084e084e41f03b2f8b0ec6af9a36d784fd8e --- /dev/null +++ b/share/machdeps/make_machdep/make_machdep_common.h @@ -0,0 +1,44 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +#if __STDC_VERSION__ < 201112L && !defined(__COMPCERT__) +/* Try using a compiler builtin */ +#define ALIGNOF alignof +#else +#define ALIGNOF _Alignof +#endif + +#if __STDC_VERSION__ >= 201112L || defined(__COMPCERT__) +// Assume _Generic() is supported +#define COMPATIBLE(T1, T2) _Generic(((T1){0}), T2 : 1, default : 0) +#else +// Expect that __builtin_types_compatible_p exists +#define COMPATIBLE(T1, T2) (__builtin_types_compatible_p(T1, T2) ? 0x15 : 0xf4) +#endif + +// needed to ensure the message is properly expanded for TEST_TYPE_IS +#define mkstr(s) #s + +#define TEST_TYPE_COMPATIBLE(T1, T2) \ + _Static_assert(!COMPATIBLE(T1, T2), "" mkstr(T2) " is `" #T1 "`"); + +#define TEST_TYPE_IS(type) TEST_TYPE_COMPATIBLE(type, TEST_TYPE) diff --git a/share/machdeps/make_machdep/nsig.c b/share/machdeps/make_machdep/nsig.c new file mode 100644 index 0000000000000000000000000000000000000000..e82b4fbe2eba34b9f74dfd6dcb0c7da9ccd53ea4 --- /dev/null +++ b/share/machdeps/make_machdep/nsig.c @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <signal.h> + +#if defined(NSIG) +int nsig_is = NSIG; +#elif defined(_NSIG) +int nsig_is = _NSIG; +#endif diff --git a/share/machdeps/make_machdep/posix_version.c b/share/machdeps/make_machdep/posix_version.c new file mode 100644 index 0000000000000000000000000000000000000000..bdd131ffc0dace0035d2dcf3b2e6a71b2b1532fd --- /dev/null +++ b/share/machdeps/make_machdep/posix_version.c @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <unistd.h> + +#if defined(_POSIX_VERSION) +long posix_version_is = _POSIX_VERSION; +#endif diff --git a/share/machdeps/make_machdep/ptrdiff_t.c b/share/machdeps/make_machdep/ptrdiff_t.c new file mode 100644 index 0000000000000000000000000000000000000000..29c9d38d42b5ca332b0111761b323ff69d60b1fc --- /dev/null +++ b/share/machdeps/make_machdep/ptrdiff_t.c @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stddef.h> +#define TEST_TYPE ptrdiff_t + +TEST_TYPE_IS(int); +TEST_TYPE_IS(long); +TEST_TYPE_IS(long long); diff --git a/share/machdeps/make_machdep/sanity_check.c b/share/machdeps/make_machdep/sanity_check.c new file mode 100644 index 0000000000000000000000000000000000000000..8e38b55803d1543ab01368a639b9915aea4305e8 --- /dev/null +++ b/share/machdeps/make_machdep/sanity_check.c @@ -0,0 +1,24 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +/* ensure that the given compiler and flags support a minimal C file */ +int main () { } diff --git a/share/machdeps/make_machdep/sig_atomic_t.c b/share/machdeps/make_machdep/sig_atomic_t.c new file mode 100644 index 0000000000000000000000000000000000000000..9141b3d9a7c0261d419d9260bfb449c9a2b7bb78 --- /dev/null +++ b/share/machdeps/make_machdep/sig_atomic_t.c @@ -0,0 +1,38 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <signal.h> + +#define TEST_TYPE sig_atomic_t + +TEST_TYPE_IS(char) +TEST_TYPE_IS(unsigned char) +TEST_TYPE_IS(signed char) +TEST_TYPE_IS(unsigned short) +TEST_TYPE_IS(short) +TEST_TYPE_IS(unsigned int) +TEST_TYPE_IS(int) +TEST_TYPE_IS(unsigned long) +TEST_TYPE_IS(long) +TEST_TYPE_IS(unsigned long long) +TEST_TYPE_IS(long long) diff --git a/share/machdeps/make_machdep/size_t.c b/share/machdeps/make_machdep/size_t.c new file mode 100644 index 0000000000000000000000000000000000000000..13a4685263cda07d1c57d97088bf9ee85f9b59a1 --- /dev/null +++ b/share/machdeps/make_machdep/size_t.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stddef.h> + +#define TEST_TYPE size_t + +TEST_TYPE_IS(unsigned int) +TEST_TYPE_IS(unsigned long) +TEST_TYPE_IS(unsigned long long) diff --git a/share/machdeps/make_machdep/sizeof_double.c b/share/machdeps/make_machdep/sizeof_double.c new file mode 100644 index 0000000000000000000000000000000000000000..c87c337250d403c4bce05eac6cf3f5197098132b --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_double.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(double) != 1, "sizeof_double is 1"); +_Static_assert(sizeof(double) != 2, "sizeof_double is 2"); +_Static_assert(sizeof(double) != 3, "sizeof_double is 3"); +_Static_assert(sizeof(double) != 4, "sizeof_double is 4"); +_Static_assert(sizeof(double) != 5, "sizeof_double is 5"); +_Static_assert(sizeof(double) != 6, "sizeof_double is 6"); +_Static_assert(sizeof(double) != 7, "sizeof_double is 7"); +_Static_assert(sizeof(double) != 8, "sizeof_double is 8"); diff --git a/share/machdeps/make_machdep/sizeof_float.c b/share/machdeps/make_machdep/sizeof_float.c new file mode 100644 index 0000000000000000000000000000000000000000..6de246c1bde90eb86caec97394c703a2b6974c32 --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_float.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(float) != 1, "sizeof_float is 1"); +_Static_assert(sizeof(float) != 2, "sizeof_float is 2"); +_Static_assert(sizeof(float) != 3, "sizeof_float is 3"); +_Static_assert(sizeof(float) != 4, "sizeof_float is 4"); +_Static_assert(sizeof(float) != 5, "sizeof_float is 5"); +_Static_assert(sizeof(float) != 6, "sizeof_float is 6"); +_Static_assert(sizeof(float) != 7, "sizeof_float is 7"); +_Static_assert(sizeof(float) != 8, "sizeof_float is 8"); diff --git a/share/machdeps/make_machdep/sizeof_fun.c b/share/machdeps/make_machdep/sizeof_fun.c new file mode 100644 index 0000000000000000000000000000000000000000..daa499b72c920df365de255e1781bddbd0835802 --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_fun.c @@ -0,0 +1,23 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(void()) != 1, "sizeof_fun is 1"); diff --git a/share/machdeps/make_machdep/sizeof_int.c b/share/machdeps/make_machdep/sizeof_int.c new file mode 100644 index 0000000000000000000000000000000000000000..914fa6af09af11e6d7565b50c24b75ec6e7f5fe2 --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_int.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(int) != 1, "sizeof_int is 1"); +_Static_assert(sizeof(int) != 2, "sizeof_int is 2"); +_Static_assert(sizeof(int) != 3, "sizeof_int is 3"); +_Static_assert(sizeof(int) != 4, "sizeof_int is 4"); +_Static_assert(sizeof(int) != 5, "sizeof_int is 5"); +_Static_assert(sizeof(int) != 6, "sizeof_int is 6"); +_Static_assert(sizeof(int) != 7, "sizeof_int is 7"); +_Static_assert(sizeof(int) != 8, "sizeof_int is 8"); diff --git a/share/machdeps/make_machdep/sizeof_long.c b/share/machdeps/make_machdep/sizeof_long.c new file mode 100644 index 0000000000000000000000000000000000000000..a545896ddfcb6d6b26dccddd33268cfebeb87fda --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_long.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(long) != 1, "sizeof_long is 1"); +_Static_assert(sizeof(long) != 2, "sizeof_long is 2"); +_Static_assert(sizeof(long) != 3, "sizeof_long is 3"); +_Static_assert(sizeof(long) != 4, "sizeof_long is 4"); +_Static_assert(sizeof(long) != 5, "sizeof_long is 5"); +_Static_assert(sizeof(long) != 6, "sizeof_long is 6"); +_Static_assert(sizeof(long) != 7, "sizeof_long is 7"); +_Static_assert(sizeof(long) != 8, "sizeof_long is 8"); diff --git a/share/machdeps/make_machdep/sizeof_longdouble.c b/share/machdeps/make_machdep/sizeof_longdouble.c new file mode 100644 index 0000000000000000000000000000000000000000..78922473994cf9d2305f426ab067079b4ba5fe04 --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_longdouble.c @@ -0,0 +1,38 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(long double) != 1, "sizeof_longdouble is 1"); +_Static_assert(sizeof(long double) != 2, "sizeof_longdouble is 2"); +_Static_assert(sizeof(long double) != 3, "sizeof_longdouble is 3"); +_Static_assert(sizeof(long double) != 4, "sizeof_longdouble is 4"); +_Static_assert(sizeof(long double) != 5, "sizeof_longdouble is 5"); +_Static_assert(sizeof(long double) != 6, "sizeof_longdouble is 6"); +_Static_assert(sizeof(long double) != 7, "sizeof_longdouble is 7"); +_Static_assert(sizeof(long double) != 8, "sizeof_longdouble is 8"); +_Static_assert(sizeof(long double) != 9, "sizeof_longdouble is 9"); +_Static_assert(sizeof(long double) != 10, "sizeof_longdouble is 10"); +_Static_assert(sizeof(long double) != 11, "sizeof_longdouble is 11"); +_Static_assert(sizeof(long double) != 12, "sizeof_longdouble is 12"); +_Static_assert(sizeof(long double) != 13, "sizeof_longdouble is 13"); +_Static_assert(sizeof(long double) != 14, "sizeof_longdouble is 14"); +_Static_assert(sizeof(long double) != 15, "sizeof_longdouble is 15"); +_Static_assert(sizeof(long double) != 16, "sizeof_longdouble is 16"); diff --git a/share/machdeps/make_machdep/sizeof_longlong.c b/share/machdeps/make_machdep/sizeof_longlong.c new file mode 100644 index 0000000000000000000000000000000000000000..246b21d6fdafe51191d9905439cf5db08b29a5d2 --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_longlong.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(long long) != 1, "sizeof_longlong is 1"); +_Static_assert(sizeof(long long) != 2, "sizeof_longlong is 2"); +_Static_assert(sizeof(long long) != 3, "sizeof_longlong is 3"); +_Static_assert(sizeof(long long) != 4, "sizeof_longlong is 4"); +_Static_assert(sizeof(long long) != 5, "sizeof_longlong is 5"); +_Static_assert(sizeof(long long) != 6, "sizeof_longlong is 6"); +_Static_assert(sizeof(long long) != 7, "sizeof_longlong is 7"); +_Static_assert(sizeof(long long) != 8, "sizeof_longlong is 8"); diff --git a/share/machdeps/make_machdep/sizeof_ptr.c b/share/machdeps/make_machdep/sizeof_ptr.c new file mode 100644 index 0000000000000000000000000000000000000000..d99d94fbcdde01a34d5d5c5db6d855c079c465ba --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_ptr.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(void *) != 1, "sizeof_ptr is 1"); +_Static_assert(sizeof(void *) != 2, "sizeof_ptr is 2"); +_Static_assert(sizeof(void *) != 3, "sizeof_ptr is 3"); +_Static_assert(sizeof(void *) != 4, "sizeof_ptr is 4"); +_Static_assert(sizeof(void *) != 5, "sizeof_ptr is 5"); +_Static_assert(sizeof(void *) != 6, "sizeof_ptr is 6"); +_Static_assert(sizeof(void *) != 7, "sizeof_ptr is 7"); +_Static_assert(sizeof(void *) != 8, "sizeof_ptr is 8"); diff --git a/share/machdeps/make_machdep/sizeof_short.c b/share/machdeps/make_machdep/sizeof_short.c new file mode 100644 index 0000000000000000000000000000000000000000..5287ec206760c0bb43d3e5fd6d06ec016dd819dc --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_short.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(short) != 1, "sizeof_short is 1"); +_Static_assert(sizeof(short) != 2, "sizeof_short is 2"); +_Static_assert(sizeof(short) != 3, "sizeof_short is 3"); +_Static_assert(sizeof(short) != 4, "sizeof_short is 4"); +_Static_assert(sizeof(short) != 5, "sizeof_short is 5"); +_Static_assert(sizeof(short) != 6, "sizeof_short is 6"); +_Static_assert(sizeof(short) != 7, "sizeof_short is 7"); +_Static_assert(sizeof(short) != 8, "sizeof_short is 8"); diff --git a/share/machdeps/make_machdep/sizeof_void.c b/share/machdeps/make_machdep/sizeof_void.c new file mode 100644 index 0000000000000000000000000000000000000000..76db3124db00720802a827e9f7b0cf54d836d7bf --- /dev/null +++ b/share/machdeps/make_machdep/sizeof_void.c @@ -0,0 +1,23 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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). */ +/* */ +/**************************************************************************/ + +_Static_assert(sizeof(void) != 1, "sizeof_void is 1"); diff --git a/share/machdeps/make_machdep/ssize_t.c b/share/machdeps/make_machdep/ssize_t.c new file mode 100644 index 0000000000000000000000000000000000000000..3f8de4170d217c8a600929955bd79e2dc712602b --- /dev/null +++ b/share/machdeps/make_machdep/ssize_t.c @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <sys/types.h> + +#define TEST_TYPE ssize_t + +TEST_TYPE_IS(char) +TEST_TYPE_IS(short) +TEST_TYPE_IS(int) +TEST_TYPE_IS(long) +TEST_TYPE_IS(long long) diff --git a/share/machdeps/make_machdep/stdio_macros.c b/share/machdeps/make_machdep/stdio_macros.c new file mode 100644 index 0000000000000000000000000000000000000000..e332c2b35407bc8c29e99d2572cfd39aec6f4679 --- /dev/null +++ b/share/machdeps/make_machdep/stdio_macros.c @@ -0,0 +1,42 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <stdio.h> + +#if defined(BUFSIZ) +int bufsiz_is = BUFSIZ; +#endif +#if defined(EOF) +int eof_is = EOF; +#endif +#if defined(FOPEN_MAX) +int fopen_max_is = FOPEN_MAX; +#endif +#if defined(FILENAME_MAX) +int filename_max_is = FILENAME_MAX; +#endif +#if defined(L_tmpnam) +int l_tmpnam_is = L_tmpnam; +#endif +#if defined(TMP_MAX) +int tmp_max_is = TMP_MAX; +#endif diff --git a/share/machdeps/make_machdep/stdlib_macros.c b/share/machdeps/make_machdep/stdlib_macros.c new file mode 100644 index 0000000000000000000000000000000000000000..88ffd4f8014ff3ab136143ad37e62ca6bb1451b9 --- /dev/null +++ b/share/machdeps/make_machdep/stdlib_macros.c @@ -0,0 +1,36 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <limits.h> +#include <stdlib.h> + +#if defined(RAND_MAX) +int rand_max_is = RAND_MAX; +#endif + +/* NB: MB_LEN_MAX is the maximal value of MB_CUR_MAX; + however, the current Frama-C libc is not equipped to + fully deal with a non-constant MB_CUR_MAX +*/ +#if defined(MB_LEN_MAX) +size_t mb_cur_max_is = ((size_t)MB_LEN_MAX); +#endif diff --git a/share/machdeps/make_machdep/time_t.c b/share/machdeps/make_machdep/time_t.c new file mode 100644 index 0000000000000000000000000000000000000000..2e1b90a172b9856d5053f0cc525c5396d37879f5 --- /dev/null +++ b/share/machdeps/make_machdep/time_t.c @@ -0,0 +1,39 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <time.h> + +#define TEST_TYPE time_t + +TEST_TYPE_IS(unsigned int) +TEST_TYPE_IS(int) +TEST_TYPE_IS(unsigned long) +TEST_TYPE_IS(long) +TEST_TYPE_IS(unsigned long long) +TEST_TYPE_IS(long long) + +// Technically, C standard speaks of a 'real' type, not an 'integer' one + +TEST_TYPE_IS(float) +TEST_TYPE_IS(double) +TEST_TYPE_IS(long double) diff --git a/share/machdeps/make_machdep/uint_fast16_t.c b/share/machdeps/make_machdep/uint_fast16_t.c new file mode 100644 index 0000000000000000000000000000000000000000..8b6524211c85d80f4089d79492e89ec7feabc559 --- /dev/null +++ b/share/machdeps/make_machdep/uint_fast16_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE uint_fast16_t + +TEST_TYPE_IS(unsigned char); +TEST_TYPE_IS(unsigned short); +TEST_TYPE_IS(unsigned int); +TEST_TYPE_IS(unsigned long); +TEST_TYPE_IS(unsigned long long); diff --git a/share/machdeps/make_machdep/uint_fast32_t.c b/share/machdeps/make_machdep/uint_fast32_t.c new file mode 100644 index 0000000000000000000000000000000000000000..ff8e7cbe8f5157e82edb98ae4e4d5e63fd034514 --- /dev/null +++ b/share/machdeps/make_machdep/uint_fast32_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE uint_fast32_t + +TEST_TYPE_IS(unsigned char); +TEST_TYPE_IS(unsigned short); +TEST_TYPE_IS(unsigned int); +TEST_TYPE_IS(unsigned long); +TEST_TYPE_IS(unsigned long long); diff --git a/share/machdeps/make_machdep/uint_fast64_t.c b/share/machdeps/make_machdep/uint_fast64_t.c new file mode 100644 index 0000000000000000000000000000000000000000..5dbc103bd28c963d211b051cebf5bf80e3fb18ff --- /dev/null +++ b/share/machdeps/make_machdep/uint_fast64_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE uint_fast64_t + +TEST_TYPE_IS(unsigned char); +TEST_TYPE_IS(unsigned short); +TEST_TYPE_IS(unsigned int); +TEST_TYPE_IS(unsigned long); +TEST_TYPE_IS(unsigned long long); diff --git a/share/machdeps/make_machdep/uint_fast8_t.c b/share/machdeps/make_machdep/uint_fast8_t.c new file mode 100644 index 0000000000000000000000000000000000000000..d7710d97b006d2a3f28f8eaa16b33af1e0340017 --- /dev/null +++ b/share/machdeps/make_machdep/uint_fast8_t.c @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE uint_fast8_t + +TEST_TYPE_IS(unsigned char); +TEST_TYPE_IS(unsigned short); +TEST_TYPE_IS(unsigned int); +TEST_TYPE_IS(unsigned long); +TEST_TYPE_IS(unsigned long long); diff --git a/share/machdeps/make_machdep/uintptr_t.c b/share/machdeps/make_machdep/uintptr_t.c new file mode 100644 index 0000000000000000000000000000000000000000..655dd30616e2fd871f4f156702d71a4ba7eba77c --- /dev/null +++ b/share/machdeps/make_machdep/uintptr_t.c @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stdint.h> +#define TEST_TYPE uintptr_t + +TEST_TYPE_IS(unsigned int); +TEST_TYPE_IS(unsigned long); +TEST_TYPE_IS(unsigned long long); diff --git a/share/machdeps/make_machdep/wchar_t.c b/share/machdeps/make_machdep/wchar_t.c new file mode 100644 index 0000000000000000000000000000000000000000..ce5b3ae2a74ab4fb8f83f6a227f5aaf174cb9b70 --- /dev/null +++ b/share/machdeps/make_machdep/wchar_t.c @@ -0,0 +1,32 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <stddef.h> +#define TEST_TYPE wchar_t + +TEST_TYPE_IS(unsigned short) +TEST_TYPE_IS(short) +TEST_TYPE_IS(unsigned int) +TEST_TYPE_IS(int) +TEST_TYPE_IS(unsigned long) +TEST_TYPE_IS(long) diff --git a/share/machdeps/make_machdep/weof.c b/share/machdeps/make_machdep/weof.c new file mode 100644 index 0000000000000000000000000000000000000000..f648ef8391c5408c06d27841062afed44ff29a31 --- /dev/null +++ b/share/machdeps/make_machdep/weof.c @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <wchar.h> + +#if defined(WEOF) +const wint_t weof_is = WEOF; +#endif diff --git a/share/machdeps/make_machdep/wint_t.c b/share/machdeps/make_machdep/wint_t.c new file mode 100644 index 0000000000000000000000000000000000000000..bf7486460e5174a58545479652f1f754f6c5a76e --- /dev/null +++ b/share/machdeps/make_machdep/wint_t.c @@ -0,0 +1,34 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 "make_machdep_common.h" +#include <wchar.h> +#define TEST_TYPE wint_t + +TEST_TYPE_IS(unsigned short); +TEST_TYPE_IS(short); +TEST_TYPE_IS(unsigned int); +TEST_TYPE_IS(int); +TEST_TYPE_IS(unsigned long); +TEST_TYPE_IS(long); +TEST_TYPE_IS(unsigned long long); +TEST_TYPE_IS(long long); diff --git a/share/machdeps/make_machdep/wordsize.c b/share/machdeps/make_machdep/wordsize.c new file mode 100644 index 0000000000000000000000000000000000000000..7279411f73930f030a8f29a523d31d47759ee88f --- /dev/null +++ b/share/machdeps/make_machdep/wordsize.c @@ -0,0 +1,27 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2023 */ +/* 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 <features.h> + +#if defined(__WORDSIZE) +const int wordsize_is = __WORDSIZE; +#endif diff --git a/src/dune b/src/dune index 5d6871a6b48e4e14d9357782b90718e664b77aeb..599d3f7423ac6a0e1daba6de1ea8c204345e76e3 100644 --- a/src/dune +++ b/src/dune @@ -32,11 +32,14 @@ (echo " - dynlink:" %{lib-available:dynlink} "\n") (echo " - bytes:" %{lib-available:bytes} "\n") (echo " - yojson:" %{lib-available:yojson} "\n") + (echo " - yaml.unix:" %{lib-available:yaml.unix} "\n") + (echo " - fpath:" %{lib-available:fpath} "\n") (echo " - menhirLib:" %{lib-available:menhirLib} "\n") (echo " - dune-site:" %{lib-available:dune-site} "\n") (echo " - dune-site.plugins:" %{lib-available:dune-site.plugins} "\n") (echo " - ppx_import:" %{lib-available:ppx_import} "\n") (echo " - ppx_deriving.eq:" %{lib-available:ppx_deriving.eq} "\n") + (echo " - ppx_deriving_yaml:" %{lib-available:ppx_deriving_yaml} "\n") ) ) ) @@ -46,9 +49,9 @@ (public_name frama-c.kernel) (foreign_stubs (language c) (names c_bindings)) (flags :standard -w -9) - (libraries frama-c.init str unix zarith ocamlgraph dynlink bytes yojson menhirLib dune-site dune-site.plugins) + (libraries frama-c.init fpath str unix zarith ocamlgraph dynlink bytes yaml.unix yojson menhirLib dune-site dune-site.plugins) (instrumentation (backend landmarks)) - (preprocess (staged_pps ppx_import ppx_deriving.eq)) + (preprocess (staged_pps ppx_import ppx_deriving.eq ppx_deriving_yaml)) ) (generate_sites_module (module config_data) (sites frama-c) (plugins (frama-c plugins) (frama-c plugins_gui))) diff --git a/src/kernel_internals/parsing/logic_parser.mly b/src/kernel_internals/parsing/logic_parser.mly index d10a972435e8ed7c85c1a17a24a7063cabb66a11..45bdd477a8fa0e572ff6655507440f012cc5fca0 100644 --- a/src/kernel_internals/parsing/logic_parser.mly +++ b/src/kernel_internals/parsing/logic_parser.mly @@ -294,7 +294,6 @@ %token PI %right prec_named -%nonassoc TYPENAME %nonassoc prec_forall prec_exists prec_lambda LET %right QUESTION prec_question %left IFF @@ -309,7 +308,6 @@ %left STARHAT %left AMP %nonassoc IN -%left LT %left LTLT GTGT %left PLUS MINUS %left STAR SLASH PERCENT @@ -761,8 +759,8 @@ logic_rt_type: ; abs_spec_option: -| /* empty */ %prec TYPENAME { fun t -> t } -| abs_spec { $1 } +| /* empty */ { fun t -> t } +| abs_spec { $1 } ; abs_spec_cv_option: @@ -772,12 +770,12 @@ abs_spec_cv_option: abs_spec: | tabs { $1 } -| stars %prec TYPENAME { $1 } -| stars tabs { fun t -> $2 ($1 t) } -| stars abs_spec_bis %prec TYPENAME { fun t -> $2 ($1 t) } -| stars abs_spec_bis tabs { fun t -> $2 ($3 ($1 t)) } -| abs_spec_bis tabs { fun t -> $1 ($2 t) } -| abs_spec_bis %prec TYPENAME { $1 } +| stars { $1 } +| stars tabs { fun t -> $2 ($1 t) } +| stars abs_spec_bis { fun t -> $2 ($1 t) } +| stars abs_spec_bis tabs { fun t -> $2 ($3 ($1 t)) } +| abs_spec_bis tabs { fun t -> $1 ($2 t) } +| abs_spec_bis { $1 } ; abs_spec_cv: @@ -813,7 +811,7 @@ stars_cv: ; tabs: -| LSQUARE array_size RSQUARE %prec TYPENAME +| LSQUARE array_size RSQUARE { fun t -> LTarray (t,$2) } @@ -1659,10 +1657,11 @@ logic_def: exit_type_variables_scope (); LDpredicate_def (id, labels, tvars, $3, $5) } /* inductive predicate definition */ -| INDUCTIVE poly_id parameters LBRACE indcases RBRACE - { let (id,labels,tvars) = $2 in - exit_type_variables_scope (); - LDinductive_def(id, labels, tvars, $3, $5) } +| INDUCTIVE pred = poly_id params = parameters + midrule({exit_type_variables_scope()}) + LBRACE cases = indcases RBRACE + { let (id,labels,tvars) = pred in + LDinductive_def(id, labels, tvars, params, cases) } | LEMMA poly_id COLON lexpr SEMICOLON { let (id,labels,tvars) = $2 in exit_type_variables_scope (); diff --git a/src/kernel_internals/runtime/machdep.ml b/src/kernel_internals/runtime/machdep.ml new file mode 100644 index 0000000000000000000000000000000000000000..9ca2d913b5b020f1358e914adf3c6bd1990eae39 --- /dev/null +++ b/src/kernel_internals/runtime/machdep.ml @@ -0,0 +1,313 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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 + +let gen_define fmt macro pp def = + Format.fprintf fmt "#define %s %a@\n" macro pp def + +let gen_include fmt file = + Format.fprintf fmt "#include <%s>@\n" file + +let gen_undef fmt macro = Format.fprintf fmt "#undef %s@\n" macro + +let gen_define_string fmt macro def = + gen_define fmt macro Format.pp_print_string def + +let gen_define_literal_string fmt macro def = + gen_define fmt macro Format.pp_print_string ("\"" ^ def ^ "\"") + +let gen_define_macro fmt macro def = + if def = "" then gen_undef fmt macro + else gen_define_string fmt macro def + +let gen_define_int fmt macro def = gen_define fmt macro Format.pp_print_int def + +let gen_byte_order fmt mach = + gen_define_string fmt "__FC_BYTE_ORDER" + (if mach.little_endian then "__LITTLE_ENDIAN" else "__BIG_ENDIAN") + +let no_signedness s = + let s = Option.value ~default:s (Extlib.string_del_prefix "signed" s) in + let s = Option.value ~default:s (Extlib.string_del_prefix "unsigned" s) in + let s = String.trim s in + if s = "" then "int" else s + +let suff_of_kind = + [ "char", ""; + "short", ""; + "int", ""; + "long", "L"; + "long long", "LL" + ] + +let pp_of_kind = + [ "char", "hh"; + "short", "h"; + "int", ""; + "long", "l"; + "long long", "ll" + ] + +let max_val bitsize is_signed kind = + let suff = List.assoc kind suff_of_kind in + let suff = if is_signed then suff else "U" ^ suff in + let to_shift = if is_signed then bitsize - 1 else bitsize in + let v = Z.(to_string (sub (shift_left one to_shift) one)) in + v ^ suff + +let min_val bitsize kind = + let suff = List.assoc kind suff_of_kind in + "(-" ^ (max_val bitsize true kind) ^ " - 1" ^ suff ^")" + +let gen_define_stype fmt name kind = + gen_define_string fmt ("__INT" ^ name ^ "_T") ("signed " ^ kind) +let gen_define_utype fmt name kind = + gen_define_string fmt ("__UINT" ^ name ^ "_T") ("unsigned " ^ kind) +let gen_define_min_stype fmt name bitsize kind = + gen_define_string fmt ("__INT" ^ name ^ "_MIN") (min_val bitsize kind) +let gen_define_max_stype fmt name bitsize kind = + gen_define_string fmt ("__INT" ^ name ^ "_MAX") (max_val bitsize true kind) +let gen_define_max_utype fmt name bitsize kind = + gen_define_string fmt ("__UINT" ^ name ^ "_MAX") (max_val bitsize false kind) + +let gen_std_signed fmt name bitsize kind = + gen_define_string fmt ("__FC_" ^ name ^ "_MIN") (min_val bitsize kind); + gen_define_string fmt ("__FC_" ^ name ^ "_MAX") (max_val bitsize true kind) + +let gen_std_unsigned fmt name bitsize kind = + gen_define_string fmt ("__FC_" ^ name ^ "_MAX") (max_val bitsize false kind) + +let gen_define_printing_prefix fmt name kind = + gen_define_literal_string fmt + ("__PRI" ^ name ^ "_PREFIX") + (List.assoc kind pp_of_kind) + +let gen_sizeof fmt name size = + gen_define_int fmt ("__SIZEOF_" ^ name) size + +let existing_int_size mach = + [ 1, "char"; + mach.sizeof_short, "short"; + mach.sizeof_int, "int"; + mach.sizeof_long, "long"; + mach.sizeof_longlong, "long long"] + +let std_type_name mach = + [ "char", if mach.char_is_unsigned then ("UCHAR", false) else ("SCHAR", true); + "signed char", ("SCHAR", true); + "unsigned char", ("UCHAR", false); + "short", ("SHRT", true); + "signed short", ("SHRT", true); + "unsigned short", ("USHRT", false); + "int", ("INT", true); + "signed", ("INT", true); + "signed int", ("INT", true); + "unsigned", ("UINT", false); + "unsigned int", ("UINT", false); + "long", ("LONG", true); + "signed long", ("LONG", true); + "unsigned long", ("ULONG", false); + "long long", ("LLONG", true); + "signed long long", ("LLONG" ,true); + "unsigned long long", ("ULLONG", false) + ] + +let gen_int_type_family fmt name bitsize kind = + gen_define_stype fmt name kind; + gen_define_utype fmt name kind; + gen_define_min_stype fmt name bitsize kind; + gen_define_max_stype fmt name bitsize kind; + gen_define_max_utype fmt name bitsize kind; + gen_define_printing_prefix fmt name kind + +let gen_fixed_size_family fmt bitsize mach = + let size = bitsize / 8 in + match + List.find_opt (fun (s,_) -> s >= size) (existing_int_size mach) + with + | None -> () (* No corresponding type. *) + | Some (exact_size, kind) -> + if size = exact_size then + gen_int_type_family fmt (string_of_int bitsize) bitsize kind; + gen_int_type_family fmt ("_LEAST" ^ string_of_int bitsize) bitsize kind + +let gen_max_size_int fmt mach = + gen_int_type_family fmt "MAX" (8 * mach.sizeof_longlong) "long long" + +let gen_std_min_max fmt mach = + gen_std_signed fmt "SCHAR" 8 "char"; + gen_std_unsigned fmt "UCHAR" 8 "char"; + gen_std_signed fmt "SHRT" (8*mach.sizeof_short) "short"; + gen_std_unsigned fmt "USHRT" (8*mach.sizeof_short) "short"; + gen_std_signed fmt "INT" (8*mach.sizeof_int) "int"; + gen_std_unsigned fmt "UINT" (8*mach.sizeof_int) "int"; + gen_std_signed fmt "LONG" (8*mach.sizeof_long) "long"; + gen_std_unsigned fmt "ULONG" (8*mach.sizeof_long) "long"; + gen_std_signed fmt "LLONG" (8*mach.sizeof_longlong) "long long"; + gen_std_unsigned fmt "ULLONG" (8*mach.sizeof_longlong) "long long" + +let gen_va_list_repr fmt mach = + let repr = + if mach.has__builtin_va_list then "__builtin_va_list" else "char*" + in + gen_define_string fmt "__FC_VA_LIST_T" repr + +let gen_char_unsigned_flag fmt mach = + let macro = "__CHAR_UNSIGNED__" in + if mach.char_is_unsigned then gen_define_string fmt macro "1" + else gen_undef fmt macro + +let gen_sizeof_std fmt mach = + gen_sizeof fmt "SHORT" mach.sizeof_short; + gen_sizeof fmt "INT" mach.sizeof_int; + gen_sizeof fmt "LONG" mach.sizeof_long; + gen_sizeof fmt "LONGLONG" mach.sizeof_longlong + +let gen_intlike_min fmt name repr mach = + if repr <> "" then begin + let macro = name ^ "_MIN" in + let repr_name, is_signed = List.assoc repr (std_type_name mach) in + if is_signed then gen_define_string fmt macro ("__FC_" ^ repr_name ^ "_MIN") + else gen_define_int fmt macro 0 + end + +let gen_intlike_max fmt name repr mach = + if repr <> "" then begin + let macro = name ^ "_MAX" in + let repr_name, _ = List.assoc repr (std_type_name mach) in + gen_define_string fmt macro ("__FC_" ^ repr_name ^ "_MAX") + end + +let gen_fast_int fmt bitsize signed repr mach = + let name = Format.sprintf "_FAST%d" bitsize in + let full_name = + Format.sprintf "__%sINT%s" (if signed then "" else "U") name + in + gen_define_string fmt (full_name ^ "_T") repr; + if signed then gen_intlike_min fmt full_name repr mach; + gen_intlike_max fmt full_name repr mach; + if signed then gen_define_printing_prefix fmt name (no_signedness repr) + +(* assuming all archs have an 8-bit char. In any case, if we end up dealing + with something else at some point, machdep will not be the only place were + changes will be required. *) +let gen_char_bit fmt _mach = + gen_define_int fmt "__CHAR_BIT" 8 + +let gen_define_errno_macro fmt (name, v) = + gen_define_string fmt ("__FC_" ^ (String.uppercase_ascii name)) v + +let machdep_macro_name s = + let tr = function + | c when 'a' <= c && c <= 'z' -> Char.uppercase_ascii c + | c when 'A' <= c && c <= 'Z' -> c + | c when '0' <= c && c <= '9' -> c + | _ -> '_' + in + String.map tr s + +let gen_all_defines fmt mach = + Format.fprintf fmt "/* Machdep-specific info for Frama-C's libc */@\n"; + Format.fprintf fmt "#ifndef __FC_MACHDEP@\n#define __FC_MACHDEP@\n"; + gen_define_int fmt ("__FC_" ^ (machdep_macro_name mach.machdep_name)) 1; + gen_byte_order fmt mach; + gen_fixed_size_family fmt 8 mach; + gen_fixed_size_family fmt 16 mach; + gen_fixed_size_family fmt 32 mach; + gen_fixed_size_family fmt 64 mach; + gen_fast_int fmt 8 true mach.int_fast8_t mach; + gen_fast_int fmt 16 true mach.int_fast16_t mach; + gen_fast_int fmt 32 true mach.int_fast32_t mach; + gen_fast_int fmt 64 true mach.int_fast64_t mach; + gen_fast_int fmt 8 false mach.uint_fast8_t mach; + gen_fast_int fmt 16 false mach.uint_fast16_t mach; + gen_fast_int fmt 32 false mach.uint_fast32_t mach; + gen_fast_int fmt 64 false mach.uint_fast64_t mach; + gen_max_size_int fmt mach; + gen_std_min_max fmt mach; + gen_va_list_repr fmt mach; + gen_char_unsigned_flag fmt mach; + gen_sizeof_std fmt mach; + gen_char_bit fmt mach; + gen_define_string fmt "__PTRDIFF_T" mach.ptrdiff_t; + gen_define_string fmt "__SIZE_T" mach.size_t; + gen_define_string fmt "__WCHAR_T" mach.wchar_t; + gen_define_string fmt "__INTPTR_T" mach.intptr_t; + gen_define_string fmt "__UINTPTR_T" mach.uintptr_t; + gen_define_string fmt "__PTRDIFF_T" mach.ptrdiff_t; + gen_define_string fmt "__WINT_T" mach.wint_t; + gen_define_string fmt "__SSIZE_T" mach.ssize_t; + gen_intlike_max fmt "__FC_SIZE" mach.size_t mach; + gen_intlike_min fmt "__FC_INTPTR" mach.intptr_t mach; + gen_intlike_max fmt "__FC_INTPTR" mach.intptr_t mach; + gen_intlike_max fmt "__FC_UINTPTR" mach.uintptr_t mach; + gen_intlike_min fmt "__FC_WCHAR" mach.wchar_t mach; + gen_intlike_max fmt "__FC_WCHAR" mach.wchar_t mach; + gen_intlike_max fmt "__SSIZE" mach.ssize_t mach; + gen_intlike_min fmt "__FC_PTRDIFF" mach.ptrdiff_t mach; + gen_intlike_max fmt "__FC_PTRDIFF" mach.ptrdiff_t mach; + gen_intlike_min fmt "__FC_WINT" mach.wint_t mach; + gen_intlike_max fmt "__FC_WINT" mach.wint_t mach; + gen_define_macro fmt "__FC_WEOF" mach.weof; + (* NB: Frama-C's inttypes.h is assuming that intptr_t and uintptr_t have the + same rank when it comes to define PRI.?PTR macros. *) + gen_define_literal_string fmt "__PRIPTR_PREFIX" + (List.assoc (no_signedness mach.intptr_t) pp_of_kind); + gen_define_macro fmt "__WORDSIZE" mach.wordsize; + gen_define_macro fmt "__FC_POSIX_VERSION" mach.posix_version; + gen_define_string fmt "__FC_SIG_ATOMIC_T" mach.sig_atomic_t; + gen_intlike_min fmt "__FC_SIG_ATOMIC_MIN" mach.sig_atomic_t mach; + gen_intlike_max fmt "__FC_SIG_ATOMIC_MAX" mach.sig_atomic_t mach; + gen_define_macro fmt "__FC_BUFSIZ" mach.bufsiz; + gen_define_macro fmt "__FC_EOF" mach.eof; + gen_define_macro fmt "__FC_FOPEN_MAX" mach.fopen_max; + gen_define_macro fmt "__FC_FILENAME_MAX" mach.filename_max; + gen_define_macro fmt "__FC_L_tmpnam" mach.l_tmpnam; + gen_define_macro fmt "__FC_TMP_MAX" mach.tmp_max; + gen_define_macro fmt "__FC_RAND_MAX" mach.rand_max; + gen_define_macro fmt "__FC_MB_CUR_MAX" mach.mb_cur_max; + gen_define_macro fmt "__FC_PATH_MAX" mach.path_max; + gen_define_macro fmt "__FC_HOST_NAME_MAX" mach.host_name_max; + gen_define_macro fmt "__FC_TTY_NAME_MAX" mach.tty_name_max; + List.iter (gen_define_errno_macro fmt) mach.errno; + gen_define_macro fmt "__FC_TIME_T" mach.time_t; + gen_define_macro fmt "__FC_NSIG" mach.nsig; + (* NB: should we use Cil.gccMode() here? *) + if mach.compiler = "gcc" then + gen_include fmt "__fc_gcc_builtins.h"; + + Format.fprintf fmt "%s@\n" mach.custom_defs; + + Format.fprintf fmt "#endif // __FC_MACHDEP@\n" + +let generate_machdep_header mach = + let debug = Kernel.(is_debug_key_enabled dkey_pp) in + let temp = Extlib.temp_dir_cleanup_at_exit ~debug "__fc_machdep" in + let temp = Filepath.Normalized.of_string temp in + let file = Filepath.Normalized.concat temp "__fc_machdep.h" in + let chan = open_out (file:>string) in + let fmt = Format.formatter_of_out_channel chan in + gen_all_defines fmt mach; + flush chan; + close_out chan; + temp diff --git a/src/plugins/gui/GSourceView.2.ml b/src/kernel_internals/runtime/machdep.mli similarity index 76% rename from src/plugins/gui/GSourceView.2.ml rename to src/kernel_internals/runtime/machdep.mli index 6e7db298617595bf60430041972be9314ed52fd3..8b4118076abaed9de7cb95cf8b3b47e7f67d6ec8 100644 --- a/src/plugins/gui/GSourceView.2.ml +++ b/src/kernel_internals/runtime/machdep.mli @@ -20,18 +20,14 @@ (* *) (**************************************************************************) -(** compatibility layer between gtksourceview 2 and 3. *) -include GSourceView2 +(** Managing machine-dependent information. *) -let make_marker_attributes - ~(source:source_view) - ~(category:string) - ~(priority: int) - ?(background: Gdk.color option) - ?(pixbuf:GdkPixbuf.pixbuf option) - ?(icon_name:string option) - () = - ignore icon_name; (* not in lablgtk2. *) - source#set_mark_category_priority ~category priority; - source#set_mark_category_pixbuf ~category pixbuf; - source#set_mark_category_background ~category background + +(** Prints on the given formatter all [#define] directives + required by [share/libc/features.h] and other system-dependent headers. +*) +val gen_all_defines: Format.formatter -> Cil_types.mach -> unit + +(** generates a [__fc_machdep.h] file in a temp directory and returns the + directory name, to be added to the search path for preprocessing stdlib *) +val generate_machdep_header: Cil_types.mach -> Filepath.Normalized.t diff --git a/src/kernel_internals/runtime/machdeps.ml b/src/kernel_internals/runtime/machdeps.ml deleted file mode 100644 index a1a9726e4b79fca10ffcb7eba109f71a04c27fd9..0000000000000000000000000000000000000000 --- a/src/kernel_internals/runtime/machdeps.ml +++ /dev/null @@ -1,239 +0,0 @@ -(****************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula <necula@cs.berkeley.edu> *) -(* Scott McPeak <smcpeak@cs.berkeley.edu> *) -(* Wes Weimer <weimer@cs.berkeley.edu> *) -(* Ben Liblit <liblit@cs.berkeley.edu> *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives) *) -(* and INRIA (Institut National de Recherche en Informatique *) -(* et Automatique). *) -(****************************************************************************) - -open Cil_types - -let x86_16 = { - version = - "x86 16 bits mode (gcc like compiler) with big or huge memory model"; - compiler = "generic"; - cpp_arch_flags = ["-m16"]; - sizeof_short = 2; - sizeof_int = 2; - sizeof_long = 4; - sizeof_longlong = 8; - sizeof_ptr = 4; - sizeof_float = 4; - sizeof_double = 8; - sizeof_longdouble = 16; - sizeof_void = -1; - sizeof_fun = -1; - size_t = "unsigned int"; - wchar_t = "int"; - ptrdiff_t = "int"; - alignof_short = 2; - alignof_int = 2; - alignof_long = 4; - alignof_longlong = 4; - alignof_ptr = 4; - alignof_float = 2; - alignof_double = 8; - alignof_longdouble = 16; - alignof_str = 1; - alignof_fun = -1; - alignof_aligned= 8; - (* I don't know if attribute aligned is supported by any 16bits - compiler. *) - char_is_unsigned = false; - const_string_literals = true; - little_endian = true; - underscore_name = true ; - has__builtin_va_list = true; -} - -let gcc_x86_16 = { x86_16 with - compiler = "gcc"; - sizeof_void = 1; sizeof_fun = 1; alignof_fun = 1; - } - -let x86_32 = { - version = "gcc 4.0.3 - X86-32bits mode"; - compiler = "generic"; - cpp_arch_flags = ["-m32"]; - sizeof_short = 2; - sizeof_int = 4; - sizeof_long = 4; - sizeof_longlong = 8; - sizeof_ptr = 4; - sizeof_float = 4; - sizeof_double = 8; - sizeof_longdouble = 12; - sizeof_void = -1; - sizeof_fun = -1; - size_t = "unsigned int"; - wchar_t = "int"; - ptrdiff_t = "int"; - alignof_short = 2; - alignof_int = 4; - alignof_long = 4; - alignof_longlong = 4; - alignof_ptr = 4; - alignof_float = 4; - alignof_double = 4; - alignof_longdouble = 4; - alignof_str = 1; - alignof_fun = -1; - alignof_aligned= 16; - char_is_unsigned = false; - const_string_literals = true; - little_endian = true; - underscore_name = false ; - has__builtin_va_list = true; -} - -let gcc_x86_32 = { x86_32 with - compiler = "gcc"; - sizeof_void = 1; sizeof_fun = 1; alignof_fun = 1; - } - -let x86_64 = { - version = "gcc 4.0.3 AMD64"; - compiler = "generic"; - cpp_arch_flags = ["-m64"]; - sizeof_short = 2; - sizeof_int = 4; - sizeof_long = 8; - sizeof_longlong = 8; - sizeof_ptr = 8; - sizeof_float = 4; - sizeof_double = 8; - sizeof_longdouble = 16; - sizeof_void = -1; - sizeof_fun = -1; - size_t = "unsigned long"; - wchar_t = "int"; - ptrdiff_t = "long"; - alignof_short = 2; - alignof_int = 4; - alignof_long = 8; - alignof_longlong = 8; - alignof_ptr = 8; - alignof_float = 4; - alignof_double = 8; - alignof_longdouble = 16; - alignof_str = 1; - alignof_fun = -1; - alignof_aligned= 16; - char_is_unsigned = false; - const_string_literals = true; - little_endian = true; - underscore_name = false ; - has__builtin_va_list = true; -} - -let gcc_x86_64 = { x86_64 with - compiler = "gcc"; - sizeof_void = 1; sizeof_fun = 1; alignof_fun = 1; - } - -let ppc_32 = { - version = "4.0.1 (Apple Computer, Inc. build 5367)"; - compiler = "standard"; - cpp_arch_flags = ["-m32"]; - sizeof_short = 2; - sizeof_int = 4; - sizeof_long = 4; - sizeof_longlong = 8; - sizeof_ptr = 4; - sizeof_float = 4; - sizeof_double = 8; - sizeof_longdouble = 16; - sizeof_void = 1; - sizeof_fun = 1; - size_t = "unsigned int"; - wchar_t = "int"; - ptrdiff_t = "int"; - alignof_short = 2; - alignof_int = 4; - alignof_long = 4; - alignof_longlong = 4; - alignof_ptr = 4; - alignof_float = 4; - alignof_double = 4; - alignof_longdouble = 16; - alignof_str = 1; - alignof_fun = 4; - alignof_aligned= 16; - char_is_unsigned = false; - const_string_literals = true; - little_endian = false; - underscore_name = false ; - has__builtin_va_list = true; -} - -let msvc_x86_64 = { - version = "MSVC - X86-64bits mode"; - compiler = "msvc"; - cpp_arch_flags = ["-m64"]; - sizeof_short = 2; - sizeof_int = 4; - sizeof_long = 4; - sizeof_longlong = 8; - sizeof_ptr = 8; - sizeof_float = 4; - sizeof_double = 8; - sizeof_longdouble = 8; - sizeof_void = 0; - sizeof_fun = -1; - size_t = "unsigned long long"; (* defined as 'unsigned __int64' *) - wchar_t = "unsigned short"; - ptrdiff_t = "long long"; (* defined as '__int64' *) - alignof_short = 2; - alignof_int = 4; - alignof_long = 4; - alignof_longlong = 8; - alignof_ptr = 8; - alignof_float = 4; - alignof_double = 8; - alignof_longdouble = 8; - alignof_str = 1; (* __alignof("a") results in compilation error C2059: - syntax error: 'string' *) - alignof_fun = -1; - alignof_aligned= 1; (* MSVC does not seem to have an 'align' attribute - equivalent to GCC's *) - char_is_unsigned = false; - const_string_literals = true; - little_endian = true; - underscore_name = false ; - has__builtin_va_list = false; -} diff --git a/src/kernel_internals/runtime/machdeps.mli b/src/kernel_internals/runtime/machdeps.mli deleted file mode 100644 index 3959c84cf536c23ebd24c750f3695ef68911cefc..0000000000000000000000000000000000000000 --- a/src/kernel_internals/runtime/machdeps.mli +++ /dev/null @@ -1,54 +0,0 @@ -(****************************************************************************) -(* *) -(* Copyright (C) 2001-2003 *) -(* George C. Necula <necula@cs.berkeley.edu> *) -(* Scott McPeak <smcpeak@cs.berkeley.edu> *) -(* Wes Weimer <weimer@cs.berkeley.edu> *) -(* Ben Liblit <liblit@cs.berkeley.edu> *) -(* All rights reserved. *) -(* *) -(* Redistribution and use in source and binary forms, with or without *) -(* modification, are permitted provided that the following conditions *) -(* are met: *) -(* *) -(* 1. Redistributions of source code must retain the above copyright *) -(* notice, this list of conditions and the following disclaimer. *) -(* *) -(* 2. Redistributions in binary form must reproduce the above copyright *) -(* notice, this list of conditions and the following disclaimer in the *) -(* documentation and/or other materials provided with the distribution. *) -(* *) -(* 3. The names of the contributors may not be used to endorse or *) -(* promote products derived from this software without specific prior *) -(* written permission. *) -(* *) -(* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *) -(* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *) -(* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *) -(* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *) -(* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *) -(* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *) -(* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *) -(* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *) -(* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *) -(* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *) -(* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *) -(* POSSIBILITY OF SUCH DAMAGE. *) -(* *) -(* File modified by CEA (Commissariat à l'énergie atomique et aux *) -(* énergies alternatives) *) -(* and INRIA (Institut National de Recherche en Informatique *) -(* et Automatique). *) -(****************************************************************************) - -(** Some predefined {!Cil_types.mach} which specifies machine-dependent - data about C programs. *) - -val x86_16: Cil_types.mach -val gcc_x86_16: Cil_types.mach -val x86_32: Cil_types.mach -val gcc_x86_32: Cil_types.mach -val x86_64: Cil_types.mach -val gcc_x86_64: Cil_types.mach -val ppc_32: Cil_types.mach -val msvc_x86_64: Cil_types.mach diff --git a/src/kernel_internals/typing/cabs2cil.ml b/src/kernel_internals/typing/cabs2cil.ml index a39379b17639f2b7b16fa30bc44001c212afbb3e..b6422e8030749d9da9814f232e4a68fa14bc868f 100644 --- a/src/kernel_internals/typing/cabs2cil.ml +++ b/src/kernel_internals/typing/cabs2cil.ml @@ -4494,9 +4494,9 @@ let checkTypedefSize name typ = (not exact && size < intended_size) then Kernel.warning ~current:true - "bad type '%a' (%d bits) for typedef '%s';@ \ + "bad type '%a' (%d bits) for typedef '%s' using machdep %s;@ \ check for mismatch between -machdep flag and headers used" - Typ.pretty typ size name + Typ.pretty typ size name Cil.theMachine.theMachine.machdep_name with (* Not a standard integer type, ignore it. *) Not_found -> () diff --git a/src/kernel_internals/typing/logic_builtin.ml b/src/kernel_internals/typing/logic_builtin.ml index 629040d5995a1e5fb7d60d8ff15876f72c3aea2d..03c45e5023eafe2b3c686eb96f98e92a1898786f 100644 --- a/src/kernel_internals/typing/logic_builtin.ml +++ b/src/kernel_internals/typing/logic_builtin.ml @@ -118,6 +118,7 @@ let init = (fun c -> Logic_env.add_builtin_logic_ctor c.ctor_name c) ctors ; list.lt_def <- Some (LTsum ctors); let _list_of_integer = Ltype (list, [Linteger]) in + let l_label = FormalLabel "L" in (* predicates *) List.iter (fun (f,tparams,labels,params) -> @@ -154,14 +155,14 @@ let init = "\\no_overflow_double", [], [], ["m", rounding_mode; "x", Lreal] ; "\\subset", [a_name], [], ["s1", set_of_a_type; "s2", set_of_a_type]; - "\\pointer_comparable", [], [], [("p1", object_ptr); - ("p2", object_ptr)]; - "\\pointer_comparable", [], [], [("p1", fun_ptr); - ("p2", fun_ptr)]; - "\\pointer_comparable", [], [], [("p1", fun_ptr); - ("p2", object_ptr)]; - "\\pointer_comparable", [], [], [("p1", object_ptr); - ("p2", fun_ptr)]; + "\\pointer_comparable", [], [l_label], [("p1", object_ptr); + ("p2", object_ptr)]; + "\\pointer_comparable", [], [l_label], [("p1", fun_ptr); + ("p2", fun_ptr)]; + "\\pointer_comparable", [], [l_label], [("p1", fun_ptr); + ("p2", object_ptr)]; + "\\pointer_comparable", [], [l_label], [("p1", object_ptr); + ("p2", fun_ptr)]; ]; (* functions *) List.iter diff --git a/src/kernel_services/abstract_interp/cvalue.ml b/src/kernel_services/abstract_interp/cvalue.ml index 4cbc4f03fee2715b7c53d9c7663b6b4d298e4085..31435f52e940154822a5ed8f287ba3b865d547b1 100644 --- a/src/kernel_services/abstract_interp/cvalue.ml +++ b/src/kernel_services/abstract_interp/cvalue.ml @@ -224,6 +224,20 @@ module V = struct (fun fmt (k, v) -> pp_base fmt k v) fmt m + let pretty_enumitem_set enuminfo fmt l = + let module S = Datatype.Integer.Map in + let assoc ei = Cil.constFoldToInt ei.eival |> Option.map (fun i -> i, ei) in + let lookup_map = + List.to_seq enuminfo.eitems |> Seq.filter_map assoc |> S.of_seq + in + let pretty_item fmt i = + match S.find_opt i lookup_map with + | Some ei -> Printer.pp_varname fmt ei.eiorig_name + | None -> Format.fprintf fmt "%a" Integer.pretty i + in + Pretty_utils.pp_iter ~pre:"@[<hov 1>{" ~suf:"}@]" ~sep:";@ " + List.iter pretty_item fmt l + let pretty_typ typ fmt v = let pretty_org fmt org = if not (Origin.is_top org) then @@ -239,7 +253,10 @@ module V = struct Base.SetLattice.pretty t pretty_org a | Map m -> try - Ival.pretty fmt (project_ival v) + let ival = project_ival v in + match Ival.project_small_set ival, Option.map Cil.unrollType typ with + | Some list, Some (TEnum (ei, _)) -> pretty_enumitem_set ei fmt list + | _ -> Ival.pretty fmt ival with | Not_based_on_null -> try diff --git a/src/kernel_services/abstract_interp/function_Froms.ml b/src/kernel_services/abstract_interp/function_Froms.ml index b5be5bfbcd8d6bdf37f36223138f6db489d69db9..f6f2f5e8a931121cbb58b2d66caf6c5fdaa4e3e5 100644 --- a/src/kernel_services/abstract_interp/function_Froms.ml +++ b/src/kernel_services/abstract_interp/function_Froms.ml @@ -105,7 +105,7 @@ struct indirect = Zone.join fd1.indirect fd2.indirect } - let _narrow fd1 fd2 = { + let narrow fd1 fd2 = { data = Zone.narrow fd1.data fd2.data; indirect = Zone.narrow fd1.indirect fd2.indirect } diff --git a/src/kernel_services/abstract_interp/function_Froms.mli b/src/kernel_services/abstract_interp/function_Froms.mli index d027b872e12325b7752219d768b1eb574d9e201e..141bfc5f9a5266c16d87476242410a5f7f679f83 100644 --- a/src/kernel_services/abstract_interp/function_Froms.mli +++ b/src/kernel_services/abstract_interp/function_Froms.mli @@ -31,7 +31,9 @@ module Deps : sig val bottom: deps val top: deps + val is_included: deps -> deps -> bool val join: deps -> deps -> deps + val narrow: deps -> deps -> deps val to_zone: deps -> Locations.Zone.t val add_data_dep: deps -> Locations.Zone.t -> deps diff --git a/src/kernel_services/abstract_interp/int_set.ml b/src/kernel_services/abstract_interp/int_set.ml index d4c45b4012f5f8d689e146ac34dcea3339bf10b4..47c3b99595189fb6c8d3d028ffa649fba37b71c6 100644 --- a/src/kernel_services/abstract_interp/int_set.ml +++ b/src/kernel_services/abstract_interp/int_set.ml @@ -111,12 +111,52 @@ let compare s1 s2 = let equal e1 e2 = compare e1 e2 = 0 +(* Used to print a compact representation of large integer sets. *) +type set_or_itv = + | Set of Int.t array + | Itv of Int.t * Int.t + +(* Converts a set into an ordered list of sets and intervals, fusing adjacent + integers into intervals. *) +let fuse_intervals s = + (* Add interval [b..e[ to the list [acc]. The interval can be a singleton. *) + let add_itv acc (b, e) = + let nb = Int.to_int_exn (Int.sub e b) in + (* If the interval is too small, uses a Set instead of Itv. *) + if nb > 3 + then Itv (b, Int.pred e) :: acc + else + let a = Array.init nb (fun i -> Int.add b (Int.of_int i)) in + (* If the last element of [acc] is a Set, adds [a] at its end. *) + match acc with + | Set a' :: tl -> Set (Array.append a' a) :: tl + | _ -> Set a :: acc + in + (* [start..prev[ is the current interval being built. *) + let f (acc, start, prev) curr = + if Int.equal prev curr + then (acc, start, Int.succ curr) + else (add_itv acc (start, prev), curr, Int.succ curr) + in + let list, start, curr = Array.fold_left f ([], s.(0), s.(0)) s in + List.rev (add_itv list (start, curr)) + +let pretty_array = + Pretty_utils.pp_iter ~pre:"@[<hov 1>{" ~suf:"}@]" ~sep:";@ " + Array.iter Int.pretty + +let pretty_set_or_itv fmt = function + | Set a -> pretty_array fmt a + | Itv (b, e) -> Format.fprintf fmt "[%a..%a]" Int.pretty b Int.pretty e + let pretty fmt s = - Pretty_utils.pp_iter - ~pre:"@[<hov 1>{" - ~suf:"}@]" - ~sep:";@ " - Array.iter Int.pretty fmt s + if Array.length s < 10 + then pretty_array fmt s + else + let union = Unicode.union_string () in + let sep = Scanf.format_from_string ("@ " ^ union ^ " ") "" in + Pretty_utils.pp_iter ~pre:"@[<hov 1>" ~suf:"@]" ~sep + List.iter pretty_set_or_itv fmt (fuse_intervals s) include Datatype.Make_with_collections (struct diff --git a/src/kernel_services/abstract_interp/lattice_bounds.ml b/src/kernel_services/abstract_interp/lattice_bounds.ml index 771b861ac05f3044f24b08d8f7d1ee7228478da8..1e48cad2696860e219610e9ed5df536a8fdd9c78 100644 --- a/src/kernel_services/abstract_interp/lattice_bounds.ml +++ b/src/kernel_services/abstract_interp/lattice_bounds.ml @@ -126,6 +126,10 @@ module Bottom = struct (* Iterators *) + let bind f = function + | `Bottom -> `Bottom + | `Value v -> f v + let fold ~bottom f = function | `Bottom -> bottom | `Value v -> f v @@ -170,17 +174,11 @@ module Bottom = struct module Operators = struct - let (>>-) t f = match t with - | `Bottom -> `Bottom - | `Value t -> f t - - let (>>-:) t f = match t with - | `Bottom -> `Bottom - | `Value t -> `Value (f t) - - let (let+) = (>>-:) + let (>>-) x f = bind f x + let (>>-:) x f = map f x + let (let+) x f = map f x let (and+) = zip - let (let*) = (>>-) + let (let*) x f = bind f x let (and*) = zip end @@ -249,6 +247,20 @@ struct | `Top, v | v, `Top -> v | `Value vx, `Value vy -> `Value (narrow_value vx vy) + (* Iterators *) + + let bind f = function + | `Top -> `Top + | `Value v -> f v + + let fold ~top f = function + | `Top -> top + | `Value v -> f v + + let map f = function + | `Top -> `Top + | `Value v -> `Value (f v) + (** Combination *) let zip x y = @@ -264,18 +276,13 @@ struct (** Operators *) - module Operators = struct - let (>>-) t f = match t with - | `Top -> `Top - | `Value t -> f t - - let (>>-:) t f = match t with - | `Top -> `Top - | `Value t -> `Value (f t) - - let (let+) = (>>-:) + module Operators = + struct + let (>>-) x f = bind f x + let (>>-:) x f = map f x + let (let+) x f = map f x let (and+) = zip - let (let*) = (>>-) + let (let*) x f = bind f x let (and*) = zip end end @@ -299,6 +306,23 @@ struct | `Bottom, _ | _, `Bottom -> `Bottom | `Value vx, `Value vy -> (narrow_value vx vy :> 'a t) + (* Iterators *) + + let bind f = function + | `Top -> `Top + | `Bottom -> `Bottom + | `Value v -> f v + + let fold ~top ~bottom f = function + | `Top -> top + | `Bottom -> bottom + | `Value v -> f v + + let map f = function + | `Top -> `Top + | `Bottom -> `Bottom + | `Value v -> `Value (f v) + (** Combination *) let zip x y = @@ -309,20 +333,13 @@ struct (** Operators *) - module Operators = struct - let (>>-) t f = match t with - | `Top -> `Top - | `Bottom -> `Bottom - | `Value t -> f t - - let (>>-:) t f = match t with - | `Top -> `Top - | `Bottom -> `Bottom - | `Value t -> `Value (f t) - - let (let+) = (>>-:) + module Operators = + struct + let (>>-) x f = bind f x + let (>>-:) x f = map f x + let (let+) x f = map f x let (and+) = zip - let (let*) = (>>-) + let (let*) x f = bind f x let (and*) = zip end end diff --git a/src/kernel_services/abstract_interp/lattice_bounds.mli b/src/kernel_services/abstract_interp/lattice_bounds.mli index 827f7856fffd3758e7f20cbe376c7aa1b1d918c5..ead45a00fb69b5e5aa017b8608dfa5039d605eb1 100644 --- a/src/kernel_services/abstract_interp/lattice_bounds.mli +++ b/src/kernel_services/abstract_interp/lattice_bounds.mli @@ -82,7 +82,8 @@ module Bottom : sig (* Iterators *) val iter: ('a -> unit) -> 'a t -> unit - val fold: bottom: 'b -> ('a -> 'b) -> 'a t -> 'b + val bind: ('a -> 'b t) -> 'a t -> 'b t + val fold: bottom:'b -> ('a -> 'b) -> 'a t -> 'b val map: ('a -> 'b) -> 'a t -> 'b t (* Combination *) @@ -144,6 +145,12 @@ module Top : sig val join: ('a -> 'a -> 'a t) -> 'a t -> 'a t -> 'a t val narrow: ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t + (* Iterators *) + val iter: ('a -> unit) -> 'a t -> unit + val bind: ('a -> 'b t) -> 'a t -> 'b t + val fold: top:'b -> ('a -> 'b) -> 'a t -> 'b + val map: ('a -> 'b) -> 'a t -> 'b t + (** Combination *) val zip: 'a t -> 'b t -> ('a * 'b) t (* `Top if any is `Top *) @@ -188,4 +195,10 @@ module TopBottom: sig (* Lattice operators *) val join: ('a -> 'a -> [< 'a t]) -> 'a t -> 'a t -> 'a t val narrow: ('a -> 'a -> [< 'a t]) -> 'a t -> 'a t -> 'a t + + (* Iterators *) + val iter: ('a -> unit) -> 'a t -> unit + val bind: ('a -> 'b t) -> 'a t -> 'b t + val fold: top:'b -> bottom:'b -> ('a -> 'b) -> 'a t -> 'b + val map: ('a -> 'b) -> 'a t -> 'b t end diff --git a/src/kernel_services/abstract_interp/lmap.ml b/src/kernel_services/abstract_interp/lmap.ml index e4c673e3379f4eaab866138c315352445668bb48..4bc48a7c76ea0b922d8d9dc475ba0b474cafa94e 100644 --- a/src/kernel_services/abstract_interp/lmap.ml +++ b/src/kernel_services/abstract_interp/lmap.ml @@ -394,7 +394,7 @@ struct in let aux = generic_join ~cache:Hptmap_sig.NoCache - ~idempotent:true ~symmetric:true ~decide + ~idempotent:true ~symmetric:false ~decide in Format.fprintf fmt "@[<v>"; ignore (aux m1 m2); diff --git a/src/kernel_services/analysis/interpreted_automata.mli b/src/kernel_services/analysis/interpreted_automata.mli index 5bf56988fb9028a19b02b66d559314891696bd12..b12dd9c6f0227bd108560e882ad3e8c05f7a195b 100644 --- a/src/kernel_services/analysis/interpreted_automata.mli +++ b/src/kernel_services/analysis/interpreted_automata.mli @@ -350,7 +350,7 @@ sig (** Same as [iter_stmt] but guarantee that the iteration will always be in the same increasing order of statements sid. - @since Frama-C+dev *) + @since 27.0-Cobalt *) val iter_stmt_asc : (Cil_types.stmt -> state -> unit) -> result -> unit (** Output result to the given channel. Must be supplied with a pretty diff --git a/src/kernel_services/ast_data/annotations.ml b/src/kernel_services/ast_data/annotations.ml index b30a7a868009fcd841748aec094e53cdf69104c1..4f049e0bf0d288ba0bb7bfbc4069a97ba6f97e0e 100644 --- a/src/kernel_services/ast_data/annotations.ml +++ b/src/kernel_services/ast_data/annotations.ml @@ -67,6 +67,9 @@ let find_englobing_kf ?kf stmt = (** {2 Internal State} *) (**************************************************************************) +module Changed = Hook.Make() +let add_hook_on_change = Changed.extend + module Usable_emitter = struct include Emitter.Usable_emitter let local_clear _ h = Hashtbl.clear h @@ -435,7 +438,8 @@ let pre_register_funspec ?tbl ?(emitter=Emitter.end_user) ?(force=false) kf = tbl; *) List.iter Property_status.register - (Property.ip_of_spec kf Kglobal ~active:[] spec) + (Property.ip_of_spec kf Kglobal ~active:[] spec); + Changed.apply(); end let register_funspec ?emitter ?force kf = @@ -767,7 +771,7 @@ let remove_code_annot_internal e ?(remove_statuses=true) ?kf stmt ca = (**************************************************************************) (* If this function gets exported, please turn e into an Emitter.t *) -let remove_model_field (e:Usable_emitter.t) m = +let do_remove_model_field (e:Usable_emitter.t) m = try let ty = m.mi_base_type in let h = Model_fields.find ty in @@ -789,7 +793,7 @@ let remove_global e a = if Emitter.Usable_emitter.equal e e' then begin Globals.remove a; (match a with - | Dmodel_annot (m,_) -> remove_model_field e m + | Dmodel_annot (m,_) -> do_remove_model_field e m | _ -> ()); let file = Ast.get () in file.globals <- @@ -797,12 +801,14 @@ let remove_global e a = (fun a' -> not (Global.equal (GAnnot(a, Global_annotation.loc a)) a')) file.globals; - Globals.apply_hooks_on_remove e a () + Globals.apply_hooks_on_remove e a (); + Changed.apply(); end) h; with Not_found -> () +(* internal use only *) let remove_in_funspec e kf set_spec = try let tbl = Funspecs.find kf in @@ -815,7 +821,8 @@ let remove_in_funspec e kf set_spec = Format.printf "For emitter %a: %a@." Emitter.Usable_emitter.pretty e Cil_printer.pp_funspec spec) tbl; *) - set_spec spec tbl + set_spec spec tbl; + Changed.apply() with Not_found -> () with Not_found -> assert false @@ -845,7 +852,8 @@ let remove_behavior ?(force=false) e kf bhv = in remove_in_funspec e kf set_spec -let remove_decreases e kf = +(* internal use only *) +let do_remove_decreases e kf = let set_spec spec _tbl = match spec.spec_variant with | None -> () @@ -855,7 +863,12 @@ let remove_decreases e kf = in remove_in_funspec e kf set_spec -let remove_terminates e kf = +let remove_decreases e kf = + do_remove_decreases e kf; + Changed.apply() + +(* internal use only *) +let do_remove_terminates e kf = let set_spec spec _tbl = match spec.spec_terminates with | None -> () @@ -865,21 +878,36 @@ let remove_terminates e kf = in remove_in_funspec e kf set_spec -let remove_complete e kf l = +let remove_terminates e kf = + do_remove_terminates e kf; + Changed.apply() + +(* internal use only *) +let do_remove_complete e kf l = let set_spec spec _tbl = spec.spec_complete_behaviors <- filterq l spec.spec_complete_behaviors in remove_in_funspec e kf set_spec; Property_status.remove (Property.ip_of_complete kf Kglobal ~active:[] l) -let remove_disjoint e kf l = +let remove_complete e kf l = + do_remove_complete e kf l; + Changed.apply() + +(* internal use only *) +let do_remove_disjoint e kf l = let set_spec spec _tbl = spec.spec_disjoint_behaviors <- filterq l spec.spec_disjoint_behaviors in remove_in_funspec e kf set_spec; Property_status.remove (Property.ip_of_disjoint kf Kglobal ~active:[] l) -let remove_requires e kf p = +let remove_disjoint e kf l = + do_remove_disjoint e kf l; + Changed.apply() + +(* internal use only *) +let do_remove_requires e kf p = let set_spec spec _tbl = List.iter (fun b -> @@ -891,7 +919,12 @@ let remove_requires e kf p = in remove_in_funspec e kf set_spec -let remove_assumes e kf p = +let remove_requires e kf p = + do_remove_requires e kf p; + Changed.apply() + +(* internal use only *) +let do_remove_assumes e kf p = let set_spec spec _tbl = List.iter (fun b -> @@ -903,7 +936,12 @@ let remove_assumes e kf p = in remove_in_funspec e kf set_spec -let remove_ensures e kf p = +let remove_assumes e kf p = + do_remove_assumes e kf p; + Changed.apply() + +(* internal use only *) +let do_remove_ensures e kf p = let set_spec spec _tbl = List.iter (fun b -> @@ -915,7 +953,12 @@ let remove_ensures e kf p = in remove_in_funspec e kf set_spec -let remove_allocates e kf p = +let remove_ensures e kf p = + do_remove_ensures e kf p; + Changed.apply() + +(* internal use only *) +let do_remove_allocates e kf p = let set_spec spec _tbl = List.iter (fun b -> @@ -929,7 +972,12 @@ let remove_allocates e kf p = in remove_in_funspec e kf set_spec -let remove_extended e kf ext = +let remove_allocates e kf p = + do_remove_allocates e kf p; + Changed.apply() + +(* internal use only *) +let do_remove_extended e kf ext = let set_spec spec _tbl = List.iter (fun b -> @@ -940,8 +988,12 @@ let remove_extended e kf ext = in remove_in_funspec e kf set_spec +let remove_extended e kf ext = + do_remove_extended e kf ext; + Changed.apply() -let remove_assigns e kf p = +(* internal use only *) +let do_remove_assigns e kf p = let set_spec spec _tbl = List.iter (fun b -> @@ -963,12 +1015,17 @@ let remove_assigns e kf p = in remove_in_funspec e kf set_spec +let remove_assigns e kf p = + do_remove_assigns e kf p; + Changed.apply() + let remove_behavior_components e kf b = - List.iter (remove_requires e kf) b.b_requires; - List.iter (remove_assumes e kf) b.b_assumes; - List.iter (remove_ensures e kf) b.b_post_cond; - remove_assigns e kf b.b_assigns; - remove_allocates e kf b.b_allocation + List.iter (do_remove_requires e kf) b.b_requires; + List.iter (do_remove_assumes e kf) b.b_assumes; + List.iter (do_remove_ensures e kf) b.b_post_cond; + do_remove_assigns e kf b.b_assigns; + do_remove_allocates e kf b.b_allocation; + Changed.apply() (**************************************************************************) (** {2 Adding annotations} *) @@ -1080,7 +1137,8 @@ let mk_spec bhv variant terminates complete disjoint = spec_complete_behaviors = complete; spec_disjoint_behaviors = disjoint; } -let add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs = +(* internal use only *) +let do_add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs = let full_spec = get_spec_all kf ?stmt ?active () in let emit_spec = get_spec_e e kf ?stmt ?active () in let existing_behaviors = emit_spec.spec_behavior in @@ -1147,10 +1205,15 @@ let add_behaviors ?(register_children=true) e kf ?stmt ?active bhvs = bhvs end +let add_behaviors ?register_children e kf ?stmt ?active bhvs = + do_add_behaviors ?register_children e kf ?stmt ?active bhvs; + Changed.apply() + exception AlreadySpecified of string list -let add_decreases ?(force=false) e kf v = - if force then remove_decreases e kf ; +(* internal use only *) +let do_add_decreases ?(force=false) e kf v = + if force then do_remove_decreases e kf ; let full_spec = get_spec_all kf () in let emit_spec = get_spec_e e kf () in (match full_spec.spec_variant with @@ -1159,8 +1222,14 @@ let add_decreases ?(force=false) e kf v = | _ -> emit_spec.spec_variant <- Some v); Property_status.register (Property.ip_of_decreases kf Kglobal v) -let add_terminates ?(force=false) e kf ?stmt ?active t = - if force then remove_terminates e kf ; +(* internal use only *) +let add_decreases ?force e kf v = + do_add_decreases ?force e kf v; + Changed.apply() + +(* internal use only *) +let do_add_terminates ?(force=false) e kf ?stmt ?active t = + if force then do_remove_terminates e kf ; let full_spec = get_spec_all kf ?stmt ?active () in let emit_spec = get_spec_e e kf ?stmt ?active () in (match full_spec.spec_terminates with @@ -1169,6 +1238,10 @@ let add_terminates ?(force=false) e kf ?stmt ?active t = | _ -> emit_spec.spec_terminates <- Some t); Property_status.register (Property.ip_of_terminates kf (kinstr stmt) t) +let add_terminates ?force e kf ?stmt ?active t = + do_add_terminates ?force e kf ?stmt ?active t; + Changed.apply() + let check_bhv_name spec name = if name = Cil.default_behavior_name then begin Kernel.fatal @@ -1182,7 +1255,8 @@ let check_bhv_name spec name = name end -let add_complete e kf ?stmt ?active l = +(* internal use only *) +let do_add_complete e kf ?stmt ?active l = let full_spec = get_spec_all kf ?stmt ?active () in let emit_spec = get_spec_e e kf ?stmt ?active () in if List.mem l full_spec.spec_complete_behaviors then @@ -1198,7 +1272,12 @@ let add_complete e kf ?stmt ?active l = (Property.ip_of_complete kf (kinstr stmt) ~active l) end -let add_disjoint e kf ?stmt ?active l = +let add_complete e kf ?stmt ?active l = + do_add_complete e kf ?stmt ?active l; + Changed.apply() + +(* internal use only *) +let do_add_disjoint e kf ?stmt ?active l = let full_spec = get_spec_all kf ?stmt ?active () in let emit_spec = get_spec_e e kf ?stmt ?active () in if List.mem l full_spec.spec_disjoint_behaviors then @@ -1213,6 +1292,10 @@ let add_disjoint e kf ?stmt ?active l = Property_status.register (Property.ip_of_disjoint kf (kinstr stmt) ~active l) end +let add_disjoint e kf ?stmt ?active l = + do_add_disjoint e kf ?stmt ?active l; + Changed.apply() + let add_spec ?register_children ?(force=false) e kf ?stmt ?active spec = let full_spec = get_spec_all kf ?stmt ?active () in let conflicts = @@ -1228,20 +1311,22 @@ let add_spec ?register_children ?(force=false) e kf ?stmt ?active spec = | _ -> []) in if not force && conflicts <> [] then raise (AlreadySpecified conflicts) ; - add_behaviors ?register_children e kf ?stmt ?active spec.spec_behavior; + do_add_behaviors ?register_children e kf ?stmt ?active spec.spec_behavior; Option.iter - (fun variant -> add_decreases ~force e kf variant) + (fun variant -> do_add_decreases ~force e kf variant) spec.spec_variant; Option.iter - (fun terminates -> add_terminates ~force e kf ?stmt ?active terminates) + (fun terminates -> do_add_terminates ~force e kf ?stmt ?active terminates) spec.spec_terminates; List.iter - (fun complete -> add_complete e kf ?stmt ?active complete) + (fun complete -> do_add_complete e kf ?stmt ?active complete) spec.spec_complete_behaviors; List.iter - (fun disjoint -> add_disjoint e kf ?stmt ?active disjoint) - spec.spec_disjoint_behaviors + (fun disjoint -> do_add_disjoint e kf ?stmt ?active disjoint) + spec.spec_disjoint_behaviors; + Changed.apply() +(* internal use only *) let extend_behavior e kf ?stmt ?active ?(behavior=Cil.default_behavior_name) set_bhv = (* Kernel.feedback "Function %a, behavior %s" Kf.pretty kf bhv_name;*) @@ -1263,7 +1348,8 @@ let extend_behavior Property_status.remove ip; set_bhv b b'; let ip = Property.ip_of_behavior kf (kinstr stmt) ~active b in - Property_status.register ip + Property_status.register ip; + Changed.apply() let add_requires e kf ?stmt ?active ?behavior l = let set_bhv _ bhv = @@ -1397,7 +1483,8 @@ let add_extended e kf ?stmt ?active ?behavior ext = (** {3 Adding code annotations} *) -let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca = +(* internal use only *) +let do_add_code_annot ~keep_empty emitter ?kf stmt ca = (* Kernel.feedback "%a: adding code annot %a with stmt %a (%d)" Project.pretty (Project.current ()) Code_annotation.pretty ca @@ -1442,18 +1529,18 @@ let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca = | [ { annot_content = AStmtSpec _ } ] -> let register_children = true in let active = bhvs in - add_behaviors + do_add_behaviors ~register_children emitter kf ~stmt ~active spec.spec_behavior; if spec.spec_variant <> None then Kernel.fatal "statement contract cannot have a decrease clause"; Option.iter - (add_terminates emitter kf ~stmt ~active) spec.spec_terminates; + (do_add_terminates emitter kf ~stmt ~active) spec.spec_terminates; List.iter - (add_complete emitter kf ~stmt ~active) + (do_add_complete emitter kf ~stmt ~active) spec.spec_complete_behaviors; List.iter - (add_disjoint emitter kf ~stmt ~active) + (do_add_disjoint emitter kf ~stmt ~active) spec.spec_disjoint_behaviors; (* By construction, we have exactly one contract corresponding to our criterion and emitter. *) @@ -1557,6 +1644,10 @@ let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca = | APragma _ | AExtended _ -> fill_tables ca (Property.ip_of_code_annot kf stmt ca) +let add_code_annot ?(keep_empty=true) emitter ?kf stmt ca = + do_add_code_annot ~keep_empty emitter ?kf stmt ca; + Changed.apply() + let add_assert e ?kf stmt a = let a = Logic_const.toplevel_predicate ~kind:Assert a in let a = Logic_const.new_code_annotation (AAssert ([],a)) in @@ -1654,7 +1745,8 @@ let add_model_field e m = try Emitter.Usable_emitter.Hashtbl.find h e with Not_found -> [] in - Emitter.Usable_emitter.Hashtbl.replace h e (m::l) + Emitter.Usable_emitter.Hashtbl.replace h e (m::l); + Changed.apply() let unsafe_add_global e a = (* Kernel.feedback "adding global %a in project %a" @@ -1669,7 +1761,8 @@ let unsafe_add_global e a = let add_global e a = unsafe_add_global e a; - if Ast.is_computed() then insert_global_in_ast a + if Ast.is_computed() then insert_global_in_ast a; + Changed.apply() (**************************************************************************) (** {2 Other useful functions} *) @@ -1766,7 +1859,9 @@ let code_annot_of_kf kf = match kf.fundec with (* don't export the possibility to removing an annotation without associated statuses. This is purely internal. *) -let remove_code_annot e ?kf stmt ca = remove_code_annot_internal e ?kf stmt ca +let remove_code_annot e ?kf stmt ca = + remove_code_annot_internal e ?kf stmt ca; + Changed.apply() (* Local Variables: diff --git a/src/kernel_services/ast_data/annotations.mli b/src/kernel_services/ast_data/annotations.mli index 3d84adb429de8fd69bd5644009a5b8a062b515df..f05e3dececf4db420c5163b7595a344c15779a65 100644 --- a/src/kernel_services/ast_data/annotations.mli +++ b/src/kernel_services/ast_data/annotations.mli @@ -30,6 +30,10 @@ open Cil_types (** {2 Getting annotations} *) (**************************************************************************) +val add_hook_on_change: (unit -> unit) -> unit +(** Emitted whenever any of the annotation tables is modified. + @since 27.0-Cobalt *) + (**************************************************************************) (** {3 Code annotations} *) (**************************************************************************) diff --git a/src/kernel_services/ast_data/cil_types.ml b/src/kernel_services/ast_data/cil_types.ml index 21a599460d2fdb73bd81e6e805e3c075424be978..d603249ae2e308282a4f99c8a8e619c36ea3f7b9 100644 --- a/src/kernel_services/ast_data/cil_types.ml +++ b/src/kernel_services/ast_data/cil_types.ml @@ -1836,27 +1836,31 @@ type kernel_function = { mutable spec : funspec; } -(* [VP] TODO: VLocal should be attached to a particular block, not a whole - function. It might be worth it to unify this type with the newer - syntactic_scope below. -*) -type localisation = - | VGlobal - | VLocal of kernel_function - | VFormal of kernel_function - (** Various syntactic scopes through which an identifier might be searched. Note that for this purpose static variables are still tied to the block where they were declared in the original source (see {!Cil_types.block}). @since Chlorine-20180501 *) type syntactic_scope = + | Global + (** Any global symbol, whether static or not. + @since 27.0-Cobalt + *) | Program (** Only non-static global symbols. *) | Translation_unit of Filepath.Normalized.t (** Any global visible within the given C source file. *) + | Formal of kernel_function + (** formal parameter of the given function. + @since 27.0-Cobalt + *) | Block_scope of stmt - (** same as above + all locals of the blocks to which the given statement + (** locals (including static locals) of the block to which the given statement belongs. *) + | Whole_function of kernel_function + (** same as above, but any local variable of the given function, regardless of + the block to which it is tied, will be considered. + @since 27.0-Cobalt + *) (** Definition of a machine model (architecture + compiler). @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *) @@ -1872,8 +1876,22 @@ type mach = { sizeof_void: int; (* Size of "void" *) sizeof_fun: int; (* Size of function. Negative if unsupported. *) size_t: string; (* Type of "sizeof(T)" *) + ssize_t: string; (* representation of ssize_t *) wchar_t: string; (* Type of "wchar_t" *) ptrdiff_t: string; (* Type of "ptrdiff_t" *) + intptr_t: string; (* Type of "intptr_t" *) + uintptr_t: string; (* Type of "uintptr_t" *) + int_fast8_t: string; (* Type of "int_fast8_t" *) + int_fast16_t: string; (* Type of "int_fast16_t" *) + int_fast32_t: string; (* Type of "int_fast32_t" *) + int_fast64_t: string; (* Type of "int_fast64_t" *) + uint_fast8_t: string; (* Type of "uint_fast8_t" *) + uint_fast16_t: string; (* Type of "uint_fast16_t" *) + uint_fast32_t: string; (* Type of "uint_fast32_t" *) + uint_fast64_t: string; (* Type of "uint_fast64_t" *) + wint_t: string; (* Type of "wint_t" *) + sig_atomic_t: string; (* Type of "sig_atomic_t" *) + time_t: string; (* Type of "time_t" *) alignof_short: int; (* Alignment of "short" *) alignof_int: int; (* Alignment of "int" *) alignof_long: int; (* Alignment of "long" *) @@ -1885,8 +1903,6 @@ type mach = { alignof_str: int; (* Alignment of strings *) alignof_fun: int; (* Alignment of function. Negative if unsupported. *) char_is_unsigned: bool; (* Whether "char" is unsigned *) - underscore_name: bool; (* If assembly names have leading underscore *) - const_string_literals: bool; (* Whether string literals have const chars *) little_endian: bool; (* whether the machine is little endian *) alignof_aligned: int (* Alignment of a type with aligned attribute *); has__builtin_va_list: bool (* Whether [__builtin_va_list] is a known type *); @@ -1895,6 +1911,24 @@ type mach = { cpp_arch_flags: string list; (* Architecture-specific flags to be given to the preprocessor (if supported) *) version: string; (* Information on this machdep *) + weof: string; (* expansion of WEOF macro, empty if undefined *) + wordsize: string; (* expansion of __WORDSIZE macro, empty if undefined *) + posix_version: string; (* expansion of _POSIX_VERSION macro, empty if undefined *) + bufsiz: string; (* expansion of BUFSIZ macro *) + eof: string; (* expansion of EOF macro *) + fopen_max: string; (* expansion of FOPEN_MAX macro *) + filename_max: string; (* expansion of FILENAME_MAX macro *) + host_name_max: string; (* expansion of HOST_NAME_MAX macro *) + tty_name_max: string; (* expansion of TTY_NAME_MAX macro *) + l_tmpnam: string; (* expansion of L_tmpnam macro *) + path_max: string; (* expansion of PATH_MAX macro *) + tmp_max: string; (* expansion of TMP_MAX macro *) + rand_max: string; (* expansion of RAND_MAX macro *) + mb_cur_max: string; (* expansion of MB_CUR_MAX macro *) + nsig: string; (* expansion of non-standard NSIG macro, empty if undefined *) + errno: (string * string) list; (* list of macros defining errors in errno.h*) + machdep_name: string; (* name of the machdep *) + custom_defs: string; (* arbitrary text to be written in the header *) } (* diff --git a/src/kernel_services/ast_data/globals.ml b/src/kernel_services/ast_data/globals.ml index 42b251943f4224c468d6d214c88d10aa91f1dcd4..4211f7a067776bf54e2f4dc46c3d19f18713bbf7 100644 --- a/src/kernel_services/ast_data/globals.ml +++ b/src/kernel_services/ast_data/globals.ml @@ -43,6 +43,8 @@ let get_locals f = match f.fundec with let get_location kf = match kf.fundec with | Definition (_, loc) | Declaration (_,_,_, loc) -> loc +let get_statics = Extlib.mk_fun "Globals.get_statics" + let find_first_stmt = Extlib.mk_fun "Globals.find_first_stmt" let find_enclosing_block = Extlib.mk_fun "Globals.find_enclosing_block" @@ -73,21 +75,40 @@ module Vars = struct let add_decl vi = add vi { init = None } - let get_astinfo_ref : (Cil_types.varinfo -> string * localisation) ref = + let get_astinfo_ref : (Cil_types.varinfo -> string * syntactic_scope) ref = Extlib.mk_fun "get_astinfo_ref" exception Found of varinfo - let find_from_astinfo name = function - | VGlobal -> + let find_from_astinfo name scope = + let iter_glob cond = + try + iter (fun v _ -> if cond v then raise (Found v)); + raise Not_found + with Found v -> v + in + match scope with + | Global -> iter_glob (fun v -> v.vname = name) + | Program -> + iter_glob (fun v -> v.vname = name && not (v.vstorage = Static)) + | Translation_unit file -> + iter_glob + (fun v -> + v.vname = name && + Filepath.Normalized.equal file (fst v.vdecl).pos_path) + | Whole_function kf -> + List.find (fun v -> v.vname = name) (get_locals kf @ !get_statics kf) + | Formal kf -> + List.find (fun v -> v.vname = name) (get_formals kf) + | Block_scope stmt -> + let blocks = !find_all_enclosing_blocks stmt in (try - iter (fun v _ -> if v.vname = name then raise (Found v)); + List.iter + (fun b -> + (List.iter (fun v -> if v.vname = name then raise (Found v)) + (b.blocals @ b.bstatics))) + blocks; raise Not_found - with Found v -> - v) - | VLocal kf -> - List.find (fun v -> v.vname = name) (get_locals kf) - | VFormal kf -> - List.find (fun v -> v.vname = name) (get_formals kf) + with Found v -> v) let get_astinfo vi = !get_astinfo_ref vi @@ -394,7 +415,12 @@ module Functions = struct exception Found of kernel_function let get_astinfo vi = vi.vname, - if vi.vglob then VGlobal + if vi.vglob then begin + if vi.vstorage = Static then + Translation_unit (fst vi.vdecl).pos_path + else + Program + end else begin if vi.vformal then begin try @@ -404,7 +430,7 @@ module Functions = struct then raise (Found kf)); assert false with Found kf -> - VFormal kf + Formal kf end else begin try iter @@ -413,7 +439,8 @@ module Functions = struct then raise (Found kf)); assert false with Found kf -> - VLocal kf + (* TODO: find the block where the varinfo is defined. *) + Whole_function kf end end @@ -622,8 +649,8 @@ end module Syntactic_search = struct module Key = - Datatype.Pair_with_collections - (Datatype.String)(Cil_datatype.Syntactic_scope) + Datatype.Triple_with_collections + (Datatype.String)(Cil_datatype.Syntactic_scope)(Datatype.Bool) (struct let module_name = "Globals.Datatype.Key" end) module Scope_info = @@ -639,23 +666,40 @@ module Syntactic_search = struct let () = Ast.add_monotonic_state self - let rec find_var (x,scope) = + let rec find_var (x,scope,strict) = let has_name v = v.vorig_name = x in let global_has_name v = has_name v && v.vglob && not (Cil.hasAttribute Cabs2cil.fc_local_static v.vattr) in + let lookup next_scope candidate = + match candidate with + | Some _ -> candidate + | None when strict -> candidate + | None -> find_in_scope x next_scope + in let module M = struct exception Found of varinfo end in match scope with + | Global -> + (try + Vars.iter (fun v _ -> if has_name v then raise (M.Found v)); + None + with M.Found v -> Some v) | Program -> (try Vars.iter (fun v _ -> if global_has_name v then raise (M.Found v)); None with M.Found v -> Some v) | Translation_unit file -> - let symbols = FileIndex.get_globals file in - (try Some (fst (List.find (fun x -> (global_has_name (fst x))) symbols)) - with Not_found -> find_in_scope x Program) + let symbols,_ = List.split (FileIndex.get_globals file) in + List.find_opt global_has_name symbols |> lookup Program + | Formal kf -> + let file = (fst (get_location kf)).Filepath.pos_path in + List.find_opt has_name (get_formals kf) |> + lookup (Translation_unit file) + | Whole_function kf -> + List.find_opt has_name (get_locals kf @ !get_statics kf) |> + lookup (Formal kf) | Block_scope stmt -> let blocks = !find_all_enclosing_blocks stmt in let find_in_block b = @@ -665,17 +709,19 @@ module Syntactic_search = struct raise (M.Found (List.find has_name b.bstatics)) in try - List.iter find_in_block blocks; - let kf = !find_englobing_kf stmt in - let filename = (fst ( get_location kf)).Filepath.pos_path in - let formals = get_formals kf in - if List.exists has_name formals then - Some (List.find has_name formals) + (* blocks can't be empty, we have at least the body of the function. *) + find_in_block (List.hd blocks); + if strict then None else - find_in_scope x (Translation_unit filename) + begin + List.iter find_in_block (List.tl blocks); + let kf = !find_englobing_kf stmt in + if strict then None else find_in_scope x (Formal kf) + end with M.Found v -> Some v - and find_in_scope x scope = Scope_info.memo find_var (x,scope) + and find_in_scope ?(strict=false) x scope = + Scope_info.memo find_var (x,scope,strict) end diff --git a/src/kernel_services/ast_data/globals.mli b/src/kernel_services/ast_data/globals.mli index 51ff3e98930da8c361f16d549623fce442cbbc93..82c52f193756bb583247a554bfb034ba90a218e4 100644 --- a/src/kernel_services/ast_data/globals.mli +++ b/src/kernel_services/ast_data/globals.mli @@ -35,7 +35,7 @@ module Vars: sig val find: varinfo -> initinfo - val find_from_astinfo: string -> localisation -> varinfo + val find_from_astinfo: string -> syntactic_scope -> varinfo (** Finds a variable from its [vname] according to its localisation (which might be a local). If you wish to search for a symbol according to its original name in the source code and the syntactic scope in which @@ -43,7 +43,7 @@ module Vars: sig @raise Not_found if no such variable exists. *) - val get_astinfo: varinfo -> string * localisation + val get_astinfo: varinfo -> string * syntactic_scope (** Linear in the number of locals and formals of the program. *) (** {2 Iterators} *) @@ -221,13 +221,24 @@ end module Syntactic_search: sig val self: State.t - val find_in_scope: string -> syntactic_scope -> varinfo option + val find_in_scope: ?strict:bool -> string -> syntactic_scope -> varinfo option (** [find_in_scope orig_name scope] finds a variable from its [orig_name], according to the syntactic [scope] in which it should be searched. + @param strict indicates whether the symbol should be searched only in + the exact [scope] that it is given. It defaults to [false], meaning + that the search will look for enclosing scopes, according to C lookup + rules. More precisely, non-strict lookup will proceed according to the + following order: [Block_scope] will move across all enclosing blocks + up to the function body (or all locals will be searched directly in + case of [Whole_function]). Then, [Formal] will be considered, followed + by [Translation_unit] (for the file where the function is defined), + then [Program]. @return [None] if there are no variables [orig_name] in [scope]. @return [Some vi] otherwise, with [vi] the [varinfo] associated to - [orig_name] in [scope] according to C lookup rules. + [orig_name] in [scope] (or an enclosing scope when [strict] is false). @since Chlorine-20180501 + @before 27.0-Cobalt [strict] parameter did not exist, symbol was always + searched according to C lookup rules. *) end @@ -338,6 +349,7 @@ val get_comments_stmt: stmt -> string list (* Forward reference to functions defined in Kernel_function. Do not use outside of this module. *) +val get_statics: (kernel_function -> varinfo list) ref val find_first_stmt: (kernel_function -> stmt) ref val find_enclosing_block: (stmt -> block) ref val find_all_enclosing_blocks: (stmt -> block list) ref diff --git a/src/kernel_services/ast_data/kernel_function.ml b/src/kernel_services/ast_data/kernel_function.ml index be29ec2b73fb94bc4a0bbdb433efd413e7d7e80f..1776d39211ec7d2ca18590947e62c903d807ce6f 100644 --- a/src/kernel_services/ast_data/kernel_function.ml +++ b/src/kernel_services/ast_data/kernel_function.ml @@ -67,6 +67,8 @@ let get_statics f = match f.fundec with !statics | Declaration (_, _, _, _) -> [] +let () = Globals.get_statics := get_statics + exception No_Definition let get_definition kf = match kf.fundec with | Definition (f,_) -> f diff --git a/src/kernel_services/ast_data/property_status.mli b/src/kernel_services/ast_data/property_status.mli index bddc3ea1c9f4eeb4ff36ebd51e744bdeb225e1e7..f25ccdcc65bd7e33052bdb2314dcd18be59f0211 100644 --- a/src/kernel_services/ast_data/property_status.mli +++ b/src/kernel_services/ast_data/property_status.mli @@ -141,7 +141,7 @@ val fold_on_statuses: val register_status_update_hook: (emitter_with_properties -> Property.t -> emitted_status -> unit) -> unit (** Registers an hook to be called each time a property status is emitted. - @since Frama-C+dev *) + @since 27.0-Cobalt *) (* ************************************************************************ *) (** {2 Consolidated status} *) diff --git a/src/kernel_services/ast_printing/cil_printer.ml b/src/kernel_services/ast_printing/cil_printer.ml index cd8d3806d7e91d1f1fc4bd7d8213b8bb832abb99..7301e2f5ed22d72161b128129b352cb24a83dfd0 100644 --- a/src/kernel_services/ast_printing/cil_printer.ml +++ b/src/kernel_services/ast_printing/cil_printer.ml @@ -2530,20 +2530,22 @@ class cil_printer () = object (self) fprintf fmt "@[%a@]" self#tand_list (get_tand_list l [r]) | TBinOp (op,l,r) -> fprintf fmt "@[%a@ %a@ %a@]" term l self#term_binop op term r - | TCastE (ty,e) -> + | TCastE (ty,t) -> begin match ty, t.term_node with | TFloat(fk,_) , TConst(LReal r as cst) when not Kernel.(is_debug_key_enabled dkey_print_logic_coercions) && Floating_point.has_suffix fk r.r_literal -> self#logic_constant fmt cst | _ -> - fprintf fmt "(%a)%a" (self#typ None) ty term e + fprintf fmt "(%a)%a" (self#typ None) ty term t end | TAddrOf lv -> fprintf fmt "&%a" (self#term_lval_prec Precedence.addrOfLevel) lv - | TStartOf lv -> fprintf fmt "(%a)%a" - (self#logic_type None) t.term_type - (self#term_lval_prec current_level) lv + | TStartOf lv -> + let typ = Logic_utils.array_to_ptr (Cil.typeOfTermLval lv) in + fprintf fmt "(%a)%a" + (self#logic_type None) typ + (self#term_lval_prec current_level) lv (* A few built-ins for lists have special syntax. Use it when we're not in print-as-is mode. *) | Tapp ({ l_var_info },[],[e1; e2]) @@ -3435,6 +3437,12 @@ let () = Cil.pp_lval_ref := pp_lval let () = Cil.pp_ikind_ref := pp_ikind let () = Cil.pp_attribute_ref := pp_attribute let () = Cil.pp_attributes_ref := pp_attributes +let () = Cil.pp_term_ref := pp_term +let () = Cil.pp_logic_type_ref := pp_logic_type +let () = Cil.pp_identified_term_ref := pp_identified_term +let () = Cil.pp_location_ref := pp_location +let () = Cil.pp_from_ref := pp_from +let () = Cil.pp_behavior_ref := pp_behavior (* Local Variables: diff --git a/src/kernel_services/ast_printing/cil_types_debug.ml b/src/kernel_services/ast_printing/cil_types_debug.ml index 052943406bf0f43ed5cde2c2c43c2cbb2e5e632c..97cbc21081fba3d4763edac53f4ed9bf1f68c882 100644 --- a/src/kernel_services/ast_printing/cil_types_debug.ml +++ b/src/kernel_services/ast_printing/cil_types_debug.ml @@ -1035,10 +1035,15 @@ let pp_kernel_function fmt kernel_function = pp_cil_function kernel_function.fundec pp_funspec kernel_function.spec -let pp_localisation fmt = function - | VGlobal -> Format.fprintf fmt "VGlobal" - | VLocal(kernel_function) -> Format.fprintf fmt "VLocal(%a)" pp_kernel_function kernel_function - | VFormal(kernel_function) -> Format.fprintf fmt "VFormal(%a)" pp_kernel_function kernel_function +let pp_syntactic_scope fmt = function + | Global -> pp_string fmt "Global" + | Program -> pp_string fmt "Program" + | Translation_unit file -> + Format.fprintf fmt "Translation_unit %S" (file:>string) + | Formal kf -> Format.fprintf fmt "Formal %a" pp_kernel_function kf + | Block_scope stmt -> Format.fprintf fmt "Local %a" pp_stmt stmt + | Whole_function kf -> + Format.fprintf fmt "Whole_function %a" pp_kernel_function kf let pp_mach fmt mach = Format.fprintf fmt @@ -1047,8 +1052,8 @@ let pp_mach fmt mach = sizeof_void=%a;sizeof_fun=%a;size_t=%a;wchar_t=%a;ptrdiff_t=%a;\ alignof_short=%a;alignof_int=%a;alignof_long=%a;alignof_longlong=%a;\ alignof_ptr=%a;alignof_float=%a;alignof_double=%a;alignof_longdouble=%a;\ - alignof_str=%a;alignof_fun=%a;char_is_unsigned=%a;underscore_name=%a;\ - const_string_literals=%a;little_endian=%a;alignof_aligned=%a;\ + alignof_str=%a;alignof_fun=%a;char_is_unsigned=%a;\ + little_endian=%a;alignof_aligned=%a;\ has__builtin_va_list=%a;compiler=%a;\ cpp_arch_flags=%a;version=%a}" pp_int mach.sizeof_short @@ -1075,8 +1080,6 @@ let pp_mach fmt mach = pp_int mach.alignof_str pp_int mach.alignof_fun pp_bool mach.char_is_unsigned - pp_bool mach.underscore_name - pp_bool mach.const_string_literals pp_bool mach.little_endian pp_int mach.alignof_aligned pp_bool mach.has__builtin_va_list diff --git a/src/kernel_services/ast_printing/cil_types_debug.mli b/src/kernel_services/ast_printing/cil_types_debug.mli index cf447e2ad48636736196b54fe87b81f6bb754aef..e9d3c6fb74aa75dd700d3ed7812ad0406449817a 100644 --- a/src/kernel_services/ast_printing/cil_types_debug.mli +++ b/src/kernel_services/ast_printing/cil_types_debug.mli @@ -157,5 +157,5 @@ val pp_global_annotation : Cil_types.global_annotation Pretty_utils.formatter val pp_kinstr : Format.formatter -> Cil_types.kinstr -> unit val pp_cil_function : Format.formatter -> Cil_types.cil_function -> unit val pp_kernel_function : Format.formatter -> Cil_types.kernel_function -> unit -val pp_localisation : Format.formatter -> Cil_types.localisation -> unit +val pp_syntactic_scope: Format.formatter -> Cil_types.syntactic_scope -> unit val pp_mach : Format.formatter -> Cil_types.mach -> unit diff --git a/src/kernel_services/ast_queries/ast_diff.ml b/src/kernel_services/ast_queries/ast_diff.ml index de58f03133ae3fbc11682cd552b454bbed0b12ec..222d4c77a26e2b10ba247b08b698d63ff7a6b886 100644 --- a/src/kernel_services/ast_queries/ast_diff.ml +++ b/src/kernel_services/ast_queries/ast_diff.ml @@ -1388,7 +1388,7 @@ and enumitem_correspondence ?loc ei env = and gvar_correspondence ?loc vi env = let add vi = - match find_candidate_varinfo ?loc vi Cil_types.VGlobal with + match find_candidate_varinfo ?loc vi Cil_types.Global with | None when Cil.isFunctionType vi.vtype -> begin match gfun_correspondence ?loc vi env with diff --git a/src/kernel_services/ast_queries/cil.ml b/src/kernel_services/ast_queries/cil.ml index c37a95eb29a7ee764725c4da4210b2e892c424d4..d5a6b27c12b79ccb5cd9734b8c2f9e42164efc67 100644 --- a/src/kernel_services/ast_queries/cil.ml +++ b/src/kernel_services/ast_queries/cil.ml @@ -105,7 +105,6 @@ type theMachine = mutable lowerConstants: bool; (** Do lower constants (default true) *) mutable insertImplicitCasts: bool; (** Do insert implicit casts (default true) *) - mutable underscore_name: bool; mutable stringLiteralType: typ; mutable upointKind: ikind; mutable upointType: typ; @@ -120,11 +119,10 @@ type theMachine = let createMachine () = (* Contain dummy values *) { useLogicalOperators = false; - theMachine = Machdeps.x86_64; + theMachine = List.hd Cil_datatype.Machdep.reprs; lowerConstants = false(*true*); insertImplicitCasts = true; - underscore_name = true; - stringLiteralType = charPtrType; + stringLiteralType = charConstPtrType; upointKind = IChar; upointType = voidType; wcharKind = IChar; @@ -140,7 +138,6 @@ let copyMachine src dst = dst.theMachine <- src.theMachine; dst.lowerConstants <- src.lowerConstants; dst.insertImplicitCasts <- src.insertImplicitCasts; - dst.underscore_name <- src.underscore_name; dst.stringLiteralType <- src.stringLiteralType; dst.upointKind <- src.upointKind; dst.upointType <- src.upointType; @@ -234,6 +231,12 @@ let pp_lval_ref = Extlib.mk_fun "Cil.pp_lval_ref" let pp_ikind_ref = Extlib.mk_fun "Cil.pp_ikind_ref" let pp_attribute_ref = Extlib.mk_fun "Cil.pp_attribute_ref" let pp_attributes_ref = Extlib.mk_fun "Cil.pp_attributes_ref" +let pp_term_ref = Extlib.mk_fun "Cil.pp_term_ref" +let pp_logic_type_ref = Extlib.mk_fun "Cil.pp_logic_type_ref" +let pp_identified_term_ref = Extlib.mk_fun "Cil.pp_identified_term_ref" +let pp_location_ref = Extlib.mk_fun "Cil.pp_location_ref" +let pp_from_ref = Extlib.mk_fun "Cil.pp_from_ref" +let pp_behavior_ref = Extlib.mk_fun "Cil.pp_behavior_ref" let default_behavior_name = "default!" let is_default_mk_behavior ~name ~assumes = name = default_behavior_name && assumes =[] @@ -3689,7 +3692,9 @@ let rec typeOf (e: exp) : typ = * have SizeOfStr for that *) | Const(CStr _s) -> theMachine.stringLiteralType - | Const(CWStr _s) -> TPtr(theMachine.wcharType,[]) + | Const(CWStr _s) -> + let typ = typeAddAttributes [Attr("const",[])] theMachine.wcharType in + TPtr(typ,[]) | Const(CReal (_, fk, _)) -> TFloat(fk, []) @@ -6408,9 +6413,7 @@ let initCIL ~initLogicBuiltins machdep = (* Set the machine *) theMachine.theMachine <- machdep; (* Pick type for string literals *) - theMachine.stringLiteralType <- - if theMachine.theMachine.const_string_literals then charConstPtrType - else charPtrType; + theMachine.stringLiteralType <- charConstPtrType; (* Find the right ikind given the size *) let findIkindSz (unsigned: bool) (sz: int) : ikind = (* Test the most common sizes first *) @@ -6453,8 +6456,6 @@ let initCIL ~initLogicBuiltins machdep = theMachine.wcharType <- TInt(theMachine.wcharKind, []); theMachine.ptrdiffKind <- findIkindName theMachine.theMachine.ptrdiff_t; theMachine.ptrdiffType <- TInt(theMachine.ptrdiffKind, []); - theMachine.underscore_name <- - theMachine.theMachine.Cil_types.underscore_name; theMachine.useLogicalOperators <- Kernel.LogicalOperators.get() (* do not use lazy LAND and LOR *); (*nextGlobalVID <- 1 ; nextCompinfoKey <- 1;*) diff --git a/src/kernel_services/ast_queries/cil.mli b/src/kernel_services/ast_queries/cil.mli index e72b94b9228cff384ad8d91edf0ca53139097053..8b63fb51b24e9a757822fd9696bd9c9b00902fcc 100644 --- a/src/kernel_services/ast_queries/cil.mli +++ b/src/kernel_services/ast_queries/cil.mli @@ -70,10 +70,6 @@ type theMachine = private mutable lowerConstants: bool; (** Do lower constants (default true) *) mutable insertImplicitCasts: bool; (** Do insert implicit casts (default true) *) - mutable underscore_name: bool; - (** Whether the compiler generates assembly labels by prepending "_" to - the identifier. That is, will function foo() have the label "foo", or - "_foo"? *) mutable stringLiteralType: typ; mutable upointKind: ikind (** An unsigned integer type that fits pointers. *); @@ -436,7 +432,7 @@ val isCompleteType: ?allowZeroSizeArrays:bool -> typ -> bool (** Performs lvalue-conversion on the type and returns the converted type, or Error if the type is incomplete and not an array type. - @since Frama-C+dev + @since 27.0-Cobalt *) val lvalue_conversion: typ -> (typ, string) result @@ -2362,6 +2358,12 @@ val pp_lval_ref: (Format.formatter -> lval -> unit) ref val pp_ikind_ref: (Format.formatter -> ikind -> unit) ref val pp_attribute_ref: (Format.formatter -> attribute -> unit) ref val pp_attributes_ref: (Format.formatter -> attribute list -> unit) ref +val pp_term_ref: (Format.formatter -> term -> unit) ref +val pp_logic_type_ref: (Format.formatter -> logic_type -> unit) ref +val pp_identified_term_ref: (Format.formatter -> identified_term -> unit) ref +val pp_location_ref: (Format.formatter -> location -> unit) ref +val pp_from_ref: (Format.formatter -> from -> unit) ref +val pp_behavior_ref: (Format.formatter -> behavior -> unit) ref val set_extension_handler: visit:(string -> cilVisitor -> acsl_extension_kind -> diff --git a/src/kernel_services/ast_queries/cil_datatype.ml b/src/kernel_services/ast_queries/cil_datatype.ml index 25c688a55d5671f268e68b266802a810db6ff9dc..ffd2febd6b3814af4e9a5c30012b4916ddc88e1c 100644 --- a/src/kernel_services/ast_queries/cil_datatype.ml +++ b/src/kernel_services/ast_queries/cil_datatype.ml @@ -2579,16 +2579,6 @@ module Lexpr = Make (** {3 Other types} *) (**************************************************************************) -module Localisation = - Datatype.Make - (struct - include Datatype.Serializable_undefined - type t = localisation - let name = "Localisation" - let reprs = [ VGlobal ] - let mem_project = Datatype.never_any_project - end) - module Syntactic_scope = Datatype.Make_with_collections (struct @@ -2598,6 +2588,9 @@ module Syntactic_scope = let reprs = [ Program ] let compare s1 s2 = match s1, s2 with + | Global, Global -> 0 + | Global, _ -> 1 + | _, Global -> -1 | Program, Program -> 0 | Program, _ -> 1 | _, Program -> -1 @@ -2605,22 +2598,117 @@ module Syntactic_scope = Datatype.Filepath.compare s1 s2 | Translation_unit _, _ -> 1 | _, Translation_unit _ -> -1 + | Formal kf1, Formal kf2 -> Kf.compare kf1 kf2 + | Formal _, _ -> 1 + | _, Formal _ -> -1 + | Whole_function kf1, Whole_function kf2 -> Kf.compare kf1 kf2 + | Whole_function _, _ -> 1 + | _, Whole_function _ -> -1 | Block_scope s1, Block_scope s2 -> Stmt_Id.compare s1 s2 let equal = Datatype.from_compare let hash s = match s with + | Global -> 3 | Program -> 5 | Translation_unit s -> 7 * Datatype.Filepath.hash s + 11 | Block_scope s -> 13 * Stmt_Id.hash s + 17 + | Whole_function kf -> 19 * Kf.hash kf + 23 + | Formal kf -> 29 * Kf.hash kf + 31 let pretty fmt = function - | Program -> Format.pp_print_string fmt "<Whole Program>" + | Global | Program -> Format.pp_print_string fmt "<Whole Program>" | Translation_unit s -> Format.fprintf fmt "File %a" Datatype.Filepath.pretty s + | Formal kf -> + Format.fprintf fmt "Parameter of %a" Kf.pretty kf + | Whole_function kf -> + Format.fprintf fmt "Local variable of %a" Kf.pretty kf | Block_scope s -> Format.fprintf fmt "Statement at %a:@\n@[%a@]" Location.pretty (Stmt.loc s) Stmt.pretty s end) +let dummy_machdep = + { + sizeof_short = 2; + sizeof_int = 4; + sizeof_long = 8; + sizeof_longlong = 8; + sizeof_ptr = 8; + sizeof_float = 4; + sizeof_double = 8; + sizeof_longdouble = 16; + sizeof_void = -1; + sizeof_fun = -1; + size_t = "unsigned long"; + ssize_t = "long"; + wchar_t = "int"; + ptrdiff_t = "long"; + intptr_t = "long"; (* Type of "intptr_t" *) + uintptr_t = "unsigned long"; (* Type of "uintptr_t" *) + int_fast8_t = "signed char"; + int_fast16_t = "long"; + int_fast32_t = "long"; + int_fast64_t = "long"; + uint_fast8_t = "unsigned char"; + uint_fast16_t = "unsigned long"; + uint_fast32_t = "unsigned long"; + uint_fast64_t = "unsigned long"; + wint_t = "int"; + sig_atomic_t = "int"; + time_t = "long"; + alignof_short = 2; + alignof_int = 4; + alignof_long = 8; + alignof_longlong = 8; + alignof_ptr = 8; + alignof_float = 4; + alignof_double = 8; + alignof_longdouble = 16; + alignof_str = 1; + alignof_fun = -1; + char_is_unsigned = true; + little_endian = true; + alignof_aligned = 16; + has__builtin_va_list = true; + compiler = "none"; + cpp_arch_flags = []; + version = "N/A"; + weof = "(-1)"; + wordsize = "64"; + posix_version = ""; + bufsiz = "255"; + eof = "(-1)"; + fopen_max = "255"; + filename_max = "4095"; + path_max = "256"; + tty_name_max = "255"; + host_name_max = "255"; + l_tmpnam = "63"; + tmp_max = "1024"; + rand_max = "0xFFFFFFFE"; + mb_cur_max = "16"; + nsig = ""; + errno = [ + "edom", "33"; + "eilseq", "84"; + "erange", "34"; + ]; + machdep_name = "dummy"; + custom_defs = ""; + } + +module Machdep = Datatype.Make_with_collections(struct + include Datatype.Serializable_undefined + let reprs = [dummy_machdep] + let name = "Machdep" + type t = Cil_types.mach + let compare : t -> t -> int = Stdlib.compare + let equal : t -> t -> bool = (=) + let hash : t -> int = Hashtbl.hash + let copy = Datatype.identity + end) + + (* -------------------------------------------------------------------------- *) (* --- Internal --- *) (* -------------------------------------------------------------------------- *) diff --git a/src/kernel_services/ast_queries/cil_datatype.mli b/src/kernel_services/ast_queries/cil_datatype.mli index efdc0387d21f1e6ae9daa8bd46bc1ec8517ba195..e145312e6c62f29d44dfbd6df84070e4ab1afabc 100644 --- a/src/kernel_services/ast_queries/cil_datatype.mli +++ b/src/kernel_services/ast_queries/cil_datatype.mli @@ -102,8 +102,6 @@ module Location: sig val equal_start_semantic : location -> location -> bool end -module Localisation: Datatype.S with type t = localisation - module Syntactic_scope: Datatype.S_with_collections with type t = syntactic_scope @@ -369,6 +367,13 @@ module PredicateStructEq: S_with_collections_pretty with type t = predicate module Lexpr: S with type t = Logic_ptree.lexpr (** Beware: no pretty-printer is available. *) +(**************************************************************************) +(** {3 Machdep} *) +(**************************************************************************) + +module Machdep: S_with_collections with type t = mach +(** since 27.0-Cobalt *) + (**/**) (* ****************************************************************************) (** {2 Internal API} *) diff --git a/src/kernel_services/ast_queries/file.ml b/src/kernel_services/ast_queries/file.ml index b15088fa8d6fd1432063c008cc1e9690028bccf3..213a01aa72e0f96f949d035b2793bb2151a65b44 100644 --- a/src/kernel_services/ast_queries/file.ml +++ b/src/kernel_services/ast_queries/file.ml @@ -23,7 +23,6 @@ open Cil_types open Cil open Visitor -open Cil_datatype type cpp_opt_kind = Gnu | Not_gnu | Unknown @@ -267,81 +266,34 @@ let print_machdep fmt (m : Cil_types.mach) = (if m.char_is_unsigned then "unsigned" else "signed"); Format.fprintf fmt " machine is %s endian@\n" (if m.little_endian then "little" else "big") ; - Format.fprintf fmt " strings are %s chars@\n" - (if m.const_string_literals then "const" else "writable") ; - Format.fprintf fmt " assembly names %s leading '_'@\n" - (if m.underscore_name then "have" else "have no") ; Format.fprintf fmt " compiler %s builtin __va_list@\n" (if m.has__builtin_va_list then "has" else "has not") ; end -module DatatypeMachdep = Datatype.Make_with_collections(struct - include Datatype.Serializable_undefined - let reprs = [Machdeps.x86_32] - let name = "File.Machdep" - type t = Cil_types.mach - let compare : t -> t -> int = Stdlib.compare - let equal : t -> t -> bool = (=) - let hash : t -> int = Hashtbl.hash - let copy = Datatype.identity - end) - -let default_machdeps = - [ "x86_16", Machdeps.x86_16; - "x86_32", Machdeps.x86_32; - "x86_64", Machdeps.x86_64; - "gcc_x86_16", Machdeps.gcc_x86_16; - "gcc_x86_32", Machdeps.gcc_x86_32; - "gcc_x86_64", Machdeps.gcc_x86_64; - "ppc_32", Machdeps.ppc_32; - "msvc_x86_64", Machdeps.msvc_x86_64; - ] - -let regexp_existing_machdep_macro = Str.regexp "-D[ ]*__FC_MACHDEP_" - -let existing_machdep_macro () = - let extra = String.concat " " (Kernel.CppExtraArgs.get ()) in - try - ignore (Str.search_forward regexp_existing_machdep_macro extra 0); - true - with Not_found -> false - -let machdep_macro = function - | "x86_16" -> "__FC_MACHDEP_X86_16" - | "gcc_x86_16" -> "__FC_MACHDEP_GCC_X86_16" - | "x86_32" -> "__FC_MACHDEP_X86_32" - | "gcc_x86_32" -> "__FC_MACHDEP_GCC_X86_32" - | "x86_64" -> "__FC_MACHDEP_X86_64" - | "gcc_x86_64" -> "__FC_MACHDEP_GCC_X86_64" - | "ppc_32" -> "__FC_MACHDEP_PPC_32" - | "msvc_x86_64" -> "__FC_MACHDEP_MSVC_X86_64" - | s -> - let res = "__FC_MACHDEP_" ^ (String.uppercase_ascii s) in - Kernel.warning ~once:true - "machdep %s has no registered macro. Using %s for pre-processing" s res; - res - -module Machdeps = - State_builder.Hashtbl(Datatype.String.Hashtbl)(DatatypeMachdep) - (struct - let name = " File.Machdeps" - let size = 5 - let dependencies = [] - end) +let machdep_dir () = Kernel.Share.get_dir ~mode:`Must_exist "machdeps" -let mem_machdep s = Machdeps.mem s || List.mem_assoc s default_machdeps +let regexp_machdep = Str.regexp "^machdep_\\([^.]*\\).yaml$" -let new_machdep s m = - try - let cm = Machdeps.find s in - if not (cm = m) then - Kernel.abort "trying to register incompatible machdeps under name `%s'" s - with Not_found -> - Machdeps.add s m +let default_machdep_file machdep = + let filename = "machdep_" ^ machdep ^ ".yaml" in + Filepath.Normalized.concat (machdep_dir()) filename + +let is_default_machdep machdep = + Filepath.Normalized.is_file (default_machdep_file machdep) + +let mem_machdep s = is_default_machdep s || Sys.file_exists s + +let default_machdeps () = + Array.fold_right + (fun s acc -> + if Str.string_match regexp_machdep s 0 then + Str.matched_group 1 s :: acc + else acc) + (Sys.readdir (machdep_dir() :> string)) + [] let pretty_machdeps fmt = - Machdeps.iter (fun x _ -> Format.fprintf fmt "@ %s" x); - List.iter (fun (x, _) -> Format.fprintf fmt "@ %s" x) default_machdeps + List.iter (fun s -> Format.fprintf fmt "@ %s" s) (default_machdeps()) let machdep_help () = let m = Kernel.Machdep.get () in @@ -358,23 +310,116 @@ let () = Cmdline.run_after_exiting_stage machdep_help let set_machdep () = let m = Kernel.Machdep.get () in if not (mem_machdep m) then - Kernel.abort "@[unsupported machine %s.@ Try one of%t.@]" m pretty_machdeps + Kernel.abort "@[unsupported machine '%s'.@ Either use a predefined name among %t,@ or an YAML machdep file.@]" m pretty_machdeps let () = Cmdline.run_after_configuring_stage set_machdep +let yaml_dict_to_list = function + | `O l -> + let make_one acc (k,v) = + Result.( + bind acc + (fun l -> + match Yaml.Util.to_string v with + | Ok s -> Ok((k,s) :: l) + | Error (`Msg s) -> + Error (`Msg ("Unexpected value for key " ^ k ^ ": " ^ s)))) + in + List.fold_left make_one (Ok []) l + | _ -> Error (`Msg "Unexpected YAML value instead of dictionary of strings") + +type mach = Cil_types.mach = { + sizeof_short: int; + sizeof_int: int; + sizeof_long: int ; + sizeof_longlong: int; + sizeof_ptr: int; + sizeof_float: int; + sizeof_double: int; + sizeof_longdouble: int; + sizeof_void: int; + sizeof_fun: int; + size_t: string; + ssize_t: string; + wchar_t: string; + ptrdiff_t: string; + intptr_t: string; + uintptr_t: string; + int_fast8_t: string; + int_fast16_t: string; + int_fast32_t: string; + int_fast64_t: string; + uint_fast8_t: string; + uint_fast16_t: string; + uint_fast32_t: string; + uint_fast64_t: string; + wint_t: string; + sig_atomic_t: string; + time_t: string; + alignof_short: int; + alignof_int: int; + alignof_long: int; + alignof_longlong: int; + alignof_ptr: int; + alignof_float: int; + alignof_double: int; + alignof_longdouble: int; + alignof_str: int; + alignof_fun: int; + char_is_unsigned: bool; + little_endian: bool; + alignof_aligned: int; + has__builtin_va_list: bool; + compiler: string; + cpp_arch_flags: string list; + version: string; + weof: string; + wordsize: string; + posix_version: string; + bufsiz: string; + eof: string; + fopen_max: string; + filename_max: string; + host_name_max: string; + tty_name_max: string; + l_tmpnam: string; + path_max: string; + tmp_max: string; + rand_max: string; + mb_cur_max: string; + nsig: string; + errno: (string * string) list [@of_yaml yaml_dict_to_list]; + machdep_name: string; + custom_defs: string; +} +[@@deriving yaml] + (* Local to this module. Use Cil.theMachine.theMachine outside *) let get_machdep () = let m = Kernel.Machdep.get () in - try - Machdeps.find m - with Not_found -> - try - List.assoc m default_machdeps - with Not_found -> (* Should not happen given the checks above *) - Kernel.fatal "Machdep %s not registered" m + let file = + if is_default_machdep m then default_machdep_file m + else Filepath.Normalized.of_string ~existence:Must_exist m + in + let res = + Result.bind + (Yaml_unix.of_file (Fpath.v (file:>string))) + mach_of_yaml + in + match res with + | Ok machdep -> machdep + | Error (`Msg s) -> + Kernel.abort "Error during machdep parsing: %s" s + +let print_machdep_header () = + if Kernel.PrintMachdepHeader.get () then begin + Machdep.gen_all_defines Format.std_formatter (get_machdep()); + raise Cmdline.Exit + end else Cmdline.nop + +let () = Cmdline.run_after_exiting_stage print_machdep_header -let list_available_machdeps () = - Machdeps.fold (fun m _ acc -> m :: acc) (List.map fst default_machdeps) +let list_available_machdeps = default_machdeps let pretty_machdep ?fmt ?machdep () = let machine = match machdep with None -> get_machdep () | Some m -> m in @@ -463,33 +508,14 @@ let build_cpp_cmd = function (* Hypothesis: the preprocessor is POSIX compliant, hence understands -I and -D. *) let fc_include_args = - if Kernel.FramaCStdLib.get () then [(Fc_config.framac_libc:>string)] - else [] - in - let fc_define_args = - if not (existing_machdep_macro ()) - then [machdep_macro (Kernel.Machdep.get ())] + if Kernel.FramaCStdLib.get () then + begin + let machdep_dir = Machdep.generate_machdep_header (get_machdep()) in + [(machdep_dir:>string); (Fc_config.framac_libc:>string)] + end else [] in - let fc_define_args = "__FRAMAC__" :: fc_define_args in - (* Hypothesis: the preprocessor does support the arch-related - options tested when 'configure' was run. *) - let required_cpp_arch_args = (get_machdep ()).cpp_arch_flags in - let supported_cpp_arch_args, unsupported_cpp_arch_args = - List.partition (fun arg -> - List.mem arg Fc_config.preprocessor_supported_arch_options) - required_cpp_arch_args - in - if is_gnu_like = Unknown && not (Kernel.CppCommand.is_set ()) - && unsupported_cpp_arch_args <> [] then - Kernel.warning ~once:true - "your preprocessor is not known to handle option(s) `%s', \ - considered necessary for machdep `%s'. To ensure compatibility \ - between your preprocessor and the machdep, consider using \ - -cpp-command with the appropriate flags. \ - Your preprocessor is known to support these flags: %s" - (concat_strs unsupported_cpp_arch_args) (Kernel.Machdep.get ()) - (concat_strs Fc_config.preprocessor_supported_arch_options); + let fc_define_args = ["__FRAMAC__"] in let nostdinc_arg = if Kernel.FramaCStdLib.get() then add_if_gnu "-nostdinc" else [] @@ -511,7 +537,7 @@ let build_cpp_cmd = function in let supp_args = string_of_supp_args - (gnu_implicit_args @ supported_cpp_arch_args @ + (gnu_implicit_args @ extra_for_this_file @ (Kernel.CppExtraArgs.get ())) fc_include_args fc_define_args in @@ -524,7 +550,7 @@ let build_cpp_cmd = function Kernel.feedback ~dkey:Kernel.dkey_pp "preprocessing with \"%s\"" cpp_command_with_chdir; - Some (cpp_command_with_chdir, ppf, supported_cpp_arch_args) + Some (cpp_command_with_chdir, ppf) let abort_with_detailed_pp_message f cpp_command = let possible_cause = @@ -562,7 +588,7 @@ let parse_cabs cpp_command = function Datatype.Filepath.pretty f; Frontc.parse f () | NeedCPP (f, cmdl, _extra_for_this_file, is_gnu_like) -> - let cpp_command, ppf, logic_pp_args = Option.get cpp_command in + let cpp_command, ppf = Option.get cpp_command in Kernel.feedback "Parsing %a (with preprocessing)" Datatype.Filepath.pretty f; if Sys.command cpp_command <> 0 then begin @@ -582,12 +608,9 @@ let parse_cabs cpp_command = function "trying to preprocess annotation with an unknown \ preprocessor."; true)) then begin - let supp_args = - Format.asprintf "%s" (concat_strs ~pre:" " ~sep:" " logic_pp_args) - in let ppf' = try Logic_preprocess.file ".c" - (replace_in_cpp_cmd cmdl supp_args) + (replace_in_cpp_cmd cmdl "") (ppf : Filepath.Normalized.t :> string) with Sys_error _ as e -> safe_remove_file ppf; @@ -913,7 +936,7 @@ let cleanup file = let visitor = object(self) inherit Visitor.frama_c_inplace - val mutable keep_stmt = Stmt.Set.empty + val mutable keep_stmt = Cil_datatype.Stmt.Set.empty val mutable changed = false @@ -927,9 +950,9 @@ let cleanup file = method! vstmt_aux st = self#remove_lexical_annotations st; - let loc = Stmt.loc st in + let loc = Cil_datatype.Stmt.loc st in if Annotations.has_code_annot st || st.labels <> [] || st.sattr <> [] then - keep_stmt <- Stmt.Set.add st keep_stmt; + keep_stmt <- Cil_datatype.Stmt.Set.add st keep_stmt; match st.skind with | Block b -> (* queue is flushed afterwards*) @@ -945,8 +968,9 @@ let cleanup file = b.bstmts <- List.filter (fun x -> - not (Cil.is_skip x.skind) || Stmt.Set.mem x keep_stmt || - ( changed <- true; false) (* don't try this at home, kids...*) + not (Cil.is_skip x.skind) + || Cil_datatype.Stmt.Set.mem x keep_stmt + || (changed <- true; false) ) b.bstmts; (* Now that annotations are in the table, we do not need to @@ -1262,7 +1286,7 @@ let find_logic_info_decl li = | GAnnot (ga,_) -> if List.exists - (fun li' -> Logic_info.equal li li') + (fun li' -> Cil_datatype.Logic_info.equal li li') (extract_logic_infos ga) then raise (F.Found g) | _ -> ()) @@ -1284,12 +1308,12 @@ class reorder_ast: Visitor.frama_c_visitor = in object(self) inherit Visitor.frama_c_inplace - val mutable known_enuminfo = Enuminfo.Set.empty - val mutable known_compinfo = Compinfo.Set.empty - val mutable known_typeinfo = Typeinfo.Set.empty - val mutable known_var = Varinfo.Set.empty - val mutable known_logic_info = Logic_info.Set.empty - val mutable local_logic_info = Logic_info.Set.empty + val mutable known_enuminfo = Cil_datatype.Enuminfo.Set.empty + val mutable known_compinfo = Cil_datatype.Compinfo.Set.empty + val mutable known_typeinfo = Cil_datatype.Typeinfo.Set.empty + val mutable known_var = Cil_datatype.Varinfo.Set.empty + val mutable known_logic_info = Cil_datatype.Logic_info.Set.empty + val mutable local_logic_info = Cil_datatype.Logic_info.Set.empty (* globals that have to be declared before current declaration. *) val mutable needed_decls = [] @@ -1306,19 +1330,19 @@ class reorder_ast: Visitor.frama_c_visitor = val logic_info_deps = Global_annotation_graph.create () method private add_known_enuminfo ei = - known_enuminfo <- Enuminfo.Set.add ei known_enuminfo + known_enuminfo <- Cil_datatype.Enuminfo.Set.add ei known_enuminfo method private add_known_compinfo ci = - known_compinfo <- Compinfo.Set.add ci known_compinfo + known_compinfo <- Cil_datatype.Compinfo.Set.add ci known_compinfo method private add_known_type ty = - known_typeinfo <- Typeinfo.Set.add ty known_typeinfo + known_typeinfo <- Cil_datatype.Typeinfo.Set.add ty known_typeinfo method private add_known_var vi = - known_var <- Varinfo.Set.add vi known_var + known_var <- Cil_datatype.Varinfo.Set.add vi known_var method private add_known_logic_info li = - known_logic_info <- Logic_info.Set.add li known_logic_info + known_logic_info <- Cil_datatype.Logic_info.Set.add li known_logic_info method private add_needed_decl g = needed_decls <- g :: needed_decls @@ -1396,8 +1420,8 @@ class reorder_ast: Visitor.frama_c_visitor = (Daxiomatic (unique_name_recursive_axiomatic (), entries, attr, - Location.unknown), - Location.unknown))::res) + Cil_datatype.Location.unknown), + Cil_datatype.Location.unknown))::res) entries [] end else begin Global_annotation_graph.fold @@ -1422,7 +1446,7 @@ class reorder_ast: Visitor.frama_c_visitor = | TNamed (ty,_) -> let g = find_typeinfo ty in - if not (Typeinfo.Set.mem ty known_typeinfo) then begin + if not (Cil_datatype.Typeinfo.Set.mem ty known_typeinfo) then begin self#add_needed_decl g; Stack.push g typedefs; Stack.push true subvisit; @@ -1440,19 +1464,19 @@ class reorder_ast: Visitor.frama_c_visitor = ty.tname) typedefs | TComp(ci,_) -> - if not (Compinfo.Set.mem ci known_compinfo) then begin - self#add_needed_decl (GCompTagDecl (ci,Location.unknown)); + if not (Cil_datatype.Compinfo.Set.mem ci known_compinfo) then begin + self#add_needed_decl(GCompTagDecl(ci,Cil_datatype.Location.unknown)); self#add_known_compinfo ci end | TEnum(ei,_) -> - if not (Enuminfo.Set.mem ei known_enuminfo) then begin - self#add_needed_decl (GEnumTagDecl (ei, Location.unknown)); + if not (Cil_datatype.Enuminfo.Set.mem ei known_enuminfo) then begin + self#add_needed_decl(GEnumTagDecl(ei,Cil_datatype.Location.unknown)); self#add_known_enuminfo ei end); DoChildren method! vvrbl vi = - if vi.vglob && not (Varinfo.Set.mem vi known_var) then begin + if vi.vglob && not (Cil_datatype.Varinfo.Set.mem vi known_var) then begin if Cil.isFunctionType vi.vtype then self#add_needed_decl (GFunDecl (Cil.empty_funspec(),vi,vi.vdecl)) else @@ -1465,7 +1489,7 @@ class reorder_ast: Visitor.frama_c_visitor = if not (Logic_env.is_builtin_logic_function lv.l_var_info.lv_name) then begin let g = find_logic_info_decl lv in - if not (Logic_info.Set.mem lv known_logic_info) then begin + if not(Cil_datatype.Logic_info.Set.mem lv known_logic_info) then begin self#add_annot_depend g; Stack.push true subvisit; (* visit will also push g in needed_annot. *) @@ -1477,13 +1501,13 @@ class reorder_ast: Visitor.frama_c_visitor = end method private add_local_logic_info li = - local_logic_info <- Logic_info.Set.add li local_logic_info + local_logic_info <- Cil_datatype.Logic_info.Set.add li local_logic_info method private remove_local_logic_info li = - local_logic_info <- Logic_info.Set.remove li local_logic_info + local_logic_info <- Cil_datatype.Logic_info.Set.remove li local_logic_info method private is_local_logic_info li = - Logic_info.Set.mem li local_logic_info + Cil_datatype.Logic_info.Set.mem li local_logic_info method! vlogic_var_use lv = let logic_infos = Annotations.logic_info_of_global lv.lv_name in @@ -1541,48 +1565,53 @@ class reorder_ast: Visitor.frama_c_visitor = module Remove_spurious = struct type env = - { typeinfos: Typeinfo.Set.t; - compinfos: Compinfo.Set.t; - enuminfos: Enuminfo.Set.t; - varinfos: Varinfo.Set.t; - logic_infos: Logic_info.Set.t; + { typeinfos: Cil_datatype.Typeinfo.Set.t; + compinfos: Cil_datatype.Compinfo.Set.t; + enuminfos: Cil_datatype.Enuminfo.Set.t; + varinfos: Cil_datatype.Varinfo.Set.t; + logic_infos: Cil_datatype.Logic_info.Set.t; kept: global list; } let treat_one_global acc g = match g with - | GType (ty,_) when Typeinfo.Set.mem ty acc.typeinfos -> acc + | GType (ty,_) when Cil_datatype.Typeinfo.Set.mem ty acc.typeinfos -> acc | GType (ty,_) -> { acc with - typeinfos = Typeinfo.Set.add ty acc.typeinfos; + typeinfos = Cil_datatype.Typeinfo.Set.add ty acc.typeinfos; kept = g :: acc.kept } | GCompTag _ -> { acc with kept = g :: acc.kept } - | GCompTagDecl(ci,_) when Compinfo.Set.mem ci acc.compinfos -> acc + | GCompTagDecl(ci,_) + when Cil_datatype.Compinfo.Set.mem ci acc.compinfos -> acc | GCompTagDecl(ci,_) -> { acc with - compinfos = Compinfo.Set.add ci acc.compinfos; + compinfos = Cil_datatype.Compinfo.Set.add ci acc.compinfos; kept = g :: acc.kept } | GEnumTag _ -> { acc with kept = g :: acc.kept } - | GEnumTagDecl(ei,_) when Enuminfo.Set.mem ei acc.enuminfos -> acc + | GEnumTagDecl(ei,_) + when Cil_datatype.Enuminfo.Set.mem ei acc.enuminfos -> acc | GEnumTagDecl(ei,_) -> { acc with - enuminfos = Enuminfo.Set.add ei acc.enuminfos; + enuminfos = Cil_datatype.Enuminfo.Set.add ei acc.enuminfos; kept = g :: acc.kept } | GVarDecl(vi,_) | GFunDecl (_, vi, _) - when Varinfo.Set.mem vi acc.varinfos -> acc + when Cil_datatype.Varinfo.Set.mem vi acc.varinfos -> acc | GVarDecl(vi,_) -> { acc with - varinfos = Varinfo.Set.add vi acc.varinfos; + varinfos = Cil_datatype.Varinfo.Set.add vi acc.varinfos; kept = g :: acc.kept } | GVar _ | GFun _ | GFunDecl _ -> { acc with kept = g :: acc.kept } | GAsm _ | GPragma _ | GText _ -> { acc with kept = g :: acc.kept } | GAnnot (a,_) -> let lis = extract_logic_infos a in - if List.exists (fun x -> Logic_info.Set.mem x acc.logic_infos) lis + if List.exists + (fun x -> Cil_datatype.Logic_info.Set.mem x acc.logic_infos) + lis then acc else begin let known_li = - List.fold_left (Fun.flip Logic_info.Set.add) acc.logic_infos lis + List.fold_left + (Fun.flip Cil_datatype.Logic_info.Set.add) acc.logic_infos lis in { acc with kept = g::acc.kept; @@ -1591,11 +1620,11 @@ module Remove_spurious = struct end let empty = - { typeinfos = Typeinfo.Set.empty; - compinfos = Compinfo.Set.empty; - enuminfos = Enuminfo.Set.empty; - varinfos = Varinfo.Set.empty; - logic_infos = Logic_info.Set.empty; + { typeinfos = Cil_datatype.Typeinfo.Set.empty; + compinfos = Cil_datatype.Compinfo.Set.empty; + enuminfos = Cil_datatype.Enuminfo.Set.empty; + varinfos = Cil_datatype.Varinfo.Set.empty; + logic_infos = Cil_datatype.Logic_info.Set.empty; kept = []; } @@ -1677,7 +1706,7 @@ let compute_sources_table cpp_commands = add_source_if_new all_sources_tbl (get_filepath file); match cmd_opt with | None -> () - | Some (cpp_cmd, _ppf, _sl) -> + | Some (cpp_cmd, _ppf) -> let tmp_file = create_temp_file "audit_produce_sources" ".txt" in let tmp_file = (tmp_file :> string) in let cmd_for_sources = cpp_cmd ^ " -H -MM >/dev/null 2>" ^ tmp_file in @@ -1750,7 +1779,7 @@ let check_source_hashes expected actual_table = end let print_and_exit cpp_commands = - let print_cpp_cmd (cpp_cmd, _ppf, _) = + let print_cpp_cmd (cpp_cmd, _ppf) = Kernel.result "Preprocessing command:@.%s" cpp_cmd in List.iter (fun (_f, ocmd) -> Option.iter print_cpp_cmd ocmd) cpp_commands; diff --git a/src/kernel_services/ast_queries/file.mli b/src/kernel_services/ast_queries/file.mli index f6ac175cf92ef311404e4a4be5cdb185c576eb88..b0da114f710eb07aa892549ae92e31cd826a4a98 100644 --- a/src/kernel_services/ast_queries/file.mli +++ b/src/kernel_services/ast_queries/file.mli @@ -53,29 +53,11 @@ val new_file_type: @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *) -val new_machdep: string -> Cil_types.mach -> unit -(** [new_machdep name module] registers a new machdep name as recognized by - Frama-C through The usual uses is - [Cmdline.run_after_loading_stage - (fun () -> File.new_machdep "my_machdep" my_machdep_implem)] - @since Nitrogen-20111001 - @raise Invalid_argument if the given name already exists - @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *) - -val machdep_macro: string -> string -(** [machdep_macro machine] returns the name of a macro __FC_MACHDEP_XXX so - that the preprocessor can select std lib definition consistent with - the selected machdep. This function will emit a warning if [machine] is - not known by default by the kernel and return __FC_MACHDEP_MACHINE in that - case. - @since Magnesium-20151001 (exported in the API) -*) - val list_available_machdeps: unit -> string list (** [list_available_machdeps ()] gives the list of the names of available - machdeps, starting with the ones added with new_machdep and ending with - the list of default machdeps. - @since 22.0-Titanium *) + machdeps in Frama-C's share path + @since 22.0-Titanium +*) type code_transformation_category (** type of registered code transformations diff --git a/src/kernel_services/ast_queries/logic_parse_string.ml b/src/kernel_services/ast_queries/logic_parse_string.ml index db62131f6e9554636d042c46fb1b5b86777468eb..a75626bd53c6f3927ca95be6d93e1c7e40faa12e 100644 --- a/src/kernel_services/ast_queries/logic_parse_string.ml +++ b/src/kernel_services/ast_queries/logic_parse_string.ml @@ -30,40 +30,32 @@ exception Unbound of string let find_var kf kinstr ?label var = let vi = try - let vi = Globals.Vars.find_from_astinfo var (VLocal kf) in - (match kinstr with - | Kglobal -> vi (* don't refine search: the Kglobal here - does not indicate the function contract, but merely - the fact that we do not have any information about - the targeted program point. Hence, no scope check - can be performed or we might reject many legitimate - terms and predicates. - *) - | Kstmt stmt -> - let scope = - match label with - | None | Some "Here" | Some "Post" | Some "Old" -> stmt + let scope = + match kinstr with + | Kglobal -> Whole_function kf + | Kstmt stmt -> + (match label with + | None | Some "Here" | Some "Post" | Some "Old" -> Block_scope stmt | Some "Pre" -> raise Not_found (* no local variable in scope. *) | Some "Init" -> raise Not_found (* no local variable in scope. *) | Some "LoopEntry" | Some "LoopCurrent" -> if not (Kernel_function.stmt_in_loop kf stmt) then Kernel.fatal "Use of LoopEntry or LoopCurrent outside of a loop"; - Kernel_function.find_enclosing_loop kf stmt + Block_scope (Kernel_function.find_enclosing_loop kf stmt) | Some l -> - (try let s = Kernel_function.find_label kf l in !s + (try let s = Kernel_function.find_label kf l in Block_scope !s with Not_found -> Kernel.fatal "Use of label %s that does not exist in function %a" - l Kernel_function.pretty kf) - in - if Kernel_function.var_is_in_scope scope vi then vi - else raise Not_found) + l Kernel_function.pretty kf)) + in + Globals.Vars.find_from_astinfo var scope with Not_found -> try - Globals.Vars.find_from_astinfo var (VFormal kf) + Globals.Vars.find_from_astinfo var (Formal kf) with Not_found -> - Globals.Vars.find_from_astinfo var VGlobal + Globals.Vars.find_from_astinfo var Global in cvar_to_lvar vi diff --git a/src/kernel_services/ast_queries/logic_typing.ml b/src/kernel_services/ast_queries/logic_typing.ml index 2aab058b278f481654b30c244eb060a8266414e1..13ea19b232fa3826cfcc3e388b49a4c67132d3a5 100644 --- a/src/kernel_services/ast_queries/logic_typing.ml +++ b/src/kernel_services/ast_queries/logic_typing.ml @@ -318,6 +318,11 @@ module Lenv = struct (* to determine in which post-state we should go in case of nested \at(\at(...,Post),Pre) *) + keep_qualifiers: bool; + (* indicates whether we should keep qualifiers in term's type. + Almost always false, except as head nodes of specific + clauses such as assigns or volatile. + *) } let string_of_current_label env = @@ -411,7 +416,8 @@ module Lenv = struct current_logic_label = None; is_post_state = None; enclosing_post_state=None; - is_funspec=false + is_funspec=false; + keep_qualifiers=false; } let funspec () = @@ -462,6 +468,9 @@ let post_state_env kind typ = let env = enter_post_state env kind in env +let keep_qualifiers env = { env with Lenv.keep_qualifiers = true } +let drop_qualifiers env = { env with Lenv.keep_qualifiers = false } + type type_namespace = Typedef | Struct | Union | Enum module Type_namespace = @@ -632,6 +641,9 @@ sig (term_offset * Cil_types.logic_type) val mk_cast: ?explicit:bool -> Cil_types.term -> Cil_types.logic_type -> Cil_types.term + val conditional_conversion: + Cil_types.location -> Logic_ptree.relation option -> + Cil_types.term -> Cil_types.term -> Cil_types.logic_type val term : Lenv.t -> Logic_ptree.lexpr -> term val predicate : Lenv.t -> Logic_ptree.lexpr -> predicate val code_annot : @@ -1786,23 +1798,15 @@ struct in mk_mem b TNoOffset + let string_of_rel = function + | Eq -> "eq" + | Neq -> "ne" + | Le -> "le" + | Lt -> "lt" + | Ge -> "ge" + | Gt -> "gt" - - let conditional_conversion loc env rel t1 t2 = - let is_rel = Option.is_some rel in - (* a comparison is mainly a function of type 'a -> 'a -> Bool/Prop. - performs the needed unifications on both sides.*) - let var = fresh_type_var "cmp" in - let env,_,_ = - partial_unif ~overloaded:false loc t1 t1.term_type var env in - let env,ty2,_ = - partial_unif ~overloaded:false loc t2 t2.term_type var env in - (* in case first partial unification did not instantiate all variables - we do another pass on t1 with information from t2. - *) - let env,ty1,_ = - partial_unif ~overloaded:false loc t1 t1.term_type var env - in + let conditional_conversion loc rel t1 t2 = let rec aux lty1 lty2 = match (unroll_type lty1), (unroll_type lty2) with | Ctype ty1, Ctype ty2 -> @@ -1820,25 +1824,30 @@ struct else if is_enum_cst t1 lty2 then lty2 else if is_enum_cst t2 lty1 then lty1 else Ctype (C.conditionalConversion ty1 ty2) - else if isArithmeticType ty1 && isArithmeticType ty2 then begin - if is_same_type lty1 lty2 then begin - if is_rel then begin - let rel = Option.get rel in - let kind = - match Cil.unrollType ty1 with - | TFloat (FFloat,_) -> "float" - | TFloat (FDouble,_) -> "double" - | TFloat (FLongDouble,_) -> "long double" - | _ -> Kernel.fatal "floating point type expected" - in - let source = fst loc in - Kernel.warning ~source ~wkey:Kernel.wkey_acsl_float_compare - "comparing two %s values as real values. You might \ - want to use \\%s_%s instead" kind rel kind; - Lreal - end else lty1 - end else Lreal - end else if is_same_ptr_type ty1 ty2 || is_same_array_type ty1 ty2 then + else if isArithmeticType ty1 && isArithmeticType ty2 then + begin + if is_same_type lty1 lty2 then + begin + match rel with + | None -> lty1 + | Some rel -> + let kind = + match Cil.unrollType ty1 with + | TFloat (FFloat,_) -> "float" + | TFloat (FDouble,_) -> "double" + | TFloat (FLongDouble,_) -> "long double" + | _ -> Kernel.fatal "floating point type expected" + in + let source = fst loc in + Kernel.warning ~source + ~wkey:Kernel.wkey_acsl_float_compare + "comparing two %s values as real values. You might \ + want to use \\%s_%s instead" kind + (string_of_rel rel) kind; + Lreal + end else Lreal + end else + if is_same_ptr_type ty1 ty2 || is_same_array_type ty1 ty2 then Ctype (C.conditionalConversion ty1 ty2) else if (isPointerType ty1 || isArrayType ty1) && @@ -1860,25 +1869,47 @@ struct when is_integral_type t && name = Utf8_logic.boolean -> Ltype(C.find_logic_type Utf8_logic.boolean,[]) | Lreal, Ctype ty | Ctype ty, Lreal when isArithmeticType ty -> Lreal - | Ltype (s1,l1), Ltype (s2,l2) when s1.lt_name = s2.lt_name && - List.for_all2 is_same_type l1 l2 -> lty1 + | Ltype (s1,l1), Ltype (s2,l2) + when s1.lt_name = s2.lt_name && List.for_all2 is_same_type l1 l2 -> + lty1 | Lvar s1, Lvar s2 when s1 = s2 -> lty1 | Linteger, Linteger -> Linteger | (Lreal | Linteger) , (Lreal | Linteger) -> Lreal - | Ltype ({lt_name = "\\list"} as lt,[t1]), - Ltype({lt_name="\\list"},[t2]) -> - Ltype(lt,[aux t1 t2]) - | Ltype ({lt_name = "set"} as lt,[t1]), Ltype({lt_name="set"},[t2]) -> - Ltype(lt,[aux t1 t2]) + | Ltype ({lt_name = "\\list"} as lt,[ty1]), + Ltype({lt_name="\\list"},[ty2]) -> + Ltype(lt,[aux ty1 ty2]) + | Ltype ({lt_name = "set"} as lt,[ty1]), Ltype({lt_name="set"},[ty2]) -> + Ltype(lt,[aux ty1 ty2]) (* implicit conversion to set *) - | Ltype ({lt_name = "set"} as lt,[t1]), t2 - | t1, Ltype({lt_name="set"} as lt,[t2]) -> Ltype(lt,[aux t1 t2]) + | Ltype ({lt_name = "set"} as lt,[ty1]), ty2 + | ty1, Ltype({lt_name="set"} as lt,[ty2]) -> + Ltype(lt,[aux ty1 ty2]) | t1, t2 when is_same_type t1 t2 -> t1 | _ -> C.error loc "types %a and %a are not convertible" Cil_printer.pp_logic_type lty1 Cil_printer.pp_logic_type lty2 in - let rt = aux ty1 ty2 in + aux t1.term_type t2.term_type + + let conditional_common_type loc env rel t1 t2 = + (* a comparison is mainly a function of type 'a -> 'a -> Bool/Prop. + performs the needed unifications on both sides.*) + let var = fresh_type_var "cmp" in + let env,_,_ = + partial_unif ~overloaded:false loc t1 t1.term_type var env in + let env,ty2,_ = + partial_unif ~overloaded:false loc t2 t2.term_type var env in + (* in case first partial unification did not instantiate all variables + we do another pass on t1 with information from t2. + *) + let env,ty1,_ = + partial_unif ~overloaded:false loc t1 t1.term_type var env + in + let rt = + conditional_conversion loc rel + { t1 with term_type = ty1 } + { t2 with term_type = ty2 } + in env,rt,ty1,ty2 type conversion = NoConv | ArithConv | IntegralConv | PointerConv @@ -2515,7 +2546,7 @@ struct | Some t -> Tapp(info, label_assoc, tl), t and term_node ctxt env loc pl = let term = ctxt.type_term ctxt in - let term_ptr pl = + let term_ptr env pl = let t = term env pl in check_logic_pointer ~check_non_void:false loc t; t @@ -2527,13 +2558,16 @@ struct | PLinitField _ -> ctxt.error loc "unsupported aggregated field construct" | PLupdate (t, toff, PLupdateCont cont) -> + let env = drop_qualifiers env in let t = term env t in normalize_update_cont ctxt env loc t (cont, toff) | PLupdate (t, toff, PLupdateTerm v) -> + let env = drop_qualifiers env in let t = term env t in normalize_update_term ctxt env loc t v toff | PLsizeof typ -> + let env = drop_qualifiers env in (match Logic_const.unroll_ltdef (logic_type ctxt loc env typ) with Ctype t -> TSizeOf t,Linteger @@ -2545,7 +2579,7 @@ struct { lexpr_node = PLconstant (StringConstant s | WStringConstant s) } -> TSizeOfStr s, Linteger | PLsizeofE lexpr -> - let t = term env lexpr in + let t = term (drop_qualifiers env) lexpr in (match Logic_const.unroll_ltdef t.term_type with | Ctype _ -> TSizeOfE t, Linteger | _ -> if ctxt.silent then raise Backtrack; @@ -2568,6 +2602,11 @@ struct Ctype (TPtr(Cil.theMachine.wcharType,[])) | PLvar x -> let old_val info = + let typ = + if env.Lenv.keep_qualifiers then info.lv_type + else + Logic_utils.logic_type_remove_qualifiers info.lv_type + in let term = TLval (TVar info, TNoOffset) in if env.Lenv.is_funspec then begin let term = @@ -2579,8 +2618,8 @@ struct Tat(Logic_const.term ~loc term info.lv_type, find_logic_label loc env "Old") | Some _ | None -> term) - in term, info.lv_type - end else term, info.lv_type + in term, typ + end else term, typ in begin try @@ -2684,6 +2723,7 @@ struct %s as constant" x) end | PLapp (f, labels, tl) -> + let env = drop_qualifiers env in let f = try (match (ctxt.find_macro f).lexpr_node with | PLvar (x) -> x | _ -> ctxt.error loc "invalid definition for macro %s" f) @@ -2692,10 +2732,10 @@ struct fresh_type#reset (); lfun_app ctxt env loc f labels ttl | PLunop (Ubw_not, t) -> - let t = type_int_term ctxt env t in + let t = type_int_term ctxt (drop_qualifiers env) t in TUnOp (BNot, t), logic_arithmetic_promotion t.term_type | PLunop (Uminus, t) -> - let t = type_num_term ctxt env t in + let t = type_num_term ctxt (drop_qualifiers env) t in let ty = logic_arithmetic_promotion t.term_type in TUnOp (Neg, mk_cast t ty), ty | PLunop (Ustar, t) -> @@ -2706,7 +2746,11 @@ struct let t = mk_logic_pointer_or_StartOf t in check_non_void_ptr loc t.term_type; let t = mk_mem t TNoOffset in - t.term_node, t.term_type + let typ = + if env.Lenv.keep_qualifiers then t.term_type + else Logic_utils.logic_type_remove_qualifiers t.term_type + in + t.term_node, typ end else begin ctxt.error loc "invalid type %a for `unary *'" Cil_printer.pp_logic_type t.term_type @@ -2722,6 +2766,7 @@ struct t.term_node, t.term_type | PLbinop (t1, (Badd | Bsub | Bmul | Bdiv | Bmod | Bbw_and | Bbw_or | Bbw_xor | Blshift | Brshift as op), t2) -> + let env = drop_qualifiers env in let t1 = term env t1 in let ty1 = t1.term_type in let t2 = term env t2 in @@ -2788,6 +2833,10 @@ struct | PLdot (t, f) -> let t = term env t in let f_ofs, f_type = type_of_field loc f t.term_type in + let f_type = + if env.Lenv.keep_qualifiers then f_type + else Logic_utils.logic_type_remove_qualifiers f_type + in let t = lift_set (mk_dot env loc f_ofs f_type) t in t.term_node, t.term_type @@ -2800,11 +2849,15 @@ struct let t = mk_logic_pointer_or_StartOf t in let struct_type = type_of_pointed t.term_type in let f_ofs, f_type = type_of_field loc f struct_type in + let f_type = + if env.Lenv.keep_qualifiers then f_type + else Logic_utils.logic_type_remove_qualifiers f_type + in (mk_mem ~loc t f_ofs).term_node, f_type | PLarrget (t1, t2) -> let t1 = term env t1 in - let t2 = term env t2 in + let t2 = term (drop_qualifiers env) t2 in (* access to a C value (either array or pointer) *) let t'1, t'2, tres = if isLogicPointer t1 && is_integral_type t2.term_type then @@ -2813,8 +2866,12 @@ struct (* memory access need a current label to have some semantics *) let t1 = mk_logic_pointer_or_StartOf t1 in check_non_void_ptr t1.term_loc t1.term_type; - (t1, t2, - set_conversion (type_of_pointed t1.term_type) t2.term_type) + let typ = type_of_pointed t1.term_type in + let typ = + if env.Lenv.keep_qualifiers then typ + else Logic_utils.logic_type_remove_qualifiers typ + in + (t1, t2, set_conversion typ t2.term_type) end else if is_integral_type t1.term_type && isLogicPointer t2 then begin @@ -2822,8 +2879,12 @@ struct (* memory access need a current label to have some semantics *) let t2 = mk_logic_pointer_or_StartOf t2 in check_non_void_ptr t2.term_loc t2.term_type; - (t2, t1, - set_conversion (type_of_pointed t2.term_type) t1.term_type) + let typ = type_of_pointed t2.term_type in + let typ = + if env.Lenv.keep_qualifiers then typ + else Logic_utils.logic_type_remove_qualifiers typ + in + (t2, t1, set_conversion typ t1.term_type) end else if (* purely logical array access. *) isLogicArrayType t1.term_type && is_integral_type t2.term_type @@ -2843,11 +2904,11 @@ struct t.term_node, t.term_type | PLif (t1, t2, t3) -> - let t1 = type_bool_term ctxt env t1 in + let t1 = type_bool_term ctxt (drop_qualifiers env) t1 in let t2 = term env t2 in let t3 = term env t3 in let env,ty,ty2,ty3 = - conditional_conversion loc env None t2 t3 in + conditional_common_type loc env None t2 t3 in let t2 = { t2 with term_type = instantiate env t2.term_type } in let _,t2 = implicit_conversion @@ -2873,7 +2934,7 @@ struct | PLbase_addr (l, t) -> (* base_addr need a current label to have some semantics *) let l = find_current_logic_label loc env l in - let t = term_ptr t in + let t = term_ptr (drop_qualifiers env) t in let t = lift_set (fun t -> Logic_const.term (Tbase_addr (l,t)) @@ -2882,14 +2943,14 @@ struct | PLoffset (l, t) -> (* offset need a current label to have some semantics *) let l = find_current_logic_label loc env l in - let t = term_ptr t in + let t = term_ptr (drop_qualifiers env) t in let t = lift_set (fun t -> Logic_const.term (Toffset (l,t)) Linteger) t in t.term_node, t.term_type | PLblock_length (l, t) -> (* block_length need a current label to have some semantics *) let l = find_current_logic_label loc env l in - let t = term_ptr t in + let t = term_ptr (drop_qualifiers env) t in let t = lift_set (fun t -> Logic_const.term (Tblock_length (l,t)) Linteger) @@ -2897,6 +2958,7 @@ struct in t.term_node, t.term_type | PLresult -> (try let t = Lenv.find_var "\\result" env in + (* by construction, return type is a C type without qualifiers. *) match t.lv_type with Ctype ty -> TLval(TResult ty,TNoOffset), t.lv_type @@ -2911,8 +2973,13 @@ struct (* no casts of tsets in grammar *) let ct = Logic_const.unroll_ltdef (logic_type ctxt loc env ty) in let { term_node; term_type } = mk_cast ~explicit:true t ct in - (term_node, term_type) + let typ = + if env.Lenv.keep_qualifiers then term_type + else Logic_utils.logic_type_remove_qualifiers term_type + in + (term_node, typ) | PLrel (t1, (Eq | Neq | Lt | Le | Gt | Ge as op), t2) -> + let env = drop_qualifiers env in let f _ op t1 t2 = (TBinOp(binop_of_rel op, t1, t2), Ltype(ctxt.find_logic_type Utf8_logic.boolean,[])) @@ -2925,21 +2992,26 @@ struct let cfalse = ctxt.find_logic_ctor "\\false" in TDataCons(cfalse,[]), Ltype(cfalse.ctor_type,[]) | PLlambda(prms,e) -> + let env = drop_qualifiers env in let (prms, env) = add_quantifiers ctxt loc ~kind:LVFormal prms env in let e = term env e in Tlambda(prms,e),Larrow(List.map (fun x -> x.lv_type) prms,e.term_type) | PLnot t -> + let env = drop_qualifiers env in let t = type_bool_term ctxt env t in TUnOp(LNot,t), Ltype (ctxt.find_logic_type Utf8_logic.boolean,[]) | PLand (t1,t2) -> + let env = drop_qualifiers env in let t1 = type_bool_term ctxt env t1 in let t2 = type_bool_term ctxt env t2 in TBinOp(LAnd,t1,t2), Ltype (ctxt.find_logic_type Utf8_logic.boolean,[]) | PLor (t1,t2) -> + let env = drop_qualifiers env in let t1 = type_bool_term ctxt env t1 in let t2 = type_bool_term ctxt env t2 in TBinOp(LOr,t1,t2), Ltype (ctxt.find_logic_type Utf8_logic.boolean,[]) | PLtypeof t1 -> + let env = drop_qualifiers env in let t1 = term env t1 in Ttypeof t1, Ltype (ctxt.find_logic_type "typetag",[]) | PLtype ty -> @@ -2949,7 +3021,7 @@ struct ctxt.error loc "cannot take type tag of logic type" end | PLlet (ident, def, body) -> - let tdef = term env def in + let tdef = term (drop_qualifiers env) def in (* At least for now, the type is supposed to be fully instantiated. No generalization is needed. *) let var = Cil_const.make_logic_info_local ident in @@ -2965,7 +3037,11 @@ struct var.l_body <- LBterm tdef; let env = Lenv.add_logic_info ident var env in let tbody = term env body in - Tlet(var,tbody), tbody.term_type + let typ = + if env.Lenv.keep_qualifiers then tbody.term_type + else Logic_utils.logic_type_remove_qualifiers tbody.term_type + in + Tlet(var,tbody), typ | PLcomprehension(t,quants,pred) -> let quants, env = add_quantifiers ctxt loc ~kind:LVQuant quants env in let t = term env t in @@ -2973,7 +3049,11 @@ struct ctxt.error loc "sets of sets are not supported yet" end else begin let pred = Option.map (predicate env) pred in - Tcomprehension(t,quants,pred), (make_set_type t.term_type) + let typ = + if env.Lenv.keep_qualifiers then t.term_type + else Logic_utils.logic_type_remove_qualifiers t.term_type + in + Tcomprehension(t,quants,pred), (make_set_type typ) end | PLempty | PLset [] -> @@ -2997,6 +3077,7 @@ struct Tinter locs, typ | PLlist l -> fresh_type#reset(); + let env = drop_qualifiers env in let empty_list,typ_items = let empty_list,typ = lfun_app ctxt env loc "\\Nil" [] [] in empty_list,(type_of_list_elem typ) @@ -3017,12 +3098,14 @@ struct in List.fold_left add_ahead (empty_list, (make_type_list_of typ_items)) l | PLrepeat (t1,t2) -> + let env = drop_qualifiers env in let t1 = term env t1 in let t2 = term env t2 in fresh_type#reset (); lfun_app ctxt env loc "\\repeat" [] [t1; t2] | PLrange (t1,t2) -> (* we allow range of floats/real. *) + let env = drop_qualifiers env in let t1,ty1 = type_num_term_option ctxt env t1 in let t2,ty2 = type_num_term_option ctxt env t2 in (Trange(t1,t2), @@ -3044,17 +3127,9 @@ struct let ty1 = t1.term_type in let t2 = ctxt.type_term ctxt env t2 in let ty2 = t2.term_type in - let rel = match op with - | Eq -> "eq" - | Neq -> "ne" - | Le -> "le" - | Lt -> "lt" - | Ge -> "ge" - | Gt -> "gt" - in let conditional_conversion t1 t2 = let env,t,ty1,ty2 = - conditional_conversion loc env (Some rel) t1 t2 + conditional_common_type loc env (Some op) t1 t2 in let t1 = { t1 with term_type = instantiate env t1.term_type } in let _,t1 = @@ -3522,6 +3597,7 @@ struct (tl, Cil_types.From tf) let type_assign ctxt ~accept_formal env a = + let env = keep_qualifiers env in let module [@warning "-60"] C = struct end in match a with WritesAny -> Cil_types.WritesAny @@ -4216,7 +4292,7 @@ struct | LDmodel_annot l -> Dmodel_annot (model_annot loc l,loc); | LDvolatile (tsets, (rd_opt, wr_opt)) -> - let env = Lenv.empty () in + let env = keep_qualifiers (Lenv.empty ()) in let ctxt = base_ctxt env in let tsets = let accept_formal = false in diff --git a/src/kernel_services/ast_queries/logic_typing.mli b/src/kernel_services/ast_queries/logic_typing.mli index 8d267131d5fa5283bf600d79cc72b211c74c5bf5..f9f671cb80244851652504b355a6e099fe1e218a 100644 --- a/src/kernel_services/ast_queries/logic_typing.mli +++ b/src/kernel_services/ast_queries/logic_typing.mli @@ -163,6 +163,23 @@ sig val mk_cast: ?explicit:bool -> Cil_types.term -> Cil_types.logic_type -> Cil_types.term + (** [conditional_conversion loc rel t1 t2] + tries to find a common type between two terms, either as part of + a comparison or a conditional. + comparisons can notably introduce logic coercions to Real, potentially + with a warning if [acsl-float-compare] is active. + + @param loc the location of the comparison. Can be used in error/warning msg + @param rel the relation, or [None] for a conditional + @param t1 first term + @param t2 second term + + @since 27.0-Cobalt + *) + val conditional_conversion: + Cil_types.location -> Logic_ptree.relation option -> + Cil_types.term -> Cil_types.term -> Cil_types.logic_type + (** type-checks a term. *) val term : Lenv.t -> Logic_ptree.lexpr -> term diff --git a/src/kernel_services/ast_queries/logic_utils.ml b/src/kernel_services/ast_queries/logic_utils.ml index 0af75114af3d582931d53b4b77dd12730b333c34..d09f0711ca63a3def21b31357b56ec6503b4d8ea 100644 --- a/src/kernel_services/ast_queries/logic_utils.ml +++ b/src/kernel_services/ast_queries/logic_utils.ml @@ -108,7 +108,7 @@ let plain_array_to_ptr ty = Kernel.fatal "Inconsistent information: I know the length of \ array type %a, but not of its elements." - Cil_printer.pp_typ tarr + !Cil.pp_typ_ref tarr in (* Normally, overflow is checked in bitsSizeOf itself *) let la = AInt (Integer.of_int len) in @@ -123,6 +123,16 @@ let plain_array_to_ptr ty = let array_to_ptr = plain_or_set plain_array_to_ptr +let logic_type_remove_qualifiers = + let plain typ = + match unroll_type typ with + | Ctype t -> + let t' = Cil.type_remove_qualifier_attributes t in + if Cil_datatype.Typ.equal t t' then typ else Ctype t' + | _ -> typ + in + Logic_const.transform_element plain + let coerce_type typ = let ty = Cil.unrollType typ in if Cil.isIntegralType ty then Linteger @@ -217,7 +227,7 @@ let mk_logic_pointer_or_StartOf t = if is_C_array t then mk_logic_StartOf t else t else Kernel.fatal ~source:(fst t.term_loc) - "%a is neither a pointer nor a C array" Cil_printer.pp_term t + "%a is neither a pointer nor a C array" !Cil.pp_term_ref t let equal_ltype = Cil_datatype.Logic_type.equal @@ -398,7 +408,7 @@ let scalar_term_conversion conversion t = | Ctype (TVoid _ | TNamed _ | TComp _ | TBuiltin_va_list _) -> Kernel.fatal "Cannot convert a term of type %a" - Cil_printer.pp_logic_type t.term_type + !Cil.pp_logic_type_ref t.term_type let scalar_term_to_predicate = let conversion ~loc is_eq t1 t2 = @@ -572,7 +582,7 @@ and expr_to_boolean e = else Kernel.fatal "Cannot convert into predicate the C expression %a" - Cil_printer.pp_exp e + !Cil.pp_exp_ref e and expr_to_predicate e = let open Cil_types in @@ -618,7 +628,7 @@ and expr_to_predicate e = else Kernel.fatal "Cannot convert into predicate the C expression %a" - Cil_printer.pp_exp e + !Cil.pp_exp_ref e and expr_to_ipredicate e = Logic_const.new_predicate (expr_to_predicate e) @@ -2066,7 +2076,7 @@ let merge_assigns_list l1 l2 = let loc = asgn1.it_content.term_loc in Kernel.warning ~once:true ~source:(fst loc) "location %a is not present in all assigns clauses" - Cil_printer.pp_identified_term asgn1; + !Cil.pp_identified_term_ref asgn1; end; (asgn1, from1) :: aux q1 l2 | Some (asgn2, from2 as cl2), q2 -> @@ -2081,8 +2091,8 @@ let merge_assigns_list l1 l2 = Kernel.warning ~once:true ~source:(fst loc1) "@[incompatible@ from@ clauses (%a:'%a'@ and@ %a:'%a').@ \ Keeping@ only@ the first@ one.@]" - Cil_printer.pp_location loc1 Cil_printer.pp_from cl1 - Cil_printer.pp_location loc2 Cil_printer.pp_from cl2; + !Cil.pp_location_ref loc1 !Cil.pp_from_ref cl1 + !Cil.pp_location_ref loc2 !Cil.pp_from_ref cl2; cl1 :: aux q1 q2 end in @@ -2140,7 +2150,7 @@ let merge_behaviors ?(oldloc=Cil_datatype.Location.unknown) ~silent old_behavior (fun fmt -> if Kernel.debug_atleast 1 then Format.fprintf fmt ":@ @[%a@] vs. @[%a@]" - Cil_printer.pp_behavior b Cil_printer.pp_behavior old_b) + !Cil.pp_behavior_ref b !Cil.pp_behavior_ref old_b) ; old_b.b_assumes <- merge_ip_list old_b.b_assumes b.b_assumes; old_b.b_requires <- merge_ip_list old_b.b_requires b.b_requires; @@ -2362,7 +2372,7 @@ class complete_types = let complete_types f = Cil.visitCilFile (new complete_types) f -let pointer_comparable ?loc t1 t2 = +let pointer_comparable ?loc ?(label=Logic_const.here_label) t1 t2 = let preds = Logic_env.find_all_logic_functions "\\pointer_comparable" in let cfct_ptr = TPtr (TFun(Cil.voidType,None,false,[]),[]) in let fct_ptr = Ctype cfct_ptr in @@ -2404,7 +2414,7 @@ let pointer_comparable ?loc t1 t2 = with Not_found -> Kernel.fatal "built-in predicate \\pointer_comparable not found" in - Logic_const.unamed ?loc (Papp (pi, [], [t1;t2])) + Logic_const.unamed ?loc (Papp (pi, [label], [t1;t2])) let is_min_max_function name li = li.l_var_info.lv_name = name && diff --git a/src/kernel_services/ast_queries/logic_utils.mli b/src/kernel_services/ast_queries/logic_utils.mli index 1e94484c56da83f416155892b65fd691c73a0069..8ab9618a28e2b85de0278a8a57e59387440a5c95 100644 --- a/src/kernel_services/ast_queries/logic_utils.mli +++ b/src/kernel_services/ast_queries/logic_utils.mli @@ -78,6 +78,11 @@ val logicCType : logic_type -> typ (** transforms an array into pointer. *) val array_to_ptr : logic_type -> logic_type +(** removes qualifiers if logic_type is a C type, identity otherwise. + @since 27.0-Cobalt +*) +val logic_type_remove_qualifiers: logic_type -> logic_type + (** C type to logic type, with implicit conversion for arithmetic types. @since 21.0-Scandium *) @@ -146,9 +151,12 @@ val numeric_coerce: logic_type -> term -> term (** \valid_range *) (* val mk_pvalid_range: ?loc:location -> term * term * term -> predicate *) -val pointer_comparable: ?loc:location -> term -> term -> predicate -(** \pointer_comparable - @since Fluorine-20130401 *) +val pointer_comparable: + ?loc:location -> ?label:logic_label -> term -> term -> predicate +(** \pointer_comparable. [label] defaults to {!Logic_const.here_label} + @since Fluorine-20130401 + @before 27.0-Cobalt no [label] argument, as the builtin did not take a label +*) (** {2 Conversion from exp to term} *) diff --git a/src/kernel_services/plugin_entry_points/kernel.ml b/src/kernel_services/plugin_entry_points/kernel.ml index 656d60a3774fceaca97f28f2d8ac9d387ad585c1..a3507a0ac08575dd11e660d284a235db59edd8c4 100644 --- a/src/kernel_services/plugin_entry_points/kernel.ml +++ b/src/kernel_services/plugin_entry_points/kernel.ml @@ -429,6 +429,18 @@ module PrintMachdep = let help = "pretty print selected machdep" end) +let () = Parameter_customize.set_group help +let () = Parameter_customize.set_cmdline_stage Cmdline.Exiting +let () = Parameter_customize.set_negative_option_name "" +module PrintMachdepHeader = + False + (struct + let module_name = "PrintMachdepHeader" + let option_name = "-print-machdep-header" + let help = + "print on standard output the content of the generated __fc_machdep.h" + end) + let () = Parameter_customize.set_group help let () = Parameter_customize.set_negative_option_name "" module DumpDependencies = diff --git a/src/kernel_services/plugin_entry_points/kernel.mli b/src/kernel_services/plugin_entry_points/kernel.mli index 0c9a85462af183fe4fa69472d76847ca85d3c3cf..de72d6bb4dee30e023ad0cd0ce900a075ee3444f 100644 --- a/src/kernel_services/plugin_entry_points/kernel.mli +++ b/src/kernel_services/plugin_entry_points/kernel.mli @@ -320,6 +320,10 @@ module PrintMachdep : Parameter_sig.Bool (** Behavior of option "-print-machdep" @since Phosphorus-20170501-beta1 *) +module PrintMachdepHeader : Parameter_sig.Bool +(** Behavior of option "-print-machdep-header" + @since 27.0-Cobalt *) + module PrintLibc: Parameter_sig.Bool (** Behavior of option "-print-libc" @since Phosphorus-20170501-beta1 *) diff --git a/src/libraries/project/state_builder.ml b/src/libraries/project/state_builder.ml index cb369ad1045dee8526dbab6490b672807fed3683..c93f9c167b30cdc49e3c100f6542147c4a548e67 100644 --- a/src/libraries/project/state_builder.ml +++ b/src/libraries/project/state_builder.ml @@ -490,9 +490,11 @@ module type Hashtbl = sig ?cmp:(key -> key -> int) -> (key -> data -> 'a -> 'a) -> 'a -> 'a val memo: ?change:(data -> data) -> (key -> data) -> key -> data val find: key -> data + val find_opt: key -> data option val find_all: key -> data list val mem: key -> bool val remove: key -> unit + val to_seq: unit -> (key * data) Seq.t end module Hashtbl @@ -548,6 +550,7 @@ struct let replace key v = H.replace !state key v let add key v = H.add !state key v let find key = H.find !state key + let find_opt key = H.find_opt !state key let find_all key = H.find_all !state key let mem key = H.mem !state key let remove key = H.remove !state key @@ -555,6 +558,7 @@ struct let iter_sorted ?cmp f = H.iter_sorted ?cmp f !state let fold f acc = H.fold f !state acc let fold_sorted ?cmp f acc = H.fold_sorted ?cmp f !state acc + let to_seq () = H.to_seq !state let memo ?change f key = try diff --git a/src/libraries/project/state_builder.mli b/src/libraries/project/state_builder.mli index 22ca6683820b4526024778cd2c3fef2a661fdc28..60a7bacace307b8face4ba02c71688789fa19cb1 100644 --- a/src/libraries/project/state_builder.mli +++ b/src/libraries/project/state_builder.mli @@ -351,11 +351,20 @@ module type Hashtbl = sig (** Return the current binding of the given key. @raise Not_found if the key is not in the table. *) + val find_opt: key -> data option + (** Return the current binding of the given key, or None if no such binding + exists. + @since 27.0-Cobalt *) + val find_all: key -> data list (** Return the list of all data associated with the given key. *) val mem: key -> bool val remove: key -> unit + + val to_seq: unit -> (key * data) Seq.t + (** Iterate on the whole table. + @since 27.0-Cobalt *) end (** @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide diff --git a/src/libraries/utils/json.mll b/src/libraries/utils/json.mll index 47dfb1329c2d0ef5d9a2e23b2ebbe10846a64b0c..2017df4f36951a3090fbfacc045dd31a8fe485ab 100644 --- a/src/libraries/utils/json.mll +++ b/src/libraries/utils/json.mll @@ -334,7 +334,6 @@ let rec merge_assoc_lists la lb = List.rev r let merge_object path json_root_obj = - let open Yojson.Basic.Util in let existing_root_obj = try match Hashtbl.find json_tbl path with @@ -343,14 +342,13 @@ let merge_object path json_root_obj = with Not_found -> `Assoc [] in - let existing_assoc = existing_root_obj |> to_assoc in - let new_assoc = json_root_obj |> to_assoc in + let existing_assoc = existing_root_obj |> Yojson.Basic.Util.to_assoc in + let new_assoc = json_root_obj |> Yojson.Basic.Util.to_assoc in let merged = merge_assoc_lists existing_assoc new_assoc in let merged_obj = `Assoc merged in Hashtbl.replace json_tbl path merged_obj let merge_array path json_root_array = - let open Yojson.Basic.Util in let existing_root_array = try match Hashtbl.find json_tbl path with @@ -359,8 +357,8 @@ let merge_array path json_root_array = with Not_found -> `List [] in - let existing_list = existing_root_array |> to_list in - let new_list = json_root_array |> to_list in + let existing_list = existing_root_array |> Yojson.Basic.Util.to_list in + let new_list = json_root_array |> Yojson.Basic.Util.to_list in let merged_list = `List (existing_list @ new_list) in Hashtbl.replace json_tbl path merged_list diff --git a/src/libraries/utils/task.ml b/src/libraries/utils/task.ml index ff296b6638cad3631833af244f0b0ed0407da11f..557953250f45cd4473a3b7229cc64e2764cef2e3 100644 --- a/src/libraries/utils/task.ml +++ b/src/libraries/utils/task.ml @@ -36,7 +36,7 @@ let error = function (* ------------------------------------------------------------------------ *) type 'a status = - | Timeout of int + | Timeout of float | Canceled | Result of 'a | Failed of exn @@ -206,7 +206,7 @@ let sync m t = lock m >>= t >>? fun _ -> unlock m type cmd = { name : string ; timed : bool ; - timeout : int ; + timeout : float ; time_start : float ; time_stop : float ; mutable time_killed : bool ; @@ -227,9 +227,9 @@ let start_command ~timeout ?time ?stdout ?stderr cmd args = Format.pp_print_string fmt cmd ; Array.iter (fun c -> Format.fprintf fmt "@ %s" c) args) ; - let timed = timeout > 0 || time <> None in + let timed = timeout > 0.0 || time <> None in let time_start = if timed then Unix.gettimeofday () else 0.0 in - let time_stop = if timeout > 0 then time_start +. float_of_int timeout else 0.0 in + let time_stop = if timeout > 0.0 then time_start +. timeout else 0.0 in let async = Command.command_async ?stdout ?stderr cmd args in { name = cmd ; @@ -251,7 +251,7 @@ let ping_command cmd coin = if coin = Kill then (kill () ; Wait 100) else let time_now = if cmd.timed then Unix.gettimeofday () else 0.0 in - if cmd.timeout > 0 && time_now > cmd.time_stop then + if cmd.timeout > 0.0 && time_now > cmd.time_stop then begin set_time cmd (time_now -. cmd.time_start) ; Kernel.debug ~dkey:Kernel.dkey_task "timeout '%s'" cmd.name ; @@ -282,7 +282,7 @@ let ping_command cmd coin = "failure '%s' [%s]" cmd.name (Printexc.to_string e) ; Return (Failed e) -let command ?(timeout=0) ?time ?stdout ?stderr cmd args = todo +let command ?(timeout=0.0) ?time ?stdout ?stderr cmd args = todo begin fun () -> let cmd = start_command ~timeout ?time ?stdout ?stderr cmd args in Monad.async (ping_command cmd) diff --git a/src/libraries/utils/task.mli b/src/libraries/utils/task.mli index 0471763487a2b4d8ee4ca22c2615709d10fea0dc..bcb501bb306fab57d64721e5bdfbd08610312bcb 100644 --- a/src/libraries/utils/task.mli +++ b/src/libraries/utils/task.mli @@ -29,7 +29,7 @@ type 'a task type 'a status = - | Timeout of int + | Timeout of float | Canceled | Result of 'a | Failed of exn @@ -134,7 +134,7 @@ val sync : mutex -> (unit -> 'a task) -> 'a task (* ************************************************************************* *) val command : - ?timeout:int -> + ?timeout:float -> ?time:float ref -> ?stdout:Buffer.t -> ?stderr:Buffer.t -> diff --git a/src/plugins/alias/.gitignore b/src/plugins/alias/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..bf8b4fea7803f726f79270ec0f26987cc09914f7 --- /dev/null +++ b/src/plugins/alias/.gitignore @@ -0,0 +1,3 @@ +/_build +tests/**/result +tests/*/oracle/dune diff --git a/src/plugins/alias/API.ml b/src/plugins/alias/API.ml new file mode 100644 index 0000000000000000000000000000000000000000..84509b9cd278681df533efcc7fe046c4ee086a6f --- /dev/null +++ b/src/plugins/alias/API.ml @@ -0,0 +1,153 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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 + +(** Points-to graphs datastructure. *) +module G = Abstract_state.G + +module LSet = Abstract_state.LSet + +module Abstract_state = Abstract_state + +let check_computed () = + if not (Analysis.is_computed ()) + then + Options.abort "Static analysis must be called before any function of the API can be called" + + +let lset + (get_set : Abstract_state.t -> LSet.t) + (kf : kernel_function) (s : stmt) = + check_computed (); + match Analysis.get_state_before_stmt kf s with + | None -> LSet.empty + | Some state -> get_set state + +let points_to_set kf s lv = lset (Abstract_state.points_to_set lv) kf s + +let new_points_to_set_stmt kf s lv = + let get_set state = + let new_state = Analysis.do_stmt state s in + Abstract_state.points_to_set lv new_state + in + lset get_set kf s + +let aliases_stmt kf s lv = + lset (Abstract_state.find_all_aliases lv) kf s + +let new_aliases_stmt kf s lv = + let get_set state = + let new_state = Analysis.do_stmt state s in + Abstract_state.find_all_aliases lv new_state + in + lset get_set kf s + +let points_to_set_kf (kf : kernel_function) (lv : lval) = + check_computed (); + if Kernel_function.has_definition kf + then + let s = Kernel_function.find_return kf in + new_points_to_set_stmt kf s lv + else + Options.abort "points_to_set_kf: function %a has no definition" Kernel_function.pretty kf + +let aliases_kf (kf : kernel_function) (lv : lval) = + check_computed (); + if Kernel_function.has_definition kf + then + let s = Kernel_function.find_return kf in + new_aliases_stmt kf s lv + else + Options.abort "aliases_kf: function %a has no definition" Kernel_function.pretty kf + +let fundec_stmts (kf : kernel_function) (lv : lval) = + check_computed (); + if Kernel_function.has_definition kf + then + List.map + (fun s -> s, new_aliases_stmt kf s lv) + (Kernel_function.get_definition kf).sallstmts + else + Options.abort "fundec_stmts: function %a has no definition" Kernel_function.pretty kf + + +let fold_points_to_set f_fold acc kf s lv = + LSet.fold (fun e a -> f_fold a e) (points_to_set kf s lv) acc + +let fold_aliases_stmt f_fold acc kf s lv = + LSet.fold (fun e a -> f_fold a e) (aliases_stmt kf s lv) acc + +let fold_new_aliases_stmt f_fold acc kf s lv = + LSet.fold (fun e a -> f_fold a e) (new_aliases_stmt kf s lv) acc + +let fold_points_to_set_kf (f_fold: 'a -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a = + LSet.fold (fun e a -> f_fold a e) (points_to_set_kf kf lv) acc + +let fold_aliases_kf (f_fold : 'a -> lval -> 'a) (acc : 'a) (kf : kernel_function) (lv : lval) : 'a = + LSet.fold (fun e a -> f_fold a e) (aliases_kf kf lv) acc + +let fold_fundec_stmts (f_fold: 'a -> stmt -> lval -> 'a) (acc: 'a) (kf:kernel_function) (lv:lval) : 'a = + List.fold_left + (fun acc (s, set) -> + LSet.fold (fun lv a -> f_fold a s lv) set acc + ) + acc + (fundec_stmts kf lv) + +let are_aliased (kf: kernel_function) (s:stmt) (lv1: lval) (lv2:lval) : bool = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> false + | Some state -> + let setv1 = Abstract_state.find_all_aliases lv1 state in + LSet.mem lv2 setv1 + +let fold_vertex (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function) (s:stmt) (lv: lval) : 'a = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> acc + | Some state -> + let v : G.V.t = Abstract_state.find_vertex lv state in + let set_aliases = Abstract_state.find_aliases lv state in + LSet.fold (fun lv a-> f_fold a v lv) set_aliases acc + +let fold_vertex_closure (f_fold : 'a -> G.V.t -> lval -> 'a) (acc: 'a) (kf: kernel_function) (s:stmt) (lv: lval) : 'a = + check_computed (); + match Analysis.get_state_before_stmt kf s with + None -> acc + | Some state -> + let list_closure : (G.V.t * LSet.t) list = Abstract_state.find_transitive_closure lv state in + List.fold_left + (fun acc (i,s) -> LSet.fold (fun lv a -> f_fold a i lv) s acc) + acc + list_closure + +let get_state_before_stmt = + Analysis.get_state_before_stmt + +let call_function a f res args = + match Analysis.get_summary f with + None -> None + | Some su -> Some(Abstract_state.call a res args su) + +let simplify_lval = Simplified.Lval.simplify diff --git a/src/plugins/alias/API.mli b/src/plugins/alias/API.mli new file mode 100644 index 0000000000000000000000000000000000000000..2ea9b4efc629d7612596bf442c96376370ba6b4b --- /dev/null +++ b/src/plugins/alias/API.mli @@ -0,0 +1,121 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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). *) +(* *) +(**************************************************************************) + +(** External API of the plugin Alias *) + +open Cil_types + +(** Points-to graphs datastructure. *) +module G: Graph.Sig.G + +(** Set of [lval]s. Differs from Cil_datatype.Lval.Set in that is uses a + different comparison function ([Cil_datatype.LvalStructEq.compare]). *) +module LSet : sig + include Set.S with type elt = lval + + val pretty: Format.formatter -> t -> unit +end + +(** NB : do the analysis BEFORE using any of those functions *) + + +(** points-to set of lval [lv] at the end of function [kf]. *) +val points_to_set_kf : kernel_function -> lval -> LSet.t + +(** aliases of lval [lv] at the end of function [kf]. *) +val aliases_kf : kernel_function -> lval -> LSet.t + +(** list of pairs [s, e] where [e] is the set of lval aliased to [v] after + statement [s] in function [kf]. *) +val fundec_stmts : kernel_function -> lval -> (stmt * LSet.t) list + + +(** [fold_points_to_set f acc kf s lv] folds [f acc] over all the lvals in the + points-to set of the given lval [lv] right before stmt [s] in function + [kf]. *) +val fold_points_to_set: + ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + +(** [fold_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of the + given lval [lv] right before stmt [s] in function [kf]. *) +val fold_aliases_stmt: + ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + +(** [fold_new_aliases_stmt f acc kf s lv] folds [f acc] over all the aliases of + the given lval [lv] created by stmt [s] in function [kf]. *) +val fold_new_aliases_stmt: + ('a -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + +(** [fold_points_to_set_kf f acc kf lv] folds [f acc] over the points-to set of lval + [lv] at the end of function [kf]. *) +val fold_points_to_set_kf : + ('a -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a + +(** [fold_aliases_kf f acc kf lv] folds [f acc] over all the aliases of lval + [lv] at the end of function [kf]. *) +val fold_aliases_kf: + ('a -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a + +(** [fold_fundec_stmts f acc kf v] folds [f acc s e] on the list of + pairs [s, e] where [e] is the set of lval aliased to [v] after statement [s] + in function [kf]. *) +val fold_fundec_stmts: + ('a -> stmt -> lval -> 'a) -> 'a -> kernel_function -> lval -> 'a + +(** [are_aliased kf s lv1 lv2] returns true if and only if the two + lvals [lv1] and [lv2] are aliased before stmt [s] in function + [kf]. *) +val are_aliased: kernel_function -> stmt -> lval -> lval -> bool + +(** [fold_vertex f acc kf s v] folds [f acc i lv] to all [lv] in [i], where [i] is + the vertex that represents the equivalence class of [v] before statement [s] in function [kf]. *) +val fold_vertex: + ('a -> G.V.t -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + +(** [fold_vertex_closure f acc kf s v] is the transitive closure of function + [fold_vertex]. *) +val fold_vertex_closure: + ('a -> G.V.t -> lval -> 'a) -> 'a -> kernel_function -> stmt -> lval -> 'a + + +(** direct access to the abstract state. See Abstract_state.mli *) + +module Abstract_state : Abstract_state.S + +(** [get_state_before_stmt f s] gets the abstract state computed after + statement [s] in function [f]. Returns [None] if + the abstract state is bottom or not computed. *) +val get_state_before_stmt : kernel_function -> stmt -> Abstract_state.t option + + +(** [call_function a f Some(res) args] computes the abstract state + after the instruction res=f(args) where res is a lval. [a] is the + abstract state before the call. If function [f] returns no value, + use [call_function a f None args] instead. Returns [None] if + the abstract state [a] is bottom or not computed. *) +val call_function: Abstract_state.t -> kernel_function -> lval option -> exp list -> Abstract_state.t option + + +(** [simplify_lval lv] returns a lval where every index of an array is + replaced by 0, evey pointer arithmetic is simplified to an access + to an array *) +val simplify_lval: lval -> lval diff --git a/src/plugins/gui/GSourceView.2.mli b/src/plugins/alias/Alias.ml similarity index 85% rename from src/plugins/gui/GSourceView.2.mli rename to src/plugins/alias/Alias.ml index a6a222088e5e324fe7fb3ea54e35e35ca34cb921..fe144bb2b96ff10ef8b8f29240892e52c4dd1390 100644 --- a/src/plugins/gui/GSourceView.2.mli +++ b/src/plugins/alias/Alias.ml @@ -20,15 +20,17 @@ (* *) (**************************************************************************) -(* compatibility between gtksourceview 2 and 3. *) -include module type of GSourceView2 -val make_marker_attributes: - source:source_view -> - category:string -> - priority: int -> - ?background: Gdk.color -> - ?pixbuf:GdkPixbuf.pixbuf -> - ?icon_name:string -> - unit -> - unit +module Analysis = Analysis + +module API = API + +let main () = + if Options.Enabled.get() then + begin + Analysis.compute (); + Options.debug "Analysis complete"; + end + +let () = + Db.Main.extend main diff --git a/src/plugins/gui/debug_manager.mli b/src/plugins/alias/Alias.mli similarity index 89% rename from src/plugins/gui/debug_manager.mli rename to src/plugins/alias/Alias.mli index 1d0f25a886ea6cee40f8a686c691359cfcb397e1..32413b01810b62d778604e2c0b9c6188b7498db3 100644 --- a/src/plugins/gui/debug_manager.mli +++ b/src/plugins/alias/Alias.mli @@ -20,10 +20,13 @@ (* *) (**************************************************************************) -(** Nothing exported. Automatic registration. *) +(** Interface for the Alias plug-in. *) -(* -Local Variables: -compile-command: "make -C ../../.." -End: -*) +module Analysis: sig + (** see file analysis.mli for documentation *) + val compute : unit -> unit + val clear : unit -> unit +end + + +module API = API diff --git a/src/plugins/alias/README.md b/src/plugins/alias/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7dc75b04fa8aa09845800030779fa2cbd8486d57 --- /dev/null +++ b/src/plugins/alias/README.md @@ -0,0 +1,78 @@ +# May-Alias Analysis plugin + +Alias is a Frama-C plugin that implements: +- a points-to analysis, i.e. an over-approximation of the possible values a + pointer may point to at run-time. +- a may-alias analysis, i.e. an over-approximation of the possible aliases + between pointer variables (and, more generally, memory regions) of the + program. + +Two pointers are called aliases of each other if they point at runtime to the +same memory location. In that case changing the value of one pointer also +changes the value of the other pointer and vice versa. + +The plugin implements a variant of « Steensgaard's algorithm ». + +## Usage + +To run the may-alias analysis either: +- call the function `Alias.Analysis.compute` +- run `frama-c` with the `-alias` flag + +Please run `frama-c -alias-h` for more information on command-line flags. + +## API + +`Alias.Analysis` provides functions to run the analysis and clear the analysis +results. +The module `Alias.API` provides function to access the analysis results. + +## Limitations + +This plugin implements a path-insensitive analysis based on purely syntactic +reasoning, with out numerical domains/values computations. When some branch +condition appears in the program, any alias in any branch is considered. +Therefore the analysis is efficient, whereas the results are not very precise. + +### Unsupported constructs +- recursive functions +- user-defined variadic functions +- function declared and used without being defined (i.e., no function body) +- function pointers +- assembly code +- instructions longjmp and setjmp +- complex instruction goto that breaks the natural control-flow of the program +- heterogeneous casts (e.g., casts from integers to pointers or conversely) +- union type +- dynamic memory allocation, except if done once at the beginning of the + program, whichever the execution path is. + +### Imprecisely-supported constructs +- non-complex instruction goto +- homogeneous casts +- recursive datatype, e.g., multiple levels of pointer dereferencing +- pointer arithmetic, and array and structure accesses +- variable-length arrays +- volatile attributes + +## Building and Installation + +The plug-in is included by default when installing Frama-C. + +To build the and install the plugin with profiling install the package +landmarks-ppx and run: +1. `dune build --instrument-with landmarks` +2. `dune install --instrument-with landmarks` +The plugin will then echo profiling information to stderr. + +Note that this plugin uses assertions extensively, which has considerable +performance cost. Building and installing using the `--release` flag disables +these assertions. + +## Project Members + +Allan Blanchard +Loïc Correnson +Tristan Le Gall +Jan Rochel +Julien Signoles diff --git a/src/plugins/alias/abstract_state.ml b/src/plugins/alias/abstract_state.ml new file mode 100644 index 0000000000000000000000000000000000000000..b1cc43122d90c913a6dcd876a1b4c21f71f1feb6 --- /dev/null +++ b/src/plugins/alias/abstract_state.ml @@ -0,0 +1,971 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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 Graph + +open Cil_types + +open Cil_datatype + +open Simplified + +module VSet = Datatype.Int.Set +module VMap = Datatype.Int.Map + +module Lval = Simplified.Lval + +module LSet = struct + include Set.Make (Lval) + + let pretty fmt s = + Format.fprintf fmt "{@["; + let is_first = ref true in + iter (fun e -> + if !is_first + then is_first := false + else Format.fprintf fmt ",@ "; + Format.fprintf fmt "%a" Lval.pretty e + ) + s; + Format.fprintf fmt "@]}" +end + +module LMap = struct + include Map.Make (Lval) + + let pretty f fmt m = + let is_first = ref true in + Format.fprintf fmt "{@[<hov 2>"; + iter (fun k v -> + if not !is_first + then Format.fprintf fmt ",@," + else is_first := false; + Format.fprintf fmt " %a -> %a" Lval.pretty k f v + ) + m; + Format.fprintf fmt " @]}" +end + +module G = Persistent.Digraph.ConcreteBidirectional(Datatype.Int) + +module V = G.V + +(* like LMap, but organized with offset and specialized functions *) +module LLMap = +struct + module OMap = Offset.Map + (* each t is a map (lhost,NoOffset) -> offset -> V.t *) + type t = (V.t OMap.t) LMap.t + + let empty : t = LMap.empty + + let mem (lv : lval) (m:t) = + let lv, off = Cil.removeOffsetLval lv in + try + OMap.mem off (LMap.find lv m) + with + Not_found -> false + + let find (lv : lval) (m:t) : V.t = + let lv, off = Cil.removeOffsetLval lv in + OMap.find off (LMap.find lv m) + + let add (lv : lval) (v:V.t) (m:t) :t = + let lv, off = Cil.removeOffsetLval lv in + let mo = try LMap.find lv m with Not_found -> OMap.empty in + LMap.add lv (OMap.add off v mo) m + + let iter f = LMap.iter @@ fun lv -> OMap.iter @@ fun o -> f @@ Cil.addOffsetLval o lv + + let map f = LMap.map @@ OMap.map f + + let pretty fmt = + let is_first = ref true in + LMap.iter (fun lv -> + OMap.iter + (fun o v -> let lv = Cil.addOffsetLval o lv in + if !is_first then is_first := false else Format.fprintf fmt "@;<3>"; + Format.fprintf fmt "@ @[%a:%d@]" Lval.pretty lv v)) + + (* left-biased *) + let union = LMap.union @@ fun _ l r -> Some (OMap.union (fun _ l _r -> Some l) l r) + + let intersect = + let intersect_omap l r = match l, r with + | Some l, Some r -> Some (l,r) + | _ -> None + in + let intersect_lmap l r = match l, r with + | Some l, Some r -> + let omap = OMap.merge (fun _ -> intersect_omap) l r in + if OMap.is_empty omap then None else Some omap + | _ -> None + in + LMap.merge @@ fun _ -> intersect_lmap + + let to_seq m = LMap.fold (fun lv omap -> OMap.fold (fun o v s -> Seq.cons (lv,o,v) s) omap) m Seq.empty + + (* specialized functions *) + let rec is_sub_offset o1 o2 = + match (o1,o2) with + NoOffset, _ -> true + | Index (e1,o1), Index (e2,o2) when Cil_datatype.ExpStructEq.equal e1 e2 -> is_sub_offset o1 o2 + | Field (f1,o1), Field (f2,o2) when Fieldinfo.equal f1 f2 -> is_sub_offset o1 o2 + | _ -> false + + (* finds all the lval lv1 apearing in [m] such as there exists an offset o1 and lv1 + o1 = lv *) + let find_upper_offsets (lv : lval) (m:t) : V.t LMap.t = + let lv, off = Cil.removeOffsetLval lv in + let mo = try LMap.find lv m with Not_found -> OMap.empty in + let f_filter o _v = is_sub_offset o off in + let mo = OMap.filter f_filter mo in + OMap.fold + (fun o -> let lv = Cil.addOffsetLval o lv in LMap.add lv) + mo + LMap.empty + +end + +module type S = +sig + (* see abstract_state.mli for coments *) + type t + val get_graph: t -> G.t + val get_lval_set : G.V.t -> t -> LSet.t + val pretty : ?debug:bool -> Format.formatter -> t -> unit + val print_dot : string -> t -> unit + val find_vertex : lval -> t -> G.V.t + val find_aliases : lval -> t -> LSet.t + val find_all_aliases : lval -> t -> LSet.t + val points_to_set : lval -> t -> LSet.t + val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list + val is_included : t -> t -> bool +end + +type t = { + graph : G.t; + lmap : LLMap.t ; (* lmap(lv) is a table [offset->v] where the vertex v corresponding to lval (lv+offset), in other words (lv+offset) is in label(v) *) + vmap : LSet.t VMap.t ;(* reverse of lmap *) +} + +let node_counter = ref 0 +let fresh_node_id () = + let id = !node_counter in + node_counter := !node_counter + 1; + id + +(* find functions *) +let find_lset (v:V.t) (x:t) : LSet.t = + try VMap.find v x.vmap + with Not_found -> LSet.empty + +let find_aliases (lv:lval) (x:t) = + let lv = Lval.simplify lv in + try + let v = LLMap.find lv x.lmap in + find_lset v x + with Not_found -> LSet.empty + +let rec get_points_to (v:V.t) (x:t) : LSet.t = + assert (G.mem_vertex x.graph v); + let set_predecessors = + List.fold_left + (fun acc v -> LSet.union acc (get_points_to v x)) + LSet.empty + (G.pred x.graph v) + in + LSet.union + (find_lset v x) + (LSet.map Lval.points_to set_predecessors) + +let aliases_of_vertex (v:V.t) (x:t) : LSet.t = + assert (G.mem_vertex x.graph v); + let list_pred = G.pred x.graph v in + List.fold_left + (fun acc v -> LSet.union acc (get_points_to v x)) + LSet.empty + list_pred + +let succ_of_lval (lv:lval) (x:t) : int option = + let lv = Lval.simplify lv in + try begin + let v = LLMap.find lv x.lmap in + match G.succ x.graph v with + | [] -> None + | [succ_v] -> Some succ_v + | _ -> Options.fatal "invariant violated (more than 1 successor)" + end with Not_found -> None + +let find_all_aliases (lv:lval) (x:t) : LSet.t = + match succ_of_lval lv x with + | None -> LSet.empty + | Some succ_v -> aliases_of_vertex succ_v x + +let points_to_set (lv:lval) (x:t) : LSet.t = + match succ_of_lval lv x with + | None -> LSet.empty + | Some succ_v -> find_lset succ_v x + +let get_graph (x:t) = x.graph + +(* renamed for the interface *) +let get_lval_set = find_lset + + +(* printing functions *) + +let print_debug fmt (x:t) = + Format.fprintf fmt "@[<v>"; + Format.fprintf fmt "@[Edges:"; + G.iter_edges (fun v1 v2 -> Format.fprintf fmt "@;<3 2>@[%d → %d@]" v1 v2) x.graph; + Format.fprintf fmt "@]@;<6>"; + Format.fprintf fmt "@[LMap:@;<3 2>"; + LLMap.pretty fmt x.lmap; + Format.fprintf fmt "@]@;<6>"; + Format.fprintf fmt "@[VMap:@;<2>"; + VMap.iter (fun v ls -> Format.fprintf fmt "@;<2 2>@[%d:%a@]" v LSet.pretty ls) x.vmap; + Format.fprintf fmt "@]"; + Format.fprintf fmt "@]" + +let print_graph fmt (x:t) = + let is_first = ref true in + let print_edge v1 v2 = + if !is_first then is_first := false else Format.fprintf fmt "@;<3>"; + let print_node v fmt lset = Format.fprintf fmt "%d:%a" v LSet.pretty lset in + Format.fprintf fmt "@[%a@] → @[%a@]" + (print_node v1) (VMap.find v1 x.vmap) + (print_node v2) (VMap.find v2 x.vmap) + in + if G.nb_edges x.graph = 0 + then Format.fprintf fmt "<empty>" + else G.iter_edges print_edge x.graph + +let print_aliases fmt (x:t) = + let is_first = ref true in + let print_alias_set _ set_lv = + if !is_first then is_first := false else Format.fprintf fmt "@;<2>"; + LSet.pretty fmt set_lv + in + let alias_set_of_vertex i _ = + let aliases = aliases_of_vertex i x in + if LSet.cardinal aliases >= 2 then Some aliases else None + in + let alias_sets = VMap.filter_map alias_set_of_vertex x.vmap in + if VMap.is_empty alias_sets + then Format.fprintf fmt "<none>" + else VMap.iter print_alias_set alias_sets + +(** invariants of type t must be true before and after each functon call *) +let assert_invariants (x:t) : unit = + (* check that all vertex of the graph have entries in vmap, + and are integer between 0 and node_counter, and have at most 1 successor *) + assert (!node_counter >= 0); + let assert_vertex (v:V.t) = + assert (v >= 0); + assert (v < !node_counter); + assert (VMap.mem v x.vmap); + assert (List.length (G.succ x.graph v) <= 1) + in + G.iter_vertex assert_vertex x.graph; + let assert_edge v1 v2 = + assert (v1 <> v2); + assert (G.mem_vertex x.graph v1); + assert (G.mem_vertex x.graph v2) + in + G.iter_edges assert_edge x.graph; + let assert_lmap (lv : lval) (v:V.t) = + assert (G.mem_vertex x.graph v); + assert (LSet.mem lv (VMap.find v x.vmap)) + in + LLMap.iter assert_lmap x.lmap; + let assert_vmap (v:V.t) (ls:LSet.t) = + assert (G.mem_vertex x.graph v); + (* TODO: we removed the invariant because of OSCS*) + (* if not (LSet.is_empty ls) + * then + * begin + * let lv = LSet.choose ls in + * let is_ptr_lv = Lval.is_pointer lv in + * assert (LSet.for_all (fun x -> Lval.is_pointer x = is_ptr_lv) ls) + * end; *) + assert (LSet.fold (fun lv acc -> acc && V.equal (LLMap.find lv x.lmap) v) ls true) + in + VMap.iter assert_vmap x.vmap + +(* Ensure that assert_invariants is not executed if the -noassert flag is supplied. *) +let assert_invariants x = assert (assert_invariants x; true) + +let pretty ?(debug = false) fmt (x:t) = + if debug then + try + assert_invariants x; + print_graph fmt x + with Assert_failure _ -> print_debug fmt x + else + print_aliases fmt x + +(** .dot printing functions*) +let find_vertex_name_ref = Extlib.mk_fun "find_vertex_name" + +module Dot = Graphviz.Dot (struct + include G + let edge_attributes _ = [] + let default_edge_attributes _ = [] + let get_subgraph _ = None + let vertex_attributes _ = [`Shape `Box] + let vertex_name (v:V.t) = + let lset = !find_vertex_name_ref v in + let fmt = Format.str_formatter in + Format.fprintf fmt "\"%a\"" LSet.pretty lset; + Format.flush_str_formatter () + let default_vertex_attributes _ = [] + let graph_attributes _ = [] + end) + +let print_dot filename (a:t) = + let file = open_out filename in + find_vertex_name_ref := + (fun v -> find_lset v a + ); + Dot.output_graph file a.graph; + close_out file + +(* find functions, part 2 *) +let rec closure_find_lset (v:V.t) (x:t) : (V.t * LSet.t) list = + match G.succ x.graph v with + [] -> [v, find_lset v x] + | [v_next] -> (v, find_lset v x)::(closure_find_lset v_next x) + | _ -> Options.fatal ("this shall not happen (invariant broken)") + +let find_transitive_closure (lv:lval) (x:t) : (G.V.t * LSet.t) list = + let lv = Lval.simplify lv in + assert_invariants x; + try closure_find_lset (LLMap.find lv x.lmap) x with Not_found -> [] +(* TODO : what about offsets ? *) + +(* NOTE on "constant vertex": a constant vertex represents an unamed + scalar value (type bottom in steensgaard's paper), or the address + of a variable. It means that in [vmap], its associated LSet is + empty. By definition, constant vertex cannot be associated to a + lval in [lmap] *) +let create_cst_vertex (x:t) : V.t * t = + let new_v = fresh_node_id () in + new_v, + { + graph = G.add_vertex x.graph new_v; + lmap = x.lmap ; + vmap = VMap.add new_v LSet.empty x.vmap + } + +(* find all the aliases of lv1 in x, for create_vertex *) +let find_all_aliases_of_offset (lv1 : lval) (x: t) : LSet.t = + let lvals_to_be_searched = decompose_lval lv1 in + (* for each lval, find the set of aliases *) + let f_map (lv,o) = + try VMap.find (LLMap.find lv x.lmap) x.vmap, o + with Not_found -> LSet.empty, o + in + Options.debug ~level:9 "decompose_lval %a : [@[<hov 2>" Lval.pretty lv1; + List.iter (fun (x, o) -> Options.debug ~level:9 " (%a,%a) " Lval.pretty x Offset.pretty o) lvals_to_be_searched; + Options.debug ~level:9 "@]]"; + let aliases = List.map f_map lvals_to_be_searched in + (* for each lval of the Lset, add the offset and add it to the resulting set *) + let f_fold_left (acc : LSet.t) (ls,o) = + LSet.fold (fun lv -> LSet.add @@ Cil.addOffsetLval o lv) ls acc + in + List.fold_left f_fold_left (LSet.singleton lv1) aliases + +(* returns the new vertex and the new graph *) +(* only for function find_or_create vertex *) +let create_vertex_simple (lv:lval) (x:t) : V.t * t = + let new_v = fresh_node_id () in + let new_g = G.add_vertex x.graph new_v in + (* find all the alias of lv (because of offset) *) + let set_of_aliases : LSet.t = find_all_aliases_of_offset lv x in + (* add all these aliases *) + Options.debug ~level:9 "all_aliases of %a : %a " Lval.pretty lv LSet.pretty set_of_aliases; + let new_lmap = + LSet.fold + (fun lv acc -> assert (not (LLMap.mem lv x.lmap)); LLMap.add lv new_v acc) + set_of_aliases + x.lmap + in + let new_vmap = VMap.add new_v set_of_aliases x.vmap in + + let new_x = + { + graph = new_g ; + lmap = new_lmap ; + vmap = new_vmap ; + } + in + assert_invariants new_x; + match lv with + | Var v, NoOffset -> + begin + match v.vtype with + TPtr _ -> + (* then add a constant vertex *) + let another_v, new_x = create_cst_vertex new_x in + let new_g = G.add_edge new_x.graph new_v another_v in + new_v, {new_x with graph = new_g} + | _ -> new_v, new_x + end + | _ -> new_v , new_x + +let diff_offset (lv1 : lval) (lv2 : lval) = + let rec f_diff_offset o1 o2 = + match o1, o2 with + NoOffset, _ -> o2 + | Field (_,o1), Field (_,o2) -> f_diff_offset o1 o2 + | Index (_,o1), Index (_,o2) -> f_diff_offset o1 o2 + | _ -> Options.fatal "%s: unexpected case" __LOC__ + in + let _, o1 = Cil.removeOffsetLval lv1 + and _, o2 = Cil.removeOffsetLval lv2 + in + assert (LLMap.is_sub_offset o1 o2); + f_diff_offset o1 o2 + +let rec create_vertex lv x = + Options.debug ~level:9 "creating a vertex for %a" Lval.pretty lv; + assert (not (LLMap.mem lv x.lmap)); + begin + match lv with + (Mem e, NoOffset) -> + (* special case, when we also add another vertex and a points-to edge*) + begin + (* first find the vertex corresponding to e *) + match LvalOrRef.from_exp e with + | None -> Options.fatal "unexpected result: Lval.from (%a) = None" Exp.pretty e + | Some (LvalOrRef.Ref _) -> Options.fatal "unexpected: *(&x)" + | Some (LvalOrRef.Lval lv1) -> + (* find the vertex *) + let v1, x = find_or_create_vertex (LvalOrRef.Lval lv1) x in + (* then creates a vertex for bvl ONLY IF there is no successor *) + begin + match G.succ x.graph v1 with + [] -> + let v2, x = create_vertex_simple lv x in + (* finally add a points-to edge between v1 and v2 *) + let new_graph = G.add_edge x.graph v1 v2 in + v2, {x with graph = new_graph } + | [succ_v1] -> + (* if there is a successor, update lmap and vmap to add blv to that successor's set *) + let new_lmap = LLMap.add lv succ_v1 x.lmap in + let new_vmap = VMap.add succ_v1 (LSet.add lv (VMap.find succ_v1 x.vmap)) x.vmap in + succ_v1, {x with lmap = new_lmap ; vmap = new_vmap } + | _ -> Options.fatal " Invariant violated : more than 1 successor" + end + end + | _ -> create_vertex_simple lv x + end + +and find_or_create_lval_vertex (lv:lval) (x:t) : V.t * t = + try LLMap.find lv x.lmap, x + with Not_found -> + (* try to find if an alias already exists in x *) + let map_predecessors : V.t LMap.t = + LLMap.find_upper_offsets lv x.lmap + in + (* for any predecessor, find all its aliases and then look for potential existing vertex *) + let f_fold_lmap lvx vx acc = + let set_aliases = VMap.find vx x.vmap in + Options.debug ~level:9 "looking for aliases of %a in set %a" Lval.pretty lv LSet.pretty set_aliases; + if LSet.cardinal set_aliases <= 1 then acc else + let off = diff_offset lvx lv in + let f_fold_lset lvs acc = + try + let lvs = Cil.addOffsetLval off lvs in + VSet.add (LLMap.find lvs x.lmap) acc + with + Not_found -> acc + in + LSet.fold f_fold_lset set_aliases acc + in + (* set of all existing aliases *) + let vset_res = LMap.fold f_fold_lmap map_predecessors VSet.empty in + Options.debug ~level:9 "found aliases of %a : %a" Lval.pretty lv VSet.pretty vset_res; + if VSet.is_empty vset_res + then create_vertex lv x + else + let () = assert (VSet.cardinal vset_res = 1) in + let v_res = VSet.choose vset_res in + (* vertex found, update the tables *) + let new_lmap = LLMap.add lv v_res x.lmap in + let new_vmap = VMap.add v_res (LSet.add lv (VMap.find v_res x.vmap)) x.vmap in + v_res, {x with lmap = new_lmap; vmap = new_vmap} + +(* find the vertex of an lval *) +and find_or_create_vertex (lv : LvalOrRef.t) (x:t) : V.t * t = + match lv with + | LvalOrRef.Lval lv -> find_or_create_lval_vertex lv x + | LvalOrRef.Ref lv -> + Options.debug ~level:9 "creating a vertex for %a" LvalOrRef.pretty (LvalOrRef.Ref lv); + let v1, x = find_or_create_lval_vertex lv x in + let va, x = create_cst_vertex x in + va, {x with graph = G.add_edge x.graph va v1} + +(* TODO is there a better way to do it ? *) +let find_vertex lv x = + let lv = Lval.simplify lv in + let v,x1 = find_or_create_lval_vertex lv x in + if x == x1 + (* if x has not been modified, then the vertex was found, not created *) + then v + else raise Not_found + +(* merge of two vertices; the first vertex carries both sets, the second is removed from the graph and from lmap and vmap *) +let merge x v1 v2 = + if (V.equal v1 v2) || not (G.mem_vertex x.graph v1) || not (G.mem_vertex x.graph v2) + then x + else + let set1 = find_lset v1 x in + let set2 = find_lset v2 x in + + let new_set = LSet.union set1 set2 in + (* update lmap : every lval in v2 must now be associated with v1*) + let new_lmap = LSet.fold (fun lv2 m -> LLMap.add lv2 v1 m) set2 x.lmap in + + (* update vmap *) + let new_vmap = VMap.add v1 new_set (VMap.remove v2 x.vmap) in + (* update the graph *) + let f_fold_succ v_succ (g:G.t) : G.t = + G.add_edge g v1 v_succ + and f_fold_pred v_pred (g:G.t) : G.t = + G.add_edge g v_pred v1 + in + let g = x.graph in + (* adds all new edges *) + let g = G.fold_succ f_fold_succ g v2 g in + let g = G.fold_pred f_fold_pred g v2 g in + (* remove v2 *) + let g = G.remove_vertex g v2 in + {graph = g; lmap = new_lmap; vmap = new_vmap} + +(* functions join and unify-pointer of steensgaard's paper *) +let rec join_without_check (x:t) (v1:V.t) (v2:V.t) : t = + if (V.equal v1 v2) || not (G.mem_vertex x.graph v1 && G.mem_vertex x.graph v2) + then + x + else + let pt1 = G.succ x.graph v1 in (* TODO ask frama-c type instead of looking in the graph *) + let pt2 = G.succ x.graph v2 in + let x = merge x v1 v2 in + assert (not (G.mem_vertex x.graph v2)); + match (pt1, pt2) with + | [], _ -> x + | _, [] -> x + | [succ_v1],[succ_v2] -> + assert (succ_v1 <> v2); + assert (succ_v2 <> v1); + join_without_check x succ_v1 succ_v2 + | _, _ -> + Options.fatal "invariant broken" + +(* since the recursive version of join, unify, unify2 and merge may break the invariants *) +let join (x:t) (v1:V.t) (v2:V.t) : t = + Options.debug ~level:7 "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x; + assert_invariants x; + let res = join_without_check x v1 v2 in + Options.debug ~level:7 "graph after join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug res; + begin + try assert_invariants res + with Assert_failure _ -> + Options.debug "join(%d,%d) failed" v1 v2; + Options.debug "graph before join(%d,%d):@;<2>@[%a@]" v1 v2 print_debug x; + Options.debug "graph after join(%d,%d):@;<2>@[ %a@]" v1 v2 print_debug res; + assert_invariants res + end; + res + +let merge_set (x:t) (vs:VSet.t) : V.t * t = + let v0 = VSet.choose vs in + if VSet.cardinal vs < 2 then v0, x else begin + Options.debug ~level:7 "graph before merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug x; + assert (G.mem_vertex x.graph v0); + let result = VSet.fold (fun v acc -> merge acc v0 v) vs x in + Options.debug ~level:7 "graph after merge_set %a:@;<2>@[%a@]" VSet.pretty vs print_debug result; + v0, result + end + +let rec join_succs (x:t) v = + Options.debug ~level:8 "joining successors of %d" v; + if not @@ G.mem_vertex x.graph v then x else + match G.succ x.graph v with + | [] | [_] -> x + | succs -> + let v0, x = merge_set x @@ VSet.of_list succs in + join_succs x v0 + +(* in Steensgard's paper, this is written settype(v1,ref(v2,bot)) *) +let set_type (x:t) (v1:V.t) (v2:V.t) : t = + assert_invariants x; + (* if v1 points to another node, suppress current outgoing edge (and the node if it is a constant node) *) + let g, new_vmap = + match G.succ x.graph v1 with + [] -> x.graph, x.vmap + | [v2] -> + (* if v2 is a constant node supress it directly *) + if LSet.is_empty (VMap.find v2 x.vmap) + then (G.remove_vertex x.graph v2, VMap.remove v2 x.vmap) + else (G.remove_edge x.graph v1 v2, x.vmap) + | _ -> Options.fatal "too many outgoing edges in set_type" + in + let new_g = G.add_edge g v1 v2 in + let new_x = {x with graph = new_g ; vmap = new_vmap} in + assert_invariants new_x ; new_x + +let assignment (a:t) (lv:lval) (e:exp) : t = + assert_invariants a; + if not @@ Cil.isPointerType (Cil.typeOf e) then a else + let x = Lval.simplify lv in + match LvalOrRef.from_exp e with + | None -> a + | Some y -> + let (v1,a) = find_or_create_lval_vertex x a in + let (v2,a) = find_or_create_vertex y a in + if List.mem v2 (G.succ a.graph v1) || List.mem v1 (G.succ a.graph v2) + then + let () = + Options.warning ~source:(fst e.eloc) + "ignoring assignment of the form: %a = %a" + Printer.pp_lval lv Printer.pp_exp e; + in a + else + let a = join a v1 v2 in + let () = assert_invariants a in + a + +(* assignment x = allocate(y) *) +let assignment_x_allocate_y (a:t) (lv:lval) : t = + assert_invariants a; + let x = Lval.simplify lv in + let (v1,a) = find_or_create_lval_vertex x a in + match G.succ a.graph v1 with + | [] -> + let (v2,a) = create_cst_vertex a in + let new_a : t = set_type a v1 v2 in + let () = assert_invariants new_a in new_a + | [_v2] -> a + | _ -> Options.fatal "this should not hapen (invariant broken)" + +let is_included (a1:t) (a2:t) = + (* tests if a1 is included in a2, at least as the nodes with lval *) + assert_invariants a1; + assert_invariants a2; + Options.debug ~level:8 "testing equal %a AND à .%a" (pretty ~debug:true) a1 (pretty ~debug:true) a2; + let exception Not_included in + try + let iter_lmap (lv : lval) (v1:V.t): unit = + let v2 : V.t = try LLMap.find lv a2.lmap with Not_found -> raise Not_included in + match G.succ a1.graph v1, G.succ a2.graph v2 with + [], _ -> () + | [_], [] -> raise Not_included + | [v1p], [v2p] -> + if LSet.subset (VMap.find v1p a1.vmap) (VMap.find v2p a2.vmap) + then + () + else + raise Not_included + | _ -> Options.fatal "this should not hapen (invariant broken)" + in + LLMap.iter iter_lmap a1.lmap; true + with + Not_included -> false + +let empty :t = + {graph = G.empty; lmap = LLMap.empty; vmap = VMap.empty} + +let is_empty s = + compare s empty = 0 + +(* add an int to all vertex values *) +let shift (a : t) : t = + assert_invariants a; + if is_empty a then a else + let () = Options.debug ~level:8 "before shift: node_counter=%d@.%a" !node_counter print_debug a in + let max_idx = G.fold_vertex max a.graph 0 in + let min_idx = G.fold_vertex min a.graph max_idx in + let offset = !node_counter - min_idx in + let shift x = x + offset in + let shift_vmap shift_elem vmap = + VMap.of_seq @@ Stdlib.Seq.map shift_elem @@ VMap.to_seq vmap + in + let {graph; lmap; vmap} = a in + node_counter := max_idx + offset + 1; + let result = + {graph = G.map_vertex shift graph; + lmap = LLMap.map shift lmap; + vmap = shift_vmap (fun (key, l) -> (shift key, l)) vmap} + in + let () = Options.debug ~level:8 "after shift: node_counter=%d@.%a" !node_counter print_debug result in + assert_invariants result; + result + +let union_find vmap intersections = + let module Store : UnionFind.STORE = UnionFind.StoreMap.Make (VMap) in + let module UF = UnionFind.Make (Store) in + let uf = UF.new_store () in + let refs = VMap.mapi (fun i _ -> UF.make uf i) vmap in + let put_into_uf (v1,v2) = + let r1 = VMap.find v1 refs in + let r2 = VMap.find v2 refs in + ignore @@ UF.union uf r1 r2 + in + let _vs = Seq.iter put_into_uf intersections in + let sets_to_be_joined = + let add_to_map i r sets = + let repr = UF.find uf r in + let add_to_set = function + | None -> Some (VSet.singleton i) + | Some set -> Some (VSet.add i set) + in + VMap.update (UF.get uf repr) add_to_set sets + in + VMap.fold add_to_map refs VMap.empty in + sets_to_be_joined + +let union (a1:t) (a2:t) :t = + (* naive algorithm : + 1 merge the graph and the vmap (by doing union of sets) + 2 for any node present in both a1.graph and a2.graph, merge/join them + 3 for any lval [lv] that are has an entry in both a1.lmap and a2.lmap, merge the two vertex a1.lmap[lv] + and a2.lmap[lv] + + I am not confident about this function, there are too many potential bugs and inefficiencies + *) + assert_invariants a1; + assert_invariants a2; + + Options.debug ~level:4 "Union: First graph:%a" print_graph a1; + Options.debug ~level:5 "Union: First graph:%a" print_debug a1; + Options.debug ~level:4 "Union: Second graph:%a" print_graph a2; + Options.debug ~level:5 "Union: Second graph:%a" print_debug a2; + let new_graph = + G.fold_vertex + (fun v2 g -> G.add_vertex g v2) + a2.graph + a1.graph + in + let new_graph = + G.fold_edges + (fun v2a v2b g -> G.add_edge g v2a v2b) + a2.graph + new_graph + in + let new_vmap = + VMap.union (fun _ lset1 lset2 -> Option.some @@ LSet.union lset1 lset2) + a2.vmap + a1.vmap + in + let sets_to_be_joined = + let intersections = LLMap.to_seq @@ LLMap.intersect a1.lmap a2.lmap in + union_find new_vmap @@ Seq.map (fun (_,_,x) -> x) intersections + in + let new_lmap = LLMap.union a1.lmap a2.lmap in + Options.debug ~level:7 "Union: sets to be joined:@["; + VMap.iter (fun _ set -> Options.debug ~level:7 "%a" VSet.pretty set) sets_to_be_joined; + Options.debug ~level:7 "@]"; + let new_a = {graph = new_graph; lmap = new_lmap; vmap = new_vmap} in + let merged_nodes, new_a = + VMap.fold + (fun _ set (merged_nodes, x) -> let v0, x = merge_set x set in (v0 :: merged_nodes), x) + sets_to_be_joined + ([], new_a) + in + let new_a = List.fold_left join_succs new_a merged_nodes in + Options.debug ~level:4 "Union: Result graph:%a" print_graph new_a; + Options.debug ~level:5 "Union: Result graph:%a" print_debug new_a; + begin + try assert_invariants new_a + with Assert_failure _ -> + Options.debug "union failed"; + Options.debug "Union: First graph:%a" print_graph a1; + Options.debug "Union: First graph:%a" print_debug a1; + Options.debug "Union: Second graph:%a" print_graph a2; + Options.debug "Union: Second graph:%a" print_debug a2; + Options.debug "Union: Result graph:%a" print_graph new_a; + Options.debug "Union: Result graph:%a" print_debug new_a; + assert_invariants new_a + end; + new_a + +(** a type for summaries of functions *) +type summary = + { + state : t option; + formals: lval list; + locals: lval list; + return : exp option + } + +let make_summary (s : t) (kf : kernel_function) = + let exp_return : exp option = + if Kernel_function.has_definition kf then + let return_stmt = Kernel_function.find_return kf in + match return_stmt.skind with + Return (e, _) -> e + | _ -> Options.fatal "this should not happen" + else + None + in + let s = + match exp_return with + None -> s + | Some e -> + begin + match s, LvalOrRef.from_exp e with + _, None -> s + | s, Some lv -> + let _, new_s = find_or_create_vertex lv s in + new_s + end + in + { + state = Some s; + formals = List.map (fun v -> (Var v,NoOffset)) (Kernel_function.get_formals kf); + locals = List.map (fun v -> (Var v,NoOffset)) (Kernel_function.get_locals kf); + return = exp_return + } + +let pretty_summary ?(debug=false) fmt s = + let print_list_lval ~state fmt (l: lval list) = + let is_first = ref true in + let print_elem x = + if !is_first then is_first := false else Format.fprintf fmt "@ "; + Format.fprintf fmt "@[%a" Cil_datatype.Lval.pretty x; + let pointees = points_to_set x state in + if not @@ LSet.is_empty pointees then + Format.fprintf fmt "→%a" LSet.pretty pointees; + Format.fprintf fmt "@]"; + in + List.iter print_elem l + in + let print_option pp fmt x = + match x with + | Some x -> pp fmt x + | None -> Format.fprintf fmt "<none>" + in + match s.state with + | None -> if debug then Format.fprintf fmt "not found" + | Some s when is_empty s -> if debug then Format.fprintf fmt "empty" + | Some state -> + begin + Format.fprintf fmt "@[formals: @[%a@]@;<4>locals: @[%a@]@;<4>returns: @[%a@]@;<4>state: @[%a@] " + (print_list_lval ~state) s.formals + (print_list_lval ~state) s.locals + (print_option Exp.pretty) s.return + (print_option @@ pretty ~debug) s.state; + end + +(* the algorithm: + - unify the two graphs dropping all the variables from the summary + - pair arguments with formals assigning the formal's successor as the argument's successor +*) +let call (state:t) (res:lval option) (args:exp list) (summary:summary) :t = + assert_invariants state; + let formals = summary.formals in + assert (List.length args = List.length formals); + let sum_state = shift @@ Option.get summary.state in + + (* pair up formals and their corresponding arguments, + as well as the bound result with the returned value *) + let arg_formal_pairs = + let res_ret = match res, summary.return with + | None, None -> [] + | Some res, Some ret -> + let simplify_ret x = match LvalOrRef.from_exp x with + | Some (LvalOrRef.Lval lval) -> lval + | _ -> Options.fatal "unexpected form of return statement" + in + [LvalOrRef.Lval (Lval.simplify res), simplify_ret ret] + | None, Some _ -> [] + | Some _, None -> (* Shouldn't happen: Frama-C adds missing returns *) + Options.fatal "unexpected case: result without return" + in + let simplify_both (arg, formal) = + try + match LvalOrRef.from_exp arg with + | None -> None + | Some lv -> Some (lv, Lval.simplify formal) + with Explicit_pointer_address loc -> + Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address + "unsupported feature: explicit pointer address: %a; analysis may be unsound" + Printer.pp_exp arg; + None + in + res_ret @ List.filter_map simplify_both @@ List.combine args formals + in + + (* for each pair (lv1,lv2) find (or create) the corresponding vertices *) + let state, vertex_pairs = + let state = ref state in + let find_vertex (lv1, lv2) = + try + let v2 = LLMap.find lv2 sum_state.lmap in + let v1, new_state = find_or_create_vertex lv1 !state in + state := new_state; + Some (v1, v2) + with Not_found -> None + in + !state, List.filter_map find_vertex arg_formal_pairs + in + + (* merge the function graph; + for every arg/formal vertex pair (v1,v2) and every edge v2→v create edge v1→v. *) + let g = + let transfer_succs (g : G.t) (v1,v2) = + let v2_succs = G.succ sum_state.graph v2 in + assert (List.length v2_succs < 2); + List.fold_left (fun g succ -> G.add_edge g v1 succ) g v2_succs + in + let g = state.graph in + let g = G.fold_vertex (fun i g -> G.add_vertex g i) sum_state.graph g in + let g = G.fold_edges (fun i j g -> G.add_edge g i j) sum_state.graph g in + List.fold_left transfer_succs g vertex_pairs + in + + (* garbage collect: remove leaf vertices from g that originate from sum_state *) + let vertices_to_add_to_g, g = + let g = ref g in + let remove_if_leaf v _ = + if G.in_degree sum_state.graph v = 0 + then let () = g := G.remove_vertex !g v in None + else Some LSet.empty + in + let remaining_vertices = VMap.filter_map remove_if_leaf sum_state.vmap in + remaining_vertices, !g + in + + let state = { + graph = g; + lmap = state.lmap; + vmap = + let left_bias _ l _ = Some l in + VMap.union left_bias state.vmap vertices_to_add_to_g} + in + + let state = List.fold_left join_succs state (List.map fst vertex_pairs) in + + assert_invariants state; + state diff --git a/src/plugins/alias/abstract_state.mli b/src/plugins/alias/abstract_state.mli new file mode 100644 index 0000000000000000000000000000000000000000..8506611bc0f61251f5ee4b60f44506145c9fff96 --- /dev/null +++ b/src/plugins/alias/abstract_state.mli @@ -0,0 +1,141 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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). *) +(* *) +(**************************************************************************) + +(** Module abstract_state *) + +open Cil_types + +(** Points-to graphs datastructure. *) +module G: Graph.Sig.G + +(** Set of [lval]s. Differs from Cil_datatype.Lval.Set in that is uses a + different comparison function ([Cil_datatype.LvalStructEq.compare]). *) +module LSet : sig + include Set.S with type elt = lval + + val pretty: Format.formatter -> t -> unit +end + +(** map of [lval]s. Differs from Cil_datatype.Lval.Met in that is uses a + different comparison function ([Cil_datatype.LvalStructEq.compare]). *) +module LMap : sig + include Map.S with type key = lval + + val pretty: (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a t -> unit +end + +(** external signature *) +module type S = +sig + + (** Type denothing an abstract state of the analysis. It is a graph containing + all aliases and points-to information. *) + type t + + (** access to the points-to graph *) + val get_graph: t -> G.t + + (** set of lvals stored in a vertex *) + val get_lval_set : G.V.t -> t -> LSet.t + + (** pretty printer; debug=true prints the graph, debug = false only + prints aliased variables *) + val pretty : ?debug:bool -> Format.formatter -> t -> unit + + (** dot printer; first argument is a file name *) + val print_dot : string -> t -> unit + + (** finds the vertex corresponding to a lval. May raise @Not_found + *) + val find_vertex : lval -> t -> G.V.t + + (** same as previous function, but return a set of lval. Cannot + raise an exception but may return an empty set if the lval is not + in the graph *) + val find_aliases : lval -> t -> LSet.t + + (** similar to the previous functions, but does not only give the + equivalence class of lv, but also all lv that are aliases in + other vertex of the graph *) + val find_all_aliases : lval -> t -> LSet.t + + (** the set of all lvars to which the given variable may point. *) + val points_to_set : lval -> t -> LSet.t + + (** find_aliases, then recursively finds other sets of lvals. We + have the property (if lval [lv] is in abstract state [x]) : + List.hd (find_transitive_closure lv x) = (find_vertex lv x, + find_aliases lv x) *) + val find_transitive_closure : lval -> t -> (G.V.t * LSet.t) list + + (** inclusion test; [is_included a1 a2] tests if, for any lvl + present in a1 (associated to a vertex v1), that it is also + present in a2 (associated to a vertex v2) and that + get_lval_set(succ(v1) is included in get_lval_set(succ(v2)) *) + val is_included : t -> t -> bool + +end + + +include S + +(** check all the invariants that must be true on an abstract value + before and after each function call or transformation of the graph) *) +val assert_invariants : t -> unit + +(** Functions for Steensgaard's algorithm, see the paper *) +val join : t -> G.V.t -> G.V.t -> t + +(** transfert functions for different kinds of assignments *) +val assignment : t -> lval -> exp -> t + +(** transfert function for malloc calls *) +val assignment_x_allocate_y : t -> lval -> t + + +(** inclusion test; [is_included a1 a2] tests if, for any lvl present + in a1 (associated to a vertex v1), that it is also present in a2 + (associated to a vertex v2) and that set(succ(v1) is included in + set(succ(v2)) *) +val is_included : t -> t -> bool + +(** union of two abstract values ; ensures that if 2 lval are + aliased in one of the two input graph (or in a points-to + relationship), then they will also be aliased/points-to in the + result *) +val union : t -> t -> t + +(** empty graph *) +val empty : t + +(** Type denoting summaries of functions *) +type summary + +(** creates a summary from a state and a function *) +val make_summary : t -> kernel_function -> summary + +(** pretty printer *) +val pretty_summary : ?debug:bool -> Format.formatter -> summary -> unit + +(** [call a res args s] computes the abstract state after the + instruction res=f(args), with f summarized by [s]. [a] is the abstract state before the call *) +val call: t -> lval option -> exp list -> summary -> t diff --git a/src/plugins/alias/analysis.ml b/src/plugins/alias/analysis.ml new file mode 100644 index 0000000000000000000000000000000000000000..148dabcd63c02521a4a2059b661b4b21af6b5c60 --- /dev/null +++ b/src/plugins/alias/analysis.ml @@ -0,0 +1,330 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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 Cil_datatype + +module Dataflow = Dataflow2 + +module type Table = sig + type key + type value + val find: key -> value + (** @raise Not_found if the key is not in the table. *) +end + +module type InternalTable = sig + include Table + val add : key -> value -> unit + val iter : (key -> value -> unit) -> unit +end + +module Make_table (H: Hashtbl.S) (V: sig type t val size : int end) + : InternalTable with type key = H.key and type value = V.t = struct + type key = H.key + type value = V.t + let tbl = H.create V.size + let add = H.replace tbl + let find = H.find tbl + let iter f = H.iter f tbl +end + +(* In Function_table, value None means the function has no definition *) +module Function_table = Make_table (Kernel_function.Hashtbl) (struct + type t = Abstract_state.summary option + let size = 7 + end) + +let function_compute_ref = Extlib.mk_fun "function_compute" + +(* In Stmt_table, value None means abstract state = Bottom *) +module Stmt_table = struct + include Dataflow.StartData (struct + type t = Abstract_state.t option + let size = 7 + end) + type key = stmt + type value = data +end + +let warn_unsupported_explicit_pointer pp_obj obj loc = + Options.warning ~source:(fst loc) ~wkey:Options.Warn.unsupported_address + "unsupported feature: explicit pointer address: %a; analysis may be unsound" pp_obj obj + +let do_assignment (lv:lval) (exp:exp) (a:Abstract_state.t) : Abstract_state.t = + try Abstract_state.assignment a lv exp + with Simplified.Explicit_pointer_address loc -> + warn_unsupported_explicit_pointer Printer.pp_exp exp loc; + a + +let rec do_init (lv:lval) (init:init) state = + match init with + | SingleInit e -> Option.map (do_assignment lv e) state + | CompoundInit (_, l) -> + List.fold_left (fun state (o, init) -> do_init (Cil.addOffsetLval o lv) init state) state l + +let doFunction f = !function_compute_ref f + +let do_function_call (stmt:stmt) state (res : lval option) (ef : exp) (args: exp list) loc = + let is_malloc (s:string) : bool = + (s = "malloc") || (s = "calloc") (* todo : add all function names *) + in + match ef with + | {enode=Lval (Var v, _);_} when is_malloc v.vname -> + begin + (* special case for malloc *) + match (state,res) with + (None, _) -> None + | (Some a, None) -> (Options.warning "Memory allocation not stored (ignored)"; Some a) + | (Some a, Some lv) -> + try Some (Abstract_state.assignment_x_allocate_y a lv) + with Simplified.Explicit_pointer_address loc -> + warn_unsupported_explicit_pointer Printer.pp_stmt stmt loc; + Some a + end + | _ -> + begin + (* general case *) + let summary = + match Kernel_function.get_called ef with + | Some kf when Kernel_function.is_main kf -> None + | Some kf -> begin + try Function_table.find kf + with Not_found -> doFunction kf + end + | None -> + Options.warning ~wkey:Options.Warn.unsupported_function ~source:(fst loc) + "unsupported feature: call to function pointer: %a" Exp.pretty ef; + None + in + match (state, summary) with + (None, _) -> None + | (Some a, Some summary) -> + Some (Abstract_state.call a res args summary) + | (Some a, None) -> + Options.warning ~wkey:Options.Warn.undefined_function ~once:true ~source:(fst loc) + "function %a has no definition" Exp.pretty ef; + Some a + end + +let do_cons_init (s:stmt) (v:varinfo) f arg t loc state = + Cil.treat_constructor_as_func (do_function_call s state) v f arg t loc + +let analyse_instr (s:stmt) (i:instr) (a:Abstract_state.t option) : Abstract_state.t option = + match i with + Set (lv,exp,_) -> Option.map (do_assignment lv exp) a + | Local_init (v,AssignInit i,_) -> do_init (Var v, NoOffset) i a + | Local_init (v,ConsInit (f,arg,t),loc) -> do_cons_init s v f arg t loc a + | Code_annot _ -> a + | Skip _ -> a + | Call (res,ef,es,loc) -> (* !function_compute_ref ef *) + do_function_call s a res ef es loc + | Asm (_,_,_,loc) -> + Options.warning + ~source:(fst loc) ~wkey:Options.Warn.unsupported_asm + "unsupported feature: assembler code; skipping"; + a + +let pp_abstract_state_opt ?(debug=false) fmt v = + match v with + | None -> Format.fprintf fmt "⊥" + | Some a -> Abstract_state.pretty ~debug fmt a + +let do_instr (s:stmt) (i:instr) (a:Abstract_state.t option) : Abstract_state.t option = + Options.feedback ~level:3 "@[analysing instruction:@ %a@]" Printer.pp_stmt s; + let result = analyse_instr s i a in + Options.feedback ~level:3 "@[May-aliases after instruction@;<2>@[%a@]@;<2>are@;<2>@[%a@]@]" + Printer.pp_stmt s (pp_abstract_state_opt ~debug:false) result; + Options.debug ~level:3 "@[May-alias graph after instruction@;<2>@[%a@]@;<2>is@;<4>@[%a@]@]" + Printer.pp_stmt s (pp_abstract_state_opt ~debug:true) result; + result + +module T = struct + let name = "alias" + + let debug = true (* TODO see options *) + + type t = Abstract_state.t option + + module StmtStartData = Stmt_table + + let copy x = x (* we only have persistant data *) + + let pretty fmt a = + match a with + None -> Format.fprintf fmt "<No abstract state>" + | Some a -> Abstract_state.pretty fmt a + + let computeFirstPredecessor _ a = a + + let combinePredecessors _stmt ~old state = + match old, state with + | _, None -> assert false + | None, Some _ -> Some state (* [old] already included in [state] *) + | Some old, Some new_ -> + if Abstract_state.is_included new_ old then + None + else + Some (Some (Abstract_state.union old new_)) + + let doInstr = do_instr + + let doGuard _ _ a = + Dataflow.GUse a, Dataflow.GUse a + + let doStmt _ _ = Dataflow.SDefault + + let doEdge _ _ a = a +end + +module F = Dataflow.Forwards (T) + +let do_stmt (a: Abstract_state.t) (s:stmt) : Abstract_state.t = + match s.skind with + Instr i -> + begin + match do_instr s i (Some a) with + None -> Options.fatal "problem here" + | Some a -> a + end + | _ -> a + +let analyse_function (kf:kernel_function) = + Options.feedback ~level:2 "analysing function: %a" Kernel_function.pretty kf; + if Kernel_function.has_definition kf then + begin + let first_stmt = + try Kernel_function.find_first_stmt kf + with Kernel_function.No_Statement -> assert false + in + T.StmtStartData.add first_stmt (Some Abstract_state.empty); + F.compute [first_stmt]; + let return_stmt = Kernel_function.find_return kf in + try Stmt_table.find return_stmt + with Not_found -> + begin + let source, _ = Kernel_function.get_location kf in + Options.warning ~source ~wkey:Options.Warn.no_return_stmt + "function %a does not return; analysis may be unsound" + Kernel_function.pretty kf; + Some Abstract_state.empty + end + end + else + None + +let doFunction (kf:kernel_function) = + let final_state = analyse_function kf in + let level = if Kernel_function.is_main kf then 1 else 2 in + Options.feedback ~level "@[May-aliases at the end of function %a:@ @[%a@]" + Kernel_function.pretty kf + (pp_abstract_state_opt ~debug:false) final_state; + Options.debug ~level "May-alias graph at the end of function %a:@;<4>@[%a@]" + Kernel_function.pretty kf + (pp_abstract_state_opt ~debug:true) final_state; + let result = + match final_state with + (* final state is None if kf has no definition *) + None -> None + | Some fs -> + let summary = Abstract_state.make_summary fs kf in + Options.debug ~level:2 "Summary of function %a:@ @[%a@]" + Kernel_function.pretty kf + (Abstract_state.pretty_summary ~debug:false) summary; + Some summary + in + if Kernel_function.is_main kf then begin + match Options.Dot_output.get (), final_state with + | "", _ -> () + | _, None -> () + | fname, Some final_state -> Abstract_state.print_dot fname final_state + end; + Function_table.add kf result; + result + +let () = function_compute_ref := doFunction + +let make_summary (state:Abstract_state.t) (kf:kernel_function) = + try + begin + match Function_table.find kf with + Some s -> (state, s) + | None -> Options.fatal "not implemented" + end + with + Not_found -> + begin + match doFunction kf with + Some s -> (state, s) + | None -> Options.fatal "not implemented" + end + +let computed_flag = ref false + +let is_computed () = !computed_flag + +let print_stmt_table_elt fmt k v :unit = + let print_key = Stmt.pretty in + let print_value fmt v = + match v with + | None -> Format.fprintf fmt "<Bot>" + | Some a -> Abstract_state.pretty ~debug:(Options.DebugTable.get ()) fmt a + in + Format.fprintf fmt "Before statement %a :@[<hov 2> %a@]" print_key k print_value v + +let print_function_table_elt fmt kf s : unit = + let function_name = Kernel_function.get_name kf in + match s with + | None -> Options.debug "function %s -> None" function_name + | Some s -> + Format.fprintf fmt "Summary of function %s:@;<5 2>@[%a@]@." + function_name + (Abstract_state.pretty_summary ~debug:(Options.DebugTable.get ())) s + +let compute () = + Ast.compute (); + Globals.Functions.iter (fun kf -> ignore @@ doFunction kf); + computed_flag := true; + if Options.ShowStmtTable.get () then + Stmt_table.iter (print_stmt_table_elt Format.std_formatter); + if Options.ShowFunctionTable.get () then + Function_table.iter (print_function_table_elt Format.std_formatter) + +let clear () = + computed_flag := false; + Stmt_table.clear () + +let get_state_before_stmt _kf stmt = + if is_computed () + then + try Stmt_table.find stmt with + Not_found -> None + else + None + +let get_summary kf = + if is_computed () + then + try Function_table.find kf with + Not_found -> None + else + None diff --git a/src/plugins/gui/dgraph_helper.yes.ml b/src/plugins/alias/analysis.mli similarity index 53% rename from src/plugins/gui/dgraph_helper.yes.ml rename to src/plugins/alias/analysis.mli index 7c506cd2a01e459a98743c651c3ad265a6d209bd..f1bb2652e88fdb27f7c590589b3dcfb6a252438b 100644 --- a/src/plugins/gui/dgraph_helper.yes.ml +++ b/src/plugins/alias/analysis.mli @@ -20,41 +20,49 @@ (* *) (**************************************************************************) -open DGRAPH_MODULE - -let graph_window ~parent ~title make_view = - let height = int_of_float (float parent#default_height *. 3. /. 4.) in - let width = int_of_float (float parent#default_width *. 3. /. 4.) in - let graph_window = - GWindow.window - ~width ~height ~title ~resizable:true ~position:`CENTER () - in - let view = make_view ~packing:graph_window#add () in - graph_window#show(); - view#adapt_zoom(); - () -;; - -let graph_window_through_dot ~parent ~title dot_formatter = - let make_view ~packing () = - let temp_file = - try - Extlib.temp_file_cleanup_at_exit - "framac_property_status_navigator_graph" "dot" - with Extlib.Temp_file_error s -> - Gui_parameters.abort "cannot create temporary file: %s" s in - let fmt = Format.formatter_of_out_channel (open_out temp_file) in - dot_formatter fmt; - Format.pp_print_flush fmt (); - let view = - snd - (DGraphContainer.Dot.from_dot_with_commands ~packing temp_file) - in - view - in - try - graph_window ~parent ~title make_view - with DGRAPH_ERROR _ as exn -> - Gui_parameters.error - "@[cannot display dot graph:@ %s@]" - (Printexc.to_string exn) +open Cil_types + +open Abstract_state + +module type Table = sig + type key + type value + val find: key -> value + (** @raise Not_found if the key is not in the table. *) +end + +(** Store the graph at each statement. *) +module Stmt_table: Table with type key = stmt and type value = Abstract_state.t option + + +(** Store the summary of each function. *) +module Function_table: + Table with type key = kernel_function and type value = Abstract_state.summary option + +(** [do_stmt a s] computes the abstract state after statement s. This + function does NOT store the result in Stmt_table. *) +val do_stmt: t -> stmt -> t + +(** [make_summary a f] computes the summary of a function (and the + next abstract state if needed) and stores the summary in + [Function_table]. *) +val make_summary: t -> kernel_function -> t * summary + +(** main analysis functions *) + +(** [compute ()] performs the may-alias analysis. It must be done once + before using functions defined in API.ml *) +val compute : unit -> unit + +(** [is_computed ()] returns true iff an analysis was done previously *) +val is_computed : unit -> bool + +(** [clear()] clears caches and imperative structures that are used by + the analysis. All accumulated data are lost. *) +val clear : unit -> unit + +(** see API.mli *) +val get_state_before_stmt : kernel_function -> stmt -> Abstract_state.t option + +(** see API.mli *) +val get_summary : kernel_function -> Abstract_state.summary option diff --git a/src/plugins/alias/dune b/src/plugins/alias/dune new file mode 100644 index 0000000000000000000000000000000000000000..63d49ab5cc95c628ad7d0cf25789504a89d9b823 --- /dev/null +++ b/src/plugins/alias/dune @@ -0,0 +1,46 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; This file is part of Frama-C. ;; +;; ;; +;; Copyright (C) 2007-2023 ;; +;; 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). ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +( rule + (alias frama-c-configure) + (deps (universe)) + (action ( progn + (echo "Alias:" %{lib-available:frama-c-alias.core} "\n") + (echo " - Frama-C:" %{lib-available:frama-c.kernel} "\n") + ) + ) +) + +( library + (name Alias) + (public_name frama-c-alias.core) + (flags -open Frama_c_kernel :standard) + (libraries frama-c.kernel ocamlgraph unionFind) + (instrumentation (backend landmarks)) +) + +( plugin + (optional) + (name alias) + (libraries frama-c-alias.core) + (site (frama-c plugins)) +) diff --git a/src/plugins/alias/dune-project b/src/plugins/alias/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..c934d313d775e41dbb3ccc769d0dba2d1439110a --- /dev/null +++ b/src/plugins/alias/dune-project @@ -0,0 +1,25 @@ +(lang dune 3.2) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; This file is part of Frama-C. ;; +;; ;; +;; Copyright (C) 2007-2023 ;; +;; 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). ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(name frama-c-alias) +(using dune_site 0.1) diff --git a/src/plugins/alias/frama-c-alias.opam b/src/plugins/alias/frama-c-alias.opam new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/plugins/alias/options.ml b/src/plugins/alias/options.ml new file mode 100644 index 0000000000000000000000000000000000000000..4f2fd9582b09ec7e2ab37cc4ae0f185a3334f6a3 --- /dev/null +++ b/src/plugins/alias/options.ml @@ -0,0 +1,79 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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). *) +(* *) +(**************************************************************************) + +(* -------------------------------------------------------------------------- *) +(* --- Plugin Registration --- *) +(* -------------------------------------------------------------------------- *) + +include Plugin.Register + (struct + let name = "Alias Analysis" + let help = "Lightweight May-Alias Analysis" + let shortname = "alias" + end) + +module Enabled = False + (struct + let option_name = "-alias" + let help = "Enable May-Alias Analyzer" + end) + +module ShowFunctionTable = False + (struct + let option_name = "-alias-show-function-table" + let help = "display summary for each function at the end of the analysis" + end) + +module ShowStmtTable = False + (struct + let option_name = "-alias-show-stmt-table" + let help = "display abstract state for each function at the end of the analysis" + end) + + +module DebugTable = False + (struct + let option_name = "-alias-debug-table" + let help = "switch to debug mode when printing statement or function tables (with options -alias-show-stmt-table and -alias-show-function-table)" + end) + + +module Dot_output = + Empty_string + (struct + let option_name = "-alias-dot-output" + let arg_name = "f" + let help = "output final abstract state as dot file <f>" + end) + +module Warn = struct + let no_return_stmt = register_warn_category "no-return" + let undefined_function = register_warn_category "undefined:fn" + let unsupported_address = register_warn_category "unsupported:addr" + let unsupported_asm = register_warn_category "unsupported:asm" + let unsupported_function = register_warn_category "unsupported:fn" + let unsafe_cast = register_warn_category "unsafe-cast" +end + +module DebugKeys = struct + let lvals = register_category "lvals" +end diff --git a/src/plugins/gui/gtk_compat.mli b/src/plugins/alias/options.mli similarity index 60% rename from src/plugins/gui/gtk_compat.mli rename to src/plugins/alias/options.mli index 8eaaf3d5fb526978fcb0e38d9edc9779c0f21fb3..bfe5800b537c1a318d743ab9f19ba389a1031700 100644 --- a/src/plugins/gui/gtk_compat.mli +++ b/src/plugins/alias/options.mli @@ -20,30 +20,36 @@ (* *) (**************************************************************************) -module Pango : sig - val set_small_font : #GObj.widget -> unit - (** makes the font smaller. *) +(* -------------------------------------------------------------------------- *) +(* --- Plugin Registration --- *) +(* -------------------------------------------------------------------------- *) - val set_bold_font : #GObj.widget -> unit - (** makes the font bold. *) +include Plugin.S + +(** Module activation *) +module Enabled : Parameter_sig.Bool + +(** Displays the table [function -> summary] at the end of the analysis *) +module ShowFunctionTable : Parameter_sig.Bool + +(** Displays the table [statement -> state] at the end of the analysis *) +module ShowStmtTable : Parameter_sig.Bool + +(** Switch to debug mode when displaying tables *) +module DebugTable : Parameter_sig.Bool + +(** Displays the final abstract state in Dot File <f> *) +module Dot_output : Parameter_sig.String + +module Warn : sig + val no_return_stmt : warn_category + val undefined_function : warn_category + val unsupported_address : warn_category + val unsupported_asm : warn_category + val unsupported_function : warn_category + val unsafe_cast : warn_category end -val get_toolbar_index: GButton.toolbar -> GButton.tool_item -> int - -val window: - ?kind:Gtk.Tags.window_type -> - ?title:string -> - ?decorated:bool -> - ?deletable:bool -> - ?focus_on_map:bool -> - ?icon:GdkPixbuf.pixbuf -> - ?icon_name:string -> - ?modal:bool -> - ?position:Gtk.Tags.window_position -> - ?resizable:bool -> - ?screen:Gdk.screen -> - ?type_hint:Gdk.Tags.window_type_hint -> - ?urgency_hint:bool -> - ?wmclass:(string * string) -> - ?border_width:int -> - ?width:int -> ?height:int -> ?show:bool -> unit -> GWindow.window +module DebugKeys : sig + val lvals : category +end diff --git a/src/plugins/alias/simplified.ml b/src/plugins/alias/simplified.ml new file mode 100644 index 0000000000000000000000000000000000000000..8250af8e229b46ebca8acba3184ef2e89bcafaad --- /dev/null +++ b/src/plugins/alias/simplified.ml @@ -0,0 +1,163 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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 Cil_datatype + +let nul_exp= Cil.zero ~loc:Location.unknown +let is_nul_exp = Cil_datatype.ExpStructEq.equal nul_exp + +module HL = Lval.Hashtbl +module HE = Exp.Hashtbl + +let cached_lval = HL.create 23 +let cached_exp = HE.create 37 + +let clear_cache () = + HL.clear cached_lval; + HE.clear cached_exp + +exception Explicit_pointer_address of location + +let check_cast_compatibility e typ = + let type_of_e = Cil.typeOf e in + (* emit a warning for unsafe casts, but not for the NULL pointer *) + if Cil.need_cast typ type_of_e && not (Cil.isZero e) then + Options.warning + ~once:true + ~source:(fst @@ e.eloc) + ~wkey:Options.Warn.unsafe_cast + "unsafe cast from %a to %a" + Printer.pp_typ type_of_e Printer.pp_typ typ + +let rec simplify_offset o = + match o with + | NoOffset -> NoOffset + | Field(f,o) -> Field(f, simplify_offset o) + | Index(_e,o) -> Index(nul_exp, simplify_offset o) + +let rec simplify_lval (h,o) = + try HL.find cached_lval (h,o) + with Not_found -> + let res = (simplify_host h, simplify_offset o) in + HL.add cached_lval (h,o) res; + res + +and simplify_host h = + match h with + | Var _ -> h + | Mem e -> + let simp_e = simplify_exp e in + if is_nul_exp simp_e + then raise (Explicit_pointer_address e.eloc) + else Mem simp_e + +and simplify_exp e = + try + HE.find cached_exp e + with Not_found -> + let res = + match e.enode with + | CastE (typ, e) -> + check_cast_compatibility e typ; + simplify_exp e + | Lval lv -> {e with enode = Lval (simplify_lval lv)} + | AddrOf lv | StartOf lv -> {e with enode = AddrOf (simplify_lval lv)} + | BinOp(PlusPI, e1, _, _) | BinOp(MinusPI, e1, _, _) -> + begin + match (simplify_exp e1).enode with + | Lval _ | AddrOf _ as node -> {e with enode = node} + | _ -> raise (Explicit_pointer_address e1.eloc) + end + | _ -> e + in + HE.add cached_exp e res; + res + +module LvalOrRef = struct + type t = Lval of lval | Ref of lval + + let pretty l = + let print f fmt x = + match x with + | Lval lv -> f fmt lv + | Ref lv -> Format.fprintf fmt "&%a" f lv + in + if Options.is_debug_key_enabled Options.DebugKeys.lvals + then print Cil_types_debug.pp_lval l + else print Printer.pp_lval l + + let from_exp e = + let e = simplify_exp e in + match e.enode with + Lval lv -> Some (Lval lv) + | AddrOf lv -> Some (Ref lv) + | _ -> None + + let is_pointer x = + match x with + | Ref _ -> true + | Lval lv -> + let t = Cil.typeOfLval lv in + match Cil.unrollType t with + TPtr _ | TArray _ -> true + | _ -> false +end + +module Lval = struct + type t = lval + + let simplify x = simplify_lval x + + let compare = Cil_datatype.LvalStructEq.compare + + let pretty l = + if Options.is_debug_key_enabled Options.DebugKeys.lvals + then Cil_types_debug.pp_lval l + else Printer.pp_lval l + + let points_to lv = Mem (Cil.dummy_exp (Lval lv)), NoOffset +end + +let decompose_lval lv1 : (lval * offset) list = + let rec list_of_offset (o: offset) : (offset*offset) list = + match o with + NoOffset -> [NoOffset,o] + | Index(e,ofs) -> + let li = + List.map + (fun (o1,o2) -> (Index(e,o1),o2)) + (list_of_offset ofs) + in + (NoOffset,o)::li + | Field(f, ofs) -> + let li = + List.map + (fun (o1,o2) -> (Field(f,o1),o2)) + (list_of_offset ofs) + in + (NoOffset,o)::li + in + let lv, off = Cil.removeOffsetLval lv1 in + List.map + (fun (o1,o2) -> Cil.addOffsetLval o1 lv, o2) + (list_of_offset off) diff --git a/src/plugins/gui/gtk_compat.3.ml b/src/plugins/alias/simplified.mli similarity index 63% rename from src/plugins/gui/gtk_compat.3.ml rename to src/plugins/alias/simplified.mli index 98bab3686652a22a62db3c18d0eb7e00ec928da5..08f5e21c9e8d1785115db6de5160d856c54b7360 100644 --- a/src/plugins/gui/gtk_compat.3.ml +++ b/src/plugins/alias/simplified.mli @@ -20,28 +20,39 @@ (* *) (**************************************************************************) -module Pango = struct - open Wutil_once - - let small_font = - once (fun (f: GPango.font_description) -> - let f = f#copy in - let size = f#size - 2 in - f#modify ~size (); f) - - let bold_font = - once (fun (f: GPango.font_description) -> - let f = f#copy in - let weight = `BOLD in - f#modify ~weight (); f) - - let modify_font phi (widget: #GObj.widget) = - widget#misc#modify_font (phi widget#misc#pango_context#font_description) - - let set_small_font w = modify_font small_font w - let set_bold_font w = modify_font bold_font w +open Cil_types + +module LvalOrRef : sig + type t = Lval of lval | Ref of lval + val pretty : Format.formatter -> t -> unit + + (* result stored in cache. May raise Explicit_pointer_address *) + val from_exp : exp -> t option + + (* true if x is assimilable to a pointer type (explicit pointer or + memory adress or array *) + val is_pointer : t -> bool +end + +(* exception raised when the program tries to access a memory location directly. *) +exception Explicit_pointer_address of location + +module Lval : sig + type t = lval + + val compare: t -> t -> int + + (* result stored in cache. May raise Explicit_pointer_address *) + val simplify : lval -> lval + + val pretty: Format.formatter -> t -> unit + + (* (points_to x) = *x and (points_to &x) = x. Raise + Explicit_pointer_address when applied to BNone *) + val points_to : lval -> lval end -let get_toolbar_index toolbar item = toolbar#get_item_index item#as_tool_item +val decompose_lval : lval -> (lval * offset) list -let window = GWindow.window +(** clear the two caches *) +val clear_cache : unit -> unit diff --git a/src/plugins/alias/tests/basic/addrof.c b/src/plugins/alias/tests/basic/addrof.c new file mode 100644 index 0000000000000000000000000000000000000000..838b4527950aea8619e4674e3e121b8d31439bd1 --- /dev/null +++ b/src/plugins/alias/tests/basic/addrof.c @@ -0,0 +1,11 @@ +int main () { + int **a, ***b, **y, *x, *z, p; + a = &x; + b = &y; + if (p) + y = &z; + else + *y = x; + + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment1.c b/src/plugins/alias/tests/basic/assignment1.c new file mode 100644 index 0000000000000000000000000000000000000000..2851d98907fe53177b4139ba9868a78f6201cf74 --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment1.c @@ -0,0 +1,11 @@ +// single pointer assignment +// {a, b, c, d} are aliased + +int main () { + + int *a=0, *b=0, *c=0, *d=0; + a = b; + b = c; + a = d; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment2.c b/src/plugins/alias/tests/basic/assignment2.c new file mode 100644 index 0000000000000000000000000000000000000000..ba0a8dc53e64428a841d94466d52a9f6cfda563a --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment2.c @@ -0,0 +1,13 @@ +// double pointer assignment +// {a, c} are aliased +// {*a, *c, b, d} are aliased + + +int main () { + + int **a=0, *b=0, **c=0, *d=0; + *a = b; + *c = d; + a = c; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment3.c b/src/plugins/alias/tests/basic/assignment3.c new file mode 100644 index 0000000000000000000000000000000000000000..203e93650c145bd0ee2a10cf547852a24551c02f --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment3.c @@ -0,0 +1,10 @@ +// address assignment +// {a, c} are aliased + +int main () { + + int *a=0, b=0, *c=0; + a = &b; + c = &b; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment4.c b/src/plugins/alias/tests/basic/assignment4.c new file mode 100644 index 0000000000000000000000000000000000000000..136a763cb531aa5b7ac9db937a41a49d60ca5041 --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment4.c @@ -0,0 +1,13 @@ +// double pointer assignment +// {a, c} are aliased +// {*a, *c, b, d} are aliased + + +int main () { + + int **a=0, *b=0, **c=0, *d=0; + *a = b; + *c = d; + b = d; + return 0; +} diff --git a/src/plugins/alias/tests/basic/assignment5.c b/src/plugins/alias/tests/basic/assignment5.c new file mode 100644 index 0000000000000000000000000000000000000000..03ccff7f6bf62d8eb127a9ff487c1b3bb0ecd6c4 --- /dev/null +++ b/src/plugins/alias/tests/basic/assignment5.c @@ -0,0 +1,12 @@ +// triple pointer assignment with some tricky alias +// {*a, b} are aliased +// {*(*a), *b, c, d} are aliased + +int main () { + + int ***a=0, **b=0, *c=0, *d=0; + *a = b; + *b = c; + d = **a; + return 0; +} diff --git a/src/plugins/alias/tests/basic/cast1.c b/src/plugins/alias/tests/basic/cast1.c new file mode 100644 index 0000000000000000000000000000000000000000..4a0713d879d9ae2d319aba0c359a3d8f8dedc102 --- /dev/null +++ b/src/plugins/alias/tests/basic/cast1.c @@ -0,0 +1,14 @@ +// homogeneous cast +// {a, c} are aliased +// {b, d} are aliased + + +int main () { + + int *a=0, *b=0; + float *c=0, *d=0; + a = (int*) c; + d = (float*) b; + + return 0; +} diff --git a/src/plugins/alias/tests/basic/conditional1.c b/src/plugins/alias/tests/basic/conditional1.c new file mode 100644 index 0000000000000000000000000000000000000000..a668cd7d083a810096ccde023c6fa83985ad2105 --- /dev/null +++ b/src/plugins/alias/tests/basic/conditional1.c @@ -0,0 +1,15 @@ +// conditional cfg +// {a, b, c} are aliased + +int main () { + + int *a=0, *b=0, *c=0; + if (a) { + a = b; + } + else { + a = c; + } + *a = 4; + return 0; +} diff --git a/src/plugins/alias/tests/basic/conditional2.c b/src/plugins/alias/tests/basic/conditional2.c new file mode 100644 index 0000000000000000000000000000000000000000..7243bebdbde9675572b75eaa0c134bd65bd65fe1 --- /dev/null +++ b/src/plugins/alias/tests/basic/conditional2.c @@ -0,0 +1,20 @@ +// conditional cfg +// {*a, *b, c} are aliased +// {*(*a), *(*b), *c, d} are aliased +// {a, b} are aliased + + +int main () { + + int ***a, ***b, **c, *d, e; + b = &c; + c = &d; + d = &e; + if (a) { + a = b; + } + else { + a = &c; + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/conditional3.c b/src/plugins/alias/tests/basic/conditional3.c new file mode 100644 index 0000000000000000000000000000000000000000..06d7dfbc131d38402a4ddbd96245cd579a4c1d44 --- /dev/null +++ b/src/plugins/alias/tests/basic/conditional3.c @@ -0,0 +1,26 @@ +// conditional with multiple levels of indirection +// {a, b, c} are aliased +// {*a, *b, *c, i, j} are aliased +// {*(*a), *(*b), *(*c), *i, *j, x, y} are aliased +// {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} are aliased + + + +int main () { + int ****a, ****b, ****c, ***i, ***j, **x, **y, *t, *u, p; + if (p) { + a=b; + b=&i; + i=&x; + x=&t; + } + else { + a=c; + c=&j; + j=&y; + y=&u; + } + p=0; + + return 0; +} diff --git a/src/plugins/alias/tests/basic/function1.c b/src/plugins/alias/tests/basic/function1.c new file mode 100644 index 0000000000000000000000000000000000000000..63bc345a7f779fd9c10517e951607731a896436b --- /dev/null +++ b/src/plugins/alias/tests/basic/function1.c @@ -0,0 +1,20 @@ +// function with no return +// {a, b} are aliased +// {c, d} are aliased + + +void swap(int *x, int* y) { + int*z=0; + z=x; + x=y; + y=z; +} + + +int main(void) +{ + int *a=0, *b=0, *c=0, *d=0; + swap(a,b); + swap(c,d); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function2.c b/src/plugins/alias/tests/basic/function2.c new file mode 100644 index 0000000000000000000000000000000000000000..e4411348cb39b56e76064ab07e3b5488281ed455 --- /dev/null +++ b/src/plugins/alias/tests/basic/function2.c @@ -0,0 +1,18 @@ +// malloc +// no alias + +#include <stdlib.h> + +int* my_malloc(int size) { + int* res=0; + res = malloc(size); + return res; +} + +int main(void) +{ + int *a=0, *b=0; + a=my_malloc(2); + b=my_malloc(3); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function3.c b/src/plugins/alias/tests/basic/function3.c new file mode 100644 index 0000000000000000000000000000000000000000..2142dcd0adefbce2ee3397a11d0c13efbb286ae2 --- /dev/null +++ b/src/plugins/alias/tests/basic/function3.c @@ -0,0 +1,23 @@ +// function with a loop inside +// {a, b} are aliased +// {c, d} are aliased + +void *f1(int *x, int* y) +{ + int *tmp = x; + + while (1) { + x=y; + y=tmp; + break; + } + return (void *) 0; +} + +int main(void) +{ + int *a=0, *b=0, *c=0, *d=0; + f1(a,b); + f1(c,d); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function4.c b/src/plugins/alias/tests/basic/function4.c new file mode 100644 index 0000000000000000000000000000000000000000..806b68cc3c364ead33143a0ad0a85e0cd9802a94 --- /dev/null +++ b/src/plugins/alias/tests/basic/function4.c @@ -0,0 +1,15 @@ +// funxtion with address agument +// {a, b} are aliased + +int * addr(int* x) +{ + return x; +} + +int main(void) +{ + int *a=0, *b=0, c=0; + a = addr(&c); + b = &c; + return 0; +} diff --git a/src/plugins/alias/tests/basic/function5.c b/src/plugins/alias/tests/basic/function5.c new file mode 100644 index 0000000000000000000000000000000000000000..94247a286c146fc451f4f7107846146d9a43d995 --- /dev/null +++ b/src/plugins/alias/tests/basic/function5.c @@ -0,0 +1,19 @@ +// function with multiple returns +// {a, b, c} are aliased + + +int * choice(int* x, int* y) +{ + int c=0; + if (c) + return x; + else + return y; +} + +int main(void) +{ + int *a=0, *b=0, *c=0; + c = choice(a,b); + return 0; +} diff --git a/src/plugins/alias/tests/basic/function6.c b/src/plugins/alias/tests/basic/function6.c new file mode 100644 index 0000000000000000000000000000000000000000..416136692b9b58787dbd32ad55e216c24b5c4ad7 --- /dev/null +++ b/src/plugins/alias/tests/basic/function6.c @@ -0,0 +1,19 @@ +// function with no return +// no alias + + +void swap(int *x, int* y) { + int z=0; + z=*x; + *x=*y; + *y=z; +} + + +int main(void) +{ + int *a=0, *b=0, *c=0, *d=0; + swap(a,b); + swap(c,d); + return 0; +} diff --git a/src/plugins/alias/tests/basic/globctr.c b/src/plugins/alias/tests/basic/globctr.c new file mode 100644 index 0000000000000000000000000000000000000000..5b399b157aef468a2f7824d7cf13b636a4570036 --- /dev/null +++ b/src/plugins/alias/tests/basic/globctr.c @@ -0,0 +1,12 @@ +void f(int *x) { + int y = 0; + *x = y; +} + +int main(void) +{ + int *a=0, *b=0; + f(a); + f(b); + return 0; +} diff --git a/src/plugins/alias/tests/basic/loop.c b/src/plugins/alias/tests/basic/loop.c new file mode 100644 index 0000000000000000000000000000000000000000..1b8f58d53345c679b86556995b74d7b37bdd9ea1 --- /dev/null +++ b/src/plugins/alias/tests/basic/loop.c @@ -0,0 +1,15 @@ +// used to lead to a loop in the graph - fixed +// no alias since there is an infinite loop + +int main() +{ + while (1) { + int l[1] = {0}; + int *n_0 = & l[1]; + n_0 = & l[1] + 0; + int w = 0; + if (w) + l[0] = *(& l[1] + 0); + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/oracle/addrof.res.oracle b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..8b2b579be28d8eee2dbeedad41454f7dcba4fbe9 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/addrof.res.oracle @@ -0,0 +1,15 @@ +[kernel] Parsing addrof.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = & x; +[alias] May-aliases after instruction a = & x; are {*a, x} +[alias] analysing instruction: b = & y; +[alias] May-aliases after instruction b = & y; are {*a, x} {*b, y} +[alias] analysing instruction: y = & z; +[alias] May-aliases after instruction y = & z; are + {*a, x} {*b, y} {*(*b), *y, z} +[alias] analysing instruction: *y = x; +[alias] May-aliases after instruction *y = x; are {*(*b), *a, *y, x} {*b, a, y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {*b, a, y} {*(*b), *a, *y, x, z} +[alias] May-aliases at the end of function main: {*b, a, y} {*(*b), *a, *y, x, z} diff --git a/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3c262c6c2ce8463df14d5cf6c6d31fadae384515 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: b = c; +[alias] May-aliases after instruction b = c; are {a, b, c} +[alias] analysing instruction: a = d; +[alias] May-aliases after instruction a = d; are {a, b, c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c, d} +[alias] May-aliases at the end of function main: {a, b, c, d} diff --git a/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0ad4f006ba3b3cf35f8fae1b61a40345b12f4143 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment2.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int **a = (int **)0; +[alias] May-aliases after instruction int **a = (int **)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int **c = (int **)0; +[alias] May-aliases after instruction int **c = (int **)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: *a = b; +[alias] May-aliases after instruction *a = b; are {*a, b} +[alias] analysing instruction: *c = d; +[alias] May-aliases after instruction *c = d; are {*a, b} {*c, d} +[alias] analysing instruction: a = c; +[alias] May-aliases after instruction a = c; are {a, c} {*a, *c, b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} {*a, *c, b, d} +[alias] May-aliases at the end of function main: {a, c} {*a, *c, b, d} diff --git a/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..65a7c76ee2a2b772a961b9574d747983a02c03a3 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment3.res.oracle @@ -0,0 +1,15 @@ +[kernel] Parsing assignment3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int b = 0; +[alias] May-aliases after instruction int b = 0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: a = & b; +[alias] May-aliases after instruction a = & b; are <none> +[alias] analysing instruction: c = & b; +[alias] May-aliases after instruction c = & b; are {a, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} +[alias] May-aliases at the end of function main: {a, c} diff --git a/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c422587f1a0662ac753d85d13b48ce30d9779b0d --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment4.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment4.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int **a = (int **)0; +[alias] May-aliases after instruction int **a = (int **)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int **c = (int **)0; +[alias] May-aliases after instruction int **c = (int **)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: *a = b; +[alias] May-aliases after instruction *a = b; are {*a, b} +[alias] analysing instruction: *c = d; +[alias] May-aliases after instruction *c = d; are {*a, b} {*c, d} +[alias] analysing instruction: b = d; +[alias] May-aliases after instruction b = d; are {a, c} {*a, *c, b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} {*a, *c, b, d} +[alias] May-aliases at the end of function main: {a, c} {*a, *c, b, d} diff --git a/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fc9d35993fc2fd1d3228b9f1888ccc80efc11155 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/assignment5.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing assignment5.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int ***a = (int ***)0; +[alias] May-aliases after instruction int ***a = (int ***)0; are <none> +[alias] analysing instruction: int **b = (int **)0; +[alias] May-aliases after instruction int **b = (int **)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: *a = b; +[alias] May-aliases after instruction *a = b; are {*a, b} +[alias] analysing instruction: *b = c; +[alias] May-aliases after instruction *b = c; are {*a, b} {*(*a), *b, c} +[alias] analysing instruction: d = *(*a); +[alias] May-aliases after instruction d = *(*a); are {*a, b} {*(*a), *b, c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {*a, b} {*(*a), *b, c, d} +[alias] May-aliases at the end of function main: {*a, b} {*(*a), *b, c, d} diff --git a/src/plugins/alias/tests/basic/oracle/cast1.res.oracle b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..efb26a239fe217242d96a035e5f532512856f69e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/cast1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing cast1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: float *c = (float *)0; +[alias] May-aliases after instruction float *c = (float *)0; are <none> +[alias] analysing instruction: float *d = (float *)0; +[alias] May-aliases after instruction float *d = (float *)0; are <none> +[alias] analysing instruction: a = (int *)c; +[alias:unsafe-cast] cast1.c:10: Warning: unsafe cast from float * to int * +[alias] May-aliases after instruction a = (int *)c; are {a, c} +[alias] analysing instruction: d = (float *)b; +[alias:unsafe-cast] cast1.c:11: Warning: unsafe cast from int * to float * +[alias] May-aliases after instruction d = (float *)b; are {a, c} {b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, c} {b, d} +[alias] May-aliases at the end of function main: {a, c} {b, d} diff --git a/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c903b74f5fe55bbca3300a508bb311813cbdd43c --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/conditional1.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing conditional1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: a = c; +[alias] May-aliases after instruction a = c; are {a, c} +[alias] analysing instruction: *a = 4; +[alias] May-aliases after instruction *a = 4; are {a, b, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c} +[alias] May-aliases at the end of function main: {a, b, c} diff --git a/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6088f9fb04df624989e4038e8fc723c7f40e880e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/conditional2.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing conditional2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: b = & c; +[alias] May-aliases after instruction b = & c; are {*b, c} +[alias] analysing instruction: c = & d; +[alias] May-aliases after instruction c = & d; are {*b, c} {*(*b), *c, d} +[alias] analysing instruction: d = & e; +[alias] May-aliases after instruction d = & e; are {*b, c} {*(*b), *c, d} +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} +[alias] analysing instruction: a = & c; +[alias] May-aliases after instruction a = & c; are + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} +[alias] May-aliases at the end of function main: + {*a, *b, c} {*(*a), *(*b), *c, d} {a, b} diff --git a/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..19088629ddb2ab448d832017d538ed52f23d0a08 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/conditional3.res.oracle @@ -0,0 +1,35 @@ +[kernel] Parsing conditional3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: b = & i; +[alias] May-aliases after instruction b = & i; are {a, b} {*a, *b, i} +[alias] analysing instruction: i = & x; +[alias] May-aliases after instruction i = & x; are + {a, b} {*a, *b, i} {*(*a), *(*b), *i, x} +[alias] analysing instruction: x = & t; +[alias] May-aliases after instruction x = & t; are + {a, b} {*a, *b, i} {*(*a), *(*b), *i, x} + {*(*(*a)), *(*(*b)), *(*i), *x, t} +[alias] analysing instruction: a = c; +[alias] May-aliases after instruction a = c; are {a, c} +[alias] analysing instruction: c = & j; +[alias] May-aliases after instruction c = & j; are {a, c} {*a, *c, j} +[alias] analysing instruction: j = & y; +[alias] May-aliases after instruction j = & y; are + {a, c} {*a, *c, j} {*(*a), *(*c), *j, y} +[alias] analysing instruction: y = & u; +[alias] May-aliases after instruction y = & u; are + {a, c} {*a, *c, j} {*(*a), *(*c), *j, y} + {*(*(*a)), *(*(*c)), *(*j), *y, u} +[alias] analysing instruction: p = 0; +[alias] May-aliases after instruction p = 0; are + {a, b, c} {*a, *b, *c, i, j} {*(*a), *(*b), *(*c), *i, *j, x, y} + {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {a, b, c} {*a, *b, *c, i, j} {*(*a), *(*b), *(*c), *i, *j, x, y} + {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} +[alias] May-aliases at the end of function main: + {a, b, c} {*a, *b, *c, i, j} {*(*a), *(*b), *(*c), *i, *j, x, y} + {*(*(*a)), *(*(*b)), *(*(*c)), *(*i), *(*j), *x, *y, t, u} diff --git a/src/plugins/alias/tests/basic/oracle/function1.res.oracle b/src/plugins/alias/tests/basic/oracle/function1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a22d297fdc0acd740dd01e992ac832c4051e6257 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function1.res.oracle @@ -0,0 +1,31 @@ +[kernel] Parsing function1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: swap(a,b); +[alias] analysing function: swap +[alias] analysing instruction: int *z = (int *)0; +[alias] May-aliases after instruction int *z = (int *)0; are <none> +[alias] analysing instruction: z = x; +[alias] May-aliases after instruction z = x; are {x, z} +[alias] analysing instruction: x = y; +[alias] May-aliases after instruction x = y; are {x, y, z} +[alias] analysing instruction: y = z; +[alias] May-aliases after instruction y = z; are {x, y, z} +[alias] May-aliases at the end of function swap: {x, y, z} +[alias] May-aliases after instruction swap(a,b); are {a, b} +[alias] analysing instruction: swap(c,d); +[alias] May-aliases after instruction swap(c,d); are {a, b} {c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} {c, d} +[alias] May-aliases at the end of function main: {a, b} {c, d} +[alias] analysing function: swap +[alias] analysing instruction: int *z = (int *)0; +[alias] May-aliases after instruction int *z = (int *)0; are <none> +[alias] May-aliases at the end of function swap: {x, y, z} diff --git a/src/plugins/alias/tests/basic/oracle/function2.res.oracle b/src/plugins/alias/tests/basic/oracle/function2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1e4decb3e431ddaeca4ca82775f8bc469b5f9756 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function2.res.oracle @@ -0,0 +1,136 @@ +[kernel] Parsing function2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: a = my_malloc(2); +[alias] analysing function: my_malloc +[alias] analysing instruction: int *res = (int *)0; +[alias] May-aliases after instruction int *res = (int *)0; are <none> +[alias] analysing instruction: res = (int *)malloc((size_t)size); +[alias] May-aliases after instruction res = (int *)malloc((size_t)size); are + <none> +[alias] May-aliases at the end of function my_malloc: <none> +[alias] May-aliases after instruction a = my_malloc(2); are <none> +[alias] analysing instruction: b = my_malloc(3); +[alias] May-aliases after instruction b = my_malloc(3); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: my_malloc +[alias] analysing instruction: int *res = (int *)0; +[alias] May-aliases after instruction int *res = (int *)0; are <none> +[alias] May-aliases at the end of function my_malloc: <none> +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/basic/oracle/function3.res.oracle b/src/plugins/alias/tests/basic/oracle/function3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d32eba5759924636897ce753d362cec982b56a90 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function3.res.oracle @@ -0,0 +1,27 @@ +[kernel] Parsing function3.c (with preprocessing) +[alias] analysing function: f1 +[alias] analysing instruction: int *tmp = x; +[alias] May-aliases after instruction int *tmp = x; are {x, tmp} +[alias] analysing instruction: x = y; +[alias] May-aliases after instruction x = y; are {x, y, tmp} +[alias] analysing instruction: y = tmp; +[alias] May-aliases after instruction y = tmp; are {x, y, tmp} +[alias] analysing instruction: __retres = (void *)0; +[alias] May-aliases after instruction __retres = (void *)0; are {x, y, tmp} +[alias] May-aliases at the end of function f1: {x, y, tmp} +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: f1(a,b); +[alias] May-aliases after instruction f1(a,b); are {a, b} +[alias] analysing instruction: f1(c,d); +[alias] May-aliases after instruction f1(c,d); are {a, b} {c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} {c, d} +[alias] May-aliases at the end of function main: {a, b} {c, d} diff --git a/src/plugins/alias/tests/basic/oracle/function4.res.oracle b/src/plugins/alias/tests/basic/oracle/function4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b7e6c7adde41156fd688fe72ca19bc4252f34c0d --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function4.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing function4.c (with preprocessing) +[alias] analysing function: addr +[alias] May-aliases at the end of function addr: <none> +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int c = 0; +[alias] May-aliases after instruction int c = 0; are <none> +[alias] analysing instruction: a = addr(& c); +[alias] May-aliases after instruction a = addr(& c); are <none> +[alias] analysing instruction: b = & c; +[alias] May-aliases after instruction b = & c; are {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} +[alias] May-aliases at the end of function main: {a, b} diff --git a/src/plugins/alias/tests/basic/oracle/function5.res.oracle b/src/plugins/alias/tests/basic/oracle/function5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..300762d6f2d441f3222d3ca79dcda3f7e0b4fd0d --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function5.res.oracle @@ -0,0 +1,21 @@ +[kernel] Parsing function5.c (with preprocessing) +[alias] analysing function: choice +[alias] analysing instruction: int c = 0; +[alias] May-aliases after instruction int c = 0; are <none> +[alias] analysing instruction: __retres = x; +[alias] May-aliases after instruction __retres = x; are {x, __retres} +[alias] analysing instruction: __retres = y; +[alias] May-aliases after instruction __retres = y; are {y, __retres} +[alias] May-aliases at the end of function choice: {x, y, __retres} +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: c = choice(a,b); +[alias] May-aliases after instruction c = choice(a,b); are {a, b, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c} +[alias] May-aliases at the end of function main: {a, b, c} diff --git a/src/plugins/alias/tests/basic/oracle/function6.res.oracle b/src/plugins/alias/tests/basic/oracle/function6.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4d8f8fa4a01fce5e95e6b5afdc4c4f24aec1c045 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/function6.res.oracle @@ -0,0 +1,31 @@ +[kernel] Parsing function6.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: swap(a,b); +[alias] analysing function: swap +[alias] analysing instruction: int z = 0; +[alias] May-aliases after instruction int z = 0; are <none> +[alias] analysing instruction: z = *x; +[alias] May-aliases after instruction z = *x; are <none> +[alias] analysing instruction: *x = *y; +[alias] May-aliases after instruction *x = *y; are <none> +[alias] analysing instruction: *y = z; +[alias] May-aliases after instruction *y = z; are <none> +[alias] May-aliases at the end of function swap: <none> +[alias] May-aliases after instruction swap(a,b); are <none> +[alias] analysing instruction: swap(c,d); +[alias] May-aliases after instruction swap(c,d); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> +[alias] analysing function: swap +[alias] analysing instruction: int z = 0; +[alias] May-aliases after instruction int z = 0; are <none> +[alias] May-aliases at the end of function swap: <none> diff --git a/src/plugins/alias/tests/basic/oracle/globctr.res.oracle b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..64f2826db29bf339219770a5cf558ec4f579b092 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/globctr.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing globctr.c (with preprocessing) +[alias] analysing function: f +[alias] analysing instruction: int y = 0; +[alias] May-aliases after instruction int y = 0; are <none> +[alias] analysing instruction: *x = y; +[alias] May-aliases after instruction *x = y; are <none> +[alias] May-aliases at the end of function f: <none> +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: f(a); +[alias] May-aliases after instruction f(a); are <none> +[alias] analysing instruction: f(b); +[alias] May-aliases after instruction f(b); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/basic/oracle/loop.res.oracle b/src/plugins/alias/tests/basic/oracle/loop.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9ef827f6daf8c1920926e31460dc19ab04c72bac --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/loop.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing loop.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int l[1] = {0}; +[alias] May-aliases after instruction int l[1] = {0}; are <none> +[alias] analysing instruction: int *n_0 = & l[1]; +[alias] May-aliases after instruction int *n_0 = & l[1]; are <none> +[alias] analysing instruction: n_0 = & l[1] + 0; +[alias] May-aliases after instruction n_0 = & l[1] + 0; are <none> +[alias] analysing instruction: int w = 0; +[alias] May-aliases after instruction int w = 0; are <none> +[alias] analysing instruction: l[0] = *(& l[1] + 0); +[alias] May-aliases after instruction l[0] = *(& l[1] + 0); are <none> +[alias] analysing instruction: int l[1] = {0}; +[alias] May-aliases after instruction int l[1] = {0}; are <none> +[alias] analysing instruction: int *n_0 = & l[1]; +[alias] May-aliases after instruction int *n_0 = & l[1]; are <none> +[alias:no-return] loop.c:4: Warning: + function main does not return; analysis may be unsound +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7b9c15f79cba40c1eb3120b93a10733bee758d1e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/steensgaard.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing steensgaard.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = & x; +[alias] May-aliases after instruction a = & x; are <none> +[alias] analysing instruction: b = & y; +[alias] May-aliases after instruction b = & y; are {*b, y} +[alias] analysing instruction: y = & z; +[alias] May-aliases after instruction y = & z; are {*b, y} +[alias] analysing instruction: y = & x; +[alias] May-aliases after instruction y = & x; are {*b, a, y} +[alias] analysing instruction: c = & y; +[alias] May-aliases after instruction c = & y; are {*b, *c, a, y} {b, c} +[alias] analysing instruction: *y = 4; +[alias] May-aliases after instruction *y = 4; are {*b, *c, a, y} {b, c} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {*b, *c, a, y} {b, c} +[alias] May-aliases at the end of function main: {*b, *c, a, y} {b, c} diff --git a/src/plugins/alias/tests/basic/oracle/switch1.res.oracle b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0819df147033b71a430fa6c56a9b42583ed83fa6 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/switch1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing switch1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: int e = 0; +[alias] May-aliases after instruction int e = 0; are <none> +[alias] analysing instruction: case 1: a = d; +[alias] May-aliases after instruction case 1: a = d; are {a, d} +[alias] analysing instruction: case 2: b = d; +[alias] May-aliases after instruction case 2: b = d; are {b, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, d} +[alias] May-aliases at the end of function main: {a, b, d} diff --git a/src/plugins/alias/tests/basic/oracle/switch2.res.oracle b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..40e0e801215e67cf06dfbc103ea1341b897bd96a --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/switch2.res.oracle @@ -0,0 +1,21 @@ +[kernel] Parsing switch2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int *d = (int *)0; +[alias] May-aliases after instruction int *d = (int *)0; are <none> +[alias] analysing instruction: int e = 0; +[alias] May-aliases after instruction int e = 0; are <none> +[alias] analysing instruction: case 1: a = d; +[alias] May-aliases after instruction case 1: a = d; are {a, d} +[alias] analysing instruction: case 2: b = d; +[alias] May-aliases after instruction case 2: b = d; are {b, d} +[alias] analysing instruction: default: c = d; +[alias] May-aliases after instruction default: c = d; are {c, d} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b, c, d} +[alias] May-aliases at the end of function main: {a, b, c, d} diff --git a/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..228274eef6fbd1b252d69ecb7bf0cf0c763c528e --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/while_for1.res.oracle @@ -0,0 +1,127 @@ +[kernel] Parsing while_for1.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *s = (int *)0; +[alias] May-aliases after instruction int *s = (int *)0; are <none> +[alias] analysing instruction: int idx = 0; +[alias] May-aliases after instruction int idx = 0; are <none> +[alias] analysing instruction: s = (int *)malloc((size_t)idx); +[alias] May-aliases after instruction s = (int *)malloc((size_t)idx); are <none> +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are <none> +[alias] analysing instruction: s = (int *)malloc((size_t)idx); +[alias] May-aliases after instruction s = (int *)malloc((size_t)idx); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..3986565e550a94827f115749244cece16be1b6ce --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/while_for2.res.oracle @@ -0,0 +1,13 @@ +[kernel] Parsing while_for2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} +[alias] May-aliases at the end of function main: {a, b} diff --git a/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..382069e577e43db211419f390f12de9f17a9da35 --- /dev/null +++ b/src/plugins/alias/tests/basic/oracle/while_for3.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing while_for3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: int *a = (int *)0; +[alias] May-aliases after instruction int *a = (int *)0; are <none> +[alias] analysing instruction: int *b = (int *)0; +[alias] May-aliases after instruction int *b = (int *)0; are <none> +[alias] analysing instruction: int *c = (int *)0; +[alias] May-aliases after instruction int *c = (int *)0; are <none> +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are <none> +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: __Cont: i ++; +[alias] May-aliases after instruction __Cont: i ++; are {a, b} +[alias] analysing instruction: a = b; +[alias] May-aliases after instruction a = b; are {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} +[alias] May-aliases at the end of function main: {a, b} diff --git a/src/plugins/alias/tests/basic/steensgaard.c b/src/plugins/alias/tests/basic/steensgaard.c new file mode 100644 index 0000000000000000000000000000000000000000..7afb87e247941e9aa1206c86324763ac77867c17 --- /dev/null +++ b/src/plugins/alias/tests/basic/steensgaard.c @@ -0,0 +1,19 @@ +// from steensgaard's paper +// {*b, *c, a, y} are aliased +// {b, c} are aliased + + +int main () { + int *a, **b, **c, *y, x, z, p; + a = &x; + b = &y; + if (p) + y = &z; + else + y = &x; + c = &y; + *y = 4; + return 0; +} + + diff --git a/src/plugins/alias/tests/basic/switch1.c b/src/plugins/alias/tests/basic/switch1.c new file mode 100644 index 0000000000000000000000000000000000000000..c0b97a18180983bda26f3439f939f604cc58624d --- /dev/null +++ b/src/plugins/alias/tests/basic/switch1.c @@ -0,0 +1,17 @@ +// switch +// {a, b, d} are aliased + +int main () +{ + int *a=0, *b=0, *c=0, *d=0, e=0; + switch (e) { + case 1: + a=d; + break; + case 2: + b=d; + break; + } + + return 0; +} diff --git a/src/plugins/alias/tests/basic/switch2.c b/src/plugins/alias/tests/basic/switch2.c new file mode 100644 index 0000000000000000000000000000000000000000..05d162bd67a0dd14fb8010af75281c989425e705 --- /dev/null +++ b/src/plugins/alias/tests/basic/switch2.c @@ -0,0 +1,19 @@ +// switch with default +// {a, b, c, d} are aliased + +int main () +{ + int *a=0, *b=0, *c=0, *d=0, e=0; + switch (e) { + case 1: + a=d; + break; + case 2: + b=d; + break; + default: + c=d; + } + + return 0; +} diff --git a/src/plugins/alias/tests/basic/while_for1.c b/src/plugins/alias/tests/basic/while_for1.c new file mode 100644 index 0000000000000000000000000000000000000000..06ef79f5f89d2573152cf3035a59fa55d2e8baad --- /dev/null +++ b/src/plugins/alias/tests/basic/while_for1.c @@ -0,0 +1,13 @@ +// for loop +// no alias + +#include <stdlib.h> + +int main () +{ + int* s = 0; + for (int idx = 0; idx < 10; idx++) { + s = malloc(idx); + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/while_for2.c b/src/plugins/alias/tests/basic/while_for2.c new file mode 100644 index 0000000000000000000000000000000000000000..f98677716b7e80a6f746b6e7033a61c4069b4c7f --- /dev/null +++ b/src/plugins/alias/tests/basic/while_for2.c @@ -0,0 +1,17 @@ +// while loops with trivial conditions +// {a, b} are aliased + +int main () +{ + int *a=0, *b=0, *c=0; + while (1) { + a = b; + break; + } + + while (0) { + a = c; + break; + } + return 0; +} diff --git a/src/plugins/alias/tests/basic/while_for3.c b/src/plugins/alias/tests/basic/while_for3.c new file mode 100644 index 0000000000000000000000000000000000000000..e7ffb9f39523ca14abdc8ba00b84fd55699e195b --- /dev/null +++ b/src/plugins/alias/tests/basic/while_for3.c @@ -0,0 +1,16 @@ +// continue +// {a, b} are aliased + +int main () +{ + int *a=0, *b=0, *c=0; + for (int i=0; i<10 ;i++) { + if (1) { + a = b; + continue; + } + a = c; + } + + return 0; +} diff --git a/src/plugins/alias/tests/fixed_bugs/empty_nodes.c b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c new file mode 100644 index 0000000000000000000000000000000000000000..004a207da7443ec4a3ee2c1c21913e53641ccd0b --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/empty_nodes.c @@ -0,0 +1,12 @@ +void f(char **x, char **y, char **z) +{ + char *t; + *y = t + (*y - *x); + *z = t + (*z - *x); + *x = t; +} + +void g(char **a) +{ + f(a,a,a); +} diff --git a/src/plugins/alias/tests/fixed_bugs/gzip124.c b/src/plugins/alias/tests/fixed_bugs/gzip124.c new file mode 100644 index 0000000000000000000000000000000000000000..70a9cc2955966f21c8ea856531bf467464e66355 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/gzip124.c @@ -0,0 +1,12 @@ +int main(void) +{ + int __retres; + short prev[1]; + short *p; + short tmp_0 = (short)0; + *(& prev[1] + 0) = tmp_0; + prev[0] = (short)0; + if (0 + 0) p = & prev[1] + (int)*p; else p = & prev[*p]; + __retres = 0; + return __retres; +} diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..970b25bd3ea518640e4cdca331963fd23ab641f8 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/empty_nodes.res.oracle @@ -0,0 +1,13 @@ +[kernel] Parsing empty_nodes.c (with preprocessing) +[alias] analysing function: f +[alias] analysing instruction: *y = t + (*y - *x); +[alias] May-aliases after instruction *y = t + (*y - *x); are {*y, t} +[alias] analysing instruction: *z = t + (*z - *x); +[alias] May-aliases after instruction *z = t + (*z - *x); are {*y, *z, t} {y, z} +[alias] analysing instruction: *x = t; +[alias] May-aliases after instruction *x = t; are {*x, *y, *z, t} {x, y, z} +[alias] May-aliases at the end of function f: {*x, *y, *z, t} {x, y, z} +[alias] analysing function: g +[alias] analysing instruction: f(a,a,a); +[alias] May-aliases after instruction f(a,a,a); are <none> +[alias] May-aliases at the end of function g: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..fd9878fef65bf1ea35de5b51eef9ccfe7b40d5a0 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/gzip124.res.oracle @@ -0,0 +1,15 @@ +[kernel] Parsing gzip124.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: short tmp_0 = (short)0; +[alias] May-aliases after instruction short tmp_0 = (short)0; are <none> +[alias] analysing instruction: *(& prev[1] + 0) = tmp_0; +[alias] May-aliases after instruction *(& prev[1] + 0) = tmp_0; are <none> +[alias] analysing instruction: prev[0] = (short)0; +[alias] May-aliases after instruction prev[0] = (short)0; are <none> +[alias] analysing instruction: p = & prev[1] + (int)*p; +[alias] May-aliases after instruction p = & prev[1] + (int)*p; are <none> +[alias] analysing instruction: p = & prev[*p]; +[alias] May-aliases after instruction p = & prev[*p]; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..bdc3f9de65441a71704fe3c6c2faf4b5d51f684b --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/semver.res.oracle @@ -0,0 +1,12 @@ +[kernel] Parsing semver.c (with preprocessing) +[alias] analysing function: f +[alias] May-aliases at the end of function f: <none> +[alias] analysing function: main +[alias] analysing instruction: f((int *)*("1" + 2)); +[alias:unsafe-cast] semver.c:6: Warning: unsafe cast from char to int * +[alias:unsupported:addr] semver.c:6: Warning: + unsupported feature: explicit pointer address: (int *)*("1" + 2); analysis may be unsound +[alias] May-aliases after instruction f((int *)*("1" + 2)); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7843cab155742b5e87b1d4e3c6fd67107fca9412 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/tkn-2.res.oracle @@ -0,0 +1,9 @@ +[kernel] Parsing tkn-2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: a = (int *)(& a); +[alias:unsafe-cast] tkn-2.c:6: Warning: unsafe cast from int ** to int * +[alias] tkn-2.c:6: Warning: ignoring assignment of the form: a = (int *)(& a) +[alias] May-aliases after instruction a = (int *)(& a); are <none> +[alias] analysing instruction: __retres = *a; +[alias] May-aliases after instruction __retres = *a; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..606169550d1d780734a260fb8b0af502e57a26c5 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/oracle/union_vmap.res.oracle @@ -0,0 +1,21 @@ +[kernel] Parsing union_vmap.c (with preprocessing) +[alias] analysing function: CPS_ParseKey +[alias] analysing instruction: char *s2 = CPS_SplitWord((char *)"a"); +[alias] analysing function: CPS_SplitWord +[alias] May-aliases at the end of function CPS_SplitWord: <none> +[alias:unsafe-cast] union_vmap.c:11: Warning: + unsafe cast from char const * to char * +[alias] May-aliases after instruction char *s2 = CPS_SplitWord((char *)"a"); are + <none> +[alias] analysing instruction: char *s3 = CPS_SplitWord((char *)"b"); +[alias:unsafe-cast] union_vmap.c:12: Warning: + unsafe cast from char const * to char * +[alias] May-aliases after instruction char *s3 = CPS_SplitWord((char *)"b"); are + <none> +[alias] analysing instruction: *key = s3; +[alias] May-aliases after instruction *key = s3; are {*key, s3} +[alias] analysing instruction: *key = s2; +[alias] May-aliases after instruction *key = s2; are {*key, s2} +[alias] May-aliases at the end of function CPS_ParseKey: {*key, s2, s3} +[alias] analysing function: CPS_SplitWord +[alias] May-aliases at the end of function CPS_SplitWord: <none> diff --git a/src/plugins/alias/tests/fixed_bugs/semver.c b/src/plugins/alias/tests/fixed_bugs/semver.c new file mode 100644 index 0000000000000000000000000000000000000000..d93edc0b90eb1d95415b0dd17453a639414a8d4e --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/semver.c @@ -0,0 +1,8 @@ +void f (int* x) { +} + +int main(void) +{ + f ((int*)*("1" + 2)); + return 0; +} diff --git a/src/plugins/alias/tests/fixed_bugs/tkn-2.c b/src/plugins/alias/tests/fixed_bugs/tkn-2.c new file mode 100644 index 0000000000000000000000000000000000000000..97ee64b4f9aa53e56ec9766877bad8dae52f260e --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/tkn-2.c @@ -0,0 +1,8 @@ +// leads to a loop; taken from open-source-case-studies/cerberus + +int main() +{ + int* a; + a = (int*)(& a); + return *a; +} diff --git a/src/plugins/alias/tests/fixed_bugs/union_vmap.c b/src/plugins/alias/tests/fixed_bugs/union_vmap.c new file mode 100644 index 0000000000000000000000000000000000000000..5bf04ceddf9510e34cf3465710a71896ed841990 --- /dev/null +++ b/src/plugins/alias/tests/fixed_bugs/union_vmap.c @@ -0,0 +1,21 @@ +// from open-source-case-studies/chrony + +char* CPS_SplitWord(char *line) +{ + return line; +} + +void CPS_ParseKey() +{ + char **key; + char *s2 = CPS_SplitWord("a"); + char *s3 = CPS_SplitWord("b"); + if (*s3) { + *key = s3; + } + else { + *key = s2; + } +} + + diff --git a/src/plugins/alias/tests/offsets/array1.c b/src/plugins/alias/tests/offsets/array1.c new file mode 100644 index 0000000000000000000000000000000000000000..34518455ecb6fae2be23331c1a9a3a1ba0251135 --- /dev/null +++ b/src/plugins/alias/tests/offsets/array1.c @@ -0,0 +1,15 @@ +// simple array +// {x, y} are aliased + +int main () { + int tab[4]; + tab[0] = 0; + tab[1] = 1; + tab[2] = tab[1] +1; + + int* x = &tab[1]; + int* y = &tab[2]; + tab[3] = *x + *y; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/array2.c b/src/plugins/alias/tests/offsets/array2.c new file mode 100644 index 0000000000000000000000000000000000000000..0ba4d222f6a4642288f2c53cfd8fcfb1d1e7b036 --- /dev/null +++ b/src/plugins/alias/tests/offsets/array2.c @@ -0,0 +1,17 @@ +// matrices (this example may be not a valid c program) +// no alias + +int main () { + int mat[4][4]; + mat[0][0] = 0; + mat[0][1] = 1; + + int **x; + *x = mat[1]; + + int* y; + *y = *x[0]; + + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/array3.c b/src/plugins/alias/tests/offsets/array3.c new file mode 100644 index 0000000000000000000000000000000000000000..09bd2e67a51be84ef8a466417a95f88709ef8b3d --- /dev/null +++ b/src/plugins/alias/tests/offsets/array3.c @@ -0,0 +1,15 @@ +// matrices +// {x, y} are aliased + +#include <stdlib.h> + + +int main () { + int mat[4][4]; + int* x = malloc (4* sizeof(int)); + int* y = malloc (4* sizeof(int)); + x = mat[0]; + y = mat[1]; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/collapse1.c b/src/plugins/alias/tests/offsets/collapse1.c new file mode 100644 index 0000000000000000000000000000000000000000..624f42c3af68819390dbbaf141ef0452f9ba3c75 --- /dev/null +++ b/src/plugins/alias/tests/offsets/collapse1.c @@ -0,0 +1,14 @@ + + +int main () { + int tab[4]; + tab[0] = 0; + tab[1] = 1; + tab[2] = tab[1] +1; + int x =0; + + for (int i=0;i<2;i++) + x = tab[i]; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/collapse2.c b/src/plugins/alias/tests/offsets/collapse2.c new file mode 100644 index 0000000000000000000000000000000000000000..9c00bd24e3b5297f9d18a9fe99922e4a5d543802 --- /dev/null +++ b/src/plugins/alias/tests/offsets/collapse2.c @@ -0,0 +1,15 @@ +// matrices + +int main () { + int mat[4][4]; + mat[0][0] = 0; + mat[0][1] = 1; + + int i=2; + mat[1][i]=i; + + i=i+1; + mat[1][i]=2; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/collapse3.c b/src/plugins/alias/tests/offsets/collapse3.c new file mode 100644 index 0000000000000000000000000000000000000000..8540638c809a74ad632b46ec6ce12342b30906e6 --- /dev/null +++ b/src/plugins/alias/tests/offsets/collapse3.c @@ -0,0 +1,15 @@ +// matrices + +int main () { + int mat[4][4]; + mat[0][0] = 0; + mat[0][1] = 1; + + int i=2; + mat[i][1]=i; + + i=i+1; + mat[i][1]=2; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/nested1.c b/src/plugins/alias/tests/offsets/nested1.c new file mode 100644 index 0000000000000000000000000000000000000000..06c14b9512b4ee4d15c4451f2d22382c2703f49c --- /dev/null +++ b/src/plugins/alias/tests/offsets/nested1.c @@ -0,0 +1,56 @@ +// nested structures and arrays +// {z1->s, z2->s, tab_y[0]} are aliased +// {t->t, z1} are aliased +// {z1->c, t->d, a} are aliased +// {z2->c, b} are aliased + + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int* c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int* d; +} st_3_t; + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_1_t *tab_y [2]; + + tab_y[0] = &x1; + tab_y[1] = &x2; + st_2_t *z1 = malloc(sizeof(st_2_t)); + st_2_t *z2 = malloc(sizeof(st_2_t)); + st_3_t *t = malloc(sizeof(st_3_t)); + int* a = malloc(sizeof(int)); + int* b = malloc(sizeof(int)); + + *a = 0; + *b = 5; + z1->s = tab_y[0]; + z2->s = tab_y[1]; + z1->c = a; + z2->c = b; + t->t = z1; + t->d = a; + + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/nested2.c b/src/plugins/alias/tests/offsets/nested2.c new file mode 100644 index 0000000000000000000000000000000000000000..193bdd1adba16542da95e964e384c3651c373379 --- /dev/null +++ b/src/plugins/alias/tests/offsets/nested2.c @@ -0,0 +1,50 @@ +// nested structures and arrays +// {t->t, z1} are aliased +// {z1->c, t->d, a} are aliased + + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s [2]; + int* c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int* d; +} st_3_t; + + + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {2,3}; + + st_2_t *z1 = malloc(sizeof(st_2_t)); + + st_3_t *t = malloc(sizeof(st_3_t)); + int* a = malloc(sizeof(int)); + + *a = 0; + z1->s[0] = &x1; + z1->s[1] = &x2; + z1->c = a; + t->t = z1; + t->d = a; + + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/oracle/array1.res.oracle b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d6bdf7ba016ca2bf534ccbde0c2f7b0fe9f36f76 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/array1.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing array1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: tab[0] = 0; +[alias] May-aliases after instruction tab[0] = 0; are <none> +[alias] analysing instruction: tab[1] = 1; +[alias] May-aliases after instruction tab[1] = 1; are <none> +[alias] analysing instruction: tab[2] = tab[1] + 1; +[alias] May-aliases after instruction tab[2] = tab[1] + 1; are <none> +[alias] analysing instruction: int *x = & tab[1]; +[alias] May-aliases after instruction int *x = & tab[1]; are <none> +[alias] analysing instruction: int *y = & tab[2]; +[alias] May-aliases after instruction int *y = & tab[2]; are {x, y} +[alias] analysing instruction: tab[3] = *x + *y; +[alias] May-aliases after instruction tab[3] = *x + *y; are {x, y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {x, y} +[alias] May-aliases at the end of function main: {x, y} diff --git a/src/plugins/alias/tests/offsets/oracle/array2.res.oracle b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..69f16a022f8b05688a9a9eb66a4180354fdcf323 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/array2.res.oracle @@ -0,0 +1,13 @@ +[kernel] Parsing array2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: mat[0][0] = 0; +[alias] May-aliases after instruction mat[0][0] = 0; are <none> +[alias] analysing instruction: mat[0][1] = 1; +[alias] May-aliases after instruction mat[0][1] = 1; are <none> +[alias] analysing instruction: *x = mat[1]; +[alias] May-aliases after instruction *x = mat[1]; are <none> +[alias] analysing instruction: *y = *(*(x + 0)); +[alias] May-aliases after instruction *y = *(*(x + 0)); are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/array3.res.oracle b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6b6a66a4677d71e520481483aaa137fa7dd8529c --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/array3.res.oracle @@ -0,0 +1,127 @@ +[kernel] Parsing array3.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *x = malloc((unsigned long)4 * sizeof(int)); +[alias] May-aliases after instruction + int *x = malloc((unsigned long)4 * sizeof(int)); are <none> +[alias] analysing instruction: int *y = malloc((unsigned long)4 * sizeof(int)); +[alias] May-aliases after instruction + int *y = malloc((unsigned long)4 * sizeof(int)); are <none> +[alias] analysing instruction: x = mat[0]; +[alias] May-aliases after instruction x = mat[0]; are <none> +[alias] analysing instruction: y = mat[1]; +[alias] May-aliases after instruction y = mat[1]; are {x, y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {x, y} +[alias] May-aliases at the end of function main: {x, y} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9b588f2f8f2484f894680dae6ca6129528811125 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/collapse1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing collapse1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: tab[0] = 0; +[alias] May-aliases after instruction tab[0] = 0; are <none> +[alias] analysing instruction: tab[1] = 1; +[alias] May-aliases after instruction tab[1] = 1; are <none> +[alias] analysing instruction: tab[2] = tab[1] + 1; +[alias] May-aliases after instruction tab[2] = tab[1] + 1; are <none> +[alias] analysing instruction: int x = 0; +[alias] May-aliases after instruction int x = 0; are <none> +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are <none> +[alias] analysing instruction: x = tab[i]; +[alias] May-aliases after instruction x = tab[i]; are <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..34b8bd11975081e1acc6cd63c7d0011d1f3b57e3 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/collapse2.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing collapse2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: mat[0][0] = 0; +[alias] May-aliases after instruction mat[0][0] = 0; are <none> +[alias] analysing instruction: mat[0][1] = 1; +[alias] May-aliases after instruction mat[0][1] = 1; are <none> +[alias] analysing instruction: int i = 2; +[alias] May-aliases after instruction int i = 2; are <none> +[alias] analysing instruction: mat[1][i] = i; +[alias] May-aliases after instruction mat[1][i] = i; are <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: mat[1][i] = 2; +[alias] May-aliases after instruction mat[1][i] = 2; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4193c3f90a212238b3a6f1452d58e097c1ae1bd1 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/collapse3.res.oracle @@ -0,0 +1,17 @@ +[kernel] Parsing collapse3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: mat[0][0] = 0; +[alias] May-aliases after instruction mat[0][0] = 0; are <none> +[alias] analysing instruction: mat[0][1] = 1; +[alias] May-aliases after instruction mat[0][1] = 1; are <none> +[alias] analysing instruction: int i = 2; +[alias] May-aliases after instruction int i = 2; are <none> +[alias] analysing instruction: mat[i][1] = i; +[alias] May-aliases after instruction mat[i][1] = i; are <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: mat[i][1] = 2; +[alias] May-aliases after instruction mat[i][1] = 2; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..e26a96622ddd53633ec3d0978ac43635f1dc1e4f --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/nested1.res.oracle @@ -0,0 +1,168 @@ +[kernel] Parsing nested1.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: tab_y[0] = & x1; +[alias] May-aliases after instruction tab_y[0] = & x1; are <none> +[alias] analysing instruction: tab_y[1] = & x2; +[alias] May-aliases after instruction tab_y[1] = & x2; are <none> +[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z1 = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_2_t *z2 = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z2 = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t)); +[alias] May-aliases after instruction st_3_t *t = malloc(sizeof(st_3_t)); are + <none> +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: int *b = malloc(sizeof(int)); +[alias] May-aliases after instruction int *b = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: *b = 5; +[alias] May-aliases after instruction *b = 5; are <none> +[alias] analysing instruction: z1->s = (struct struct_1_t *)tab_y[0]; +[alias:unsafe-cast] nested1.c:47: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z1->s = (struct struct_1_t *)tab_y[0]; are + {z1->s, tab_y[0]} +[alias] analysing instruction: z2->s = (struct struct_1_t *)tab_y[1]; +[alias:unsafe-cast] nested1.c:48: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z2->s = (struct struct_1_t *)tab_y[1]; are + {z1->s, z2->s, tab_y[0]} +[alias] analysing instruction: z1->c = a; +[alias] May-aliases after instruction z1->c = a; are + {z1->s, z2->s, tab_y[0]} {z1->c, a} +[alias] analysing instruction: z2->c = b; +[alias] May-aliases after instruction z2->c = b; are + {z1->s, z2->s, tab_y[0]} {z1->c, a} {z2->c, b} +[alias] analysing instruction: t->t = (struct struct_2_t *)z1; +[alias:unsafe-cast] nested1.c:51: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction t->t = (struct struct_2_t *)z1; are + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, a} {z2->c, b} +[alias] analysing instruction: t->d = a; +[alias] May-aliases after instruction t->d = a; are + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, t->d, a} {z2->c, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, t->d, a} {z2->c, b} +[alias] May-aliases at the end of function main: + {z1->s, z2->s, tab_y[0]} {t->t, z1} {z1->c, t->d, a} {z2->c, b} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7167c4aebae1c65a02d1333dd738a7c9cccc658c --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/nested2.res.oracle @@ -0,0 +1,151 @@ +[kernel] Parsing nested2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 2, .b = 3}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 2, .b = 3}; are <none> +[alias] analysing instruction: st_2_t *z1 = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z1 = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t)); +[alias] May-aliases after instruction st_3_t *t = malloc(sizeof(st_3_t)); are + <none> +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: z1->s[0] = (struct struct_1_t *)(& x1); +[alias:unsafe-cast] nested2.c:42: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z1->s[0] = (struct struct_1_t *)(& x1); are + <none> +[alias] analysing instruction: z1->s[1] = (struct struct_1_t *)(& x2); +[alias:unsafe-cast] nested2.c:43: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z1->s[1] = (struct struct_1_t *)(& x2); are + <none> +[alias] analysing instruction: z1->c = a; +[alias] May-aliases after instruction z1->c = a; are {z1->c, a} +[alias] analysing instruction: t->t = (struct struct_2_t *)z1; +[alias:unsafe-cast] nested2.c:45: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction t->t = (struct struct_2_t *)z1; are + {t->t, z1} {z1->c, a} +[alias] analysing instruction: t->d = a; +[alias] May-aliases after instruction t->d = a; are {t->t, z1} {z1->c, t->d, a} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {t->t, z1} {z1->c, t->d, a} +[alias] May-aliases at the end of function main: {t->t, z1} {z1->c, t->d, a} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6fab8c1f99d32876d28e448212a5a4a026a7809c --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure1.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing structure1.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: st_1_t x = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_2_t y = {.a = 3, .c = 4}; +[alias] May-aliases after instruction st_2_t y = {.a = 3, .c = 4}; are <none> +[alias] analysing instruction: st_1_t *p_x = & x; +[alias] May-aliases after instruction st_1_t *p_x = & x; are <none> +[alias] analysing instruction: st_2_t *p_y = & y; +[alias] May-aliases after instruction st_2_t *p_y = & y; are <none> +[alias] analysing instruction: p_x->a = 3; +[alias] May-aliases after instruction p_x->a = 3; are <none> +[alias] analysing instruction: p_x = (st_1_t *)p_y; +[alias:unsafe-cast] structure1.c:28: Warning: + unsafe cast from st_2_t * to st_1_t * +[alias] May-aliases after instruction p_x = (st_1_t *)p_y; are {p_x, p_y} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {p_x, p_y} +[alias] May-aliases at the end of function main: {p_x, p_y} diff --git a/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2b2f7ecd4e531f1ec02f3d115396b6b6f0de27d0 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure2.res.oracle @@ -0,0 +1,19 @@ +[kernel] Parsing structure2.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4}; +[alias:unsafe-cast] structure2.c:21: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction + st_2_t y = {.s = (struct struct_1_t *)(& x1), .c = 4}; are <none> +[alias] analysing instruction: y.s = (struct struct_1_t *)(& x2); +[alias:unsafe-cast] structure2.c:23: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction y.s = (struct struct_1_t *)(& x2); are + <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7ec86d402cb6980ff01296b3901039b234b94464 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure3.res.oracle @@ -0,0 +1,33 @@ +[kernel] Parsing structure3.c (with preprocessing) +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: + st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3}; +[alias:unsafe-cast] structure3.c:31: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction + st_2_t y1 = {.s = (struct struct_1_t *)(& x1), .c = 3}; are <none> +[alias] analysing instruction: + st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4}; +[alias:unsafe-cast] structure3.c:32: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction + st_2_t y2 = {.s = (struct struct_1_t *)(& x2), .c = 4}; are <none> +[alias] analysing instruction: st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5}; +[alias:unsafe-cast] structure3.c:33: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction + st_3_t z = {.t = (struct struct_2_t *)(& y1), .d = 5}; are <none> +[alias] analysing instruction: z.t = (struct struct_2_t *)(& y2); +[alias:unsafe-cast] structure3.c:35: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction z.t = (struct struct_2_t *)(& y2); are + <none> +[alias] analysing instruction: y1.c = z.d; +[alias] May-aliases after instruction y1.c = z.d; are <none> +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are <none> +[alias] May-aliases at the end of function main: <none> diff --git a/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..17d462a32e0c6ec88e3c3c03b6c82ae0b907a465 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure4.res.oracle @@ -0,0 +1,136 @@ +[kernel] Parsing structure4.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t)); +[alias] May-aliases after instruction st_1_t *y1 = malloc(sizeof(st_1_t)); are + <none> +[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: y1 = & x1; +[alias] May-aliases after instruction y1 = & x1; are <none> +[alias] analysing instruction: z->s = (struct struct_1_t *)y1; +[alias:unsafe-cast] structure4.c:37: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z->s = (struct struct_1_t *)y1; are + {z->s, y1} +[alias] analysing instruction: z->c = 6; +[alias] May-aliases after instruction z->c = 6; are {z->s, y1} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {z->s, y1} +[alias] May-aliases at the end of function main: {z->s, y1} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6ab3b8478904bba3396ee4bf1314b90cb372fb45 --- /dev/null +++ b/src/plugins/alias/tests/offsets/oracle/structure5.res.oracle @@ -0,0 +1,153 @@ +[kernel] Parsing structure5.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: st_1_t x1 = {.a = 0, .b = 1}; +[alias] May-aliases after instruction st_1_t x1 = {.a = 0, .b = 1}; are <none> +[alias] analysing instruction: st_1_t x2 = {.a = 1, .b = 2}; +[alias] May-aliases after instruction st_1_t x2 = {.a = 1, .b = 2}; are <none> +[alias] analysing instruction: st_1_t *y1 = malloc(sizeof(st_1_t)); +[alias] May-aliases after instruction st_1_t *y1 = malloc(sizeof(st_1_t)); are + <none> +[alias] analysing instruction: st_2_t *z = malloc(sizeof(st_2_t)); +[alias] May-aliases after instruction st_2_t *z = malloc(sizeof(st_2_t)); are + <none> +[alias] analysing instruction: st_3_t *t = malloc(sizeof(st_3_t)); +[alias] May-aliases after instruction st_3_t *t = malloc(sizeof(st_3_t)); are + <none> +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: y1 = & x1; +[alias] May-aliases after instruction y1 = & x1; are <none> +[alias] analysing instruction: z->s = (struct struct_1_t *)y1; +[alias:unsafe-cast] structure5.c:41: Warning: + unsafe cast from st_1_t * to struct struct_1_t * +[alias] May-aliases after instruction z->s = (struct struct_1_t *)y1; are + {z->s, y1} +[alias] analysing instruction: z->c = a; +[alias] May-aliases after instruction z->c = a; are {z->s, y1} {z->c, a} +[alias] analysing instruction: t->t = (struct struct_2_t *)z; +[alias:unsafe-cast] structure5.c:43: Warning: + unsafe cast from st_2_t * to struct struct_2_t * +[alias] May-aliases after instruction t->t = (struct struct_2_t *)z; are + {z->s, y1} {t->t, z} {z->c, a} +[alias] analysing instruction: t->d = a; +[alias] May-aliases after instruction t->d = a; are + {z->s, y1} {t->t, z} {z->c, t->d, a} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {z->s, y1} {t->t, z} {z->c, t->d, a} +[alias] May-aliases at the end of function main: + {z->s, y1} {t->t, z} {z->c, t->d, a} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/offsets/structure1.c b/src/plugins/alias/tests/offsets/structure1.c new file mode 100644 index 0000000000000000000000000000000000000000..95cf272878359073767764d7340b0546eb21f65c --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure1.c @@ -0,0 +1,30 @@ +// simple structure +// {p_x, p_y} are aliased + + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + int a; + int c; +} st_2_t; + + +int main () { + + st_1_t x = {0,1}; + st_2_t y = {3,4}; + + st_1_t * p_x = &x; + st_2_t * p_y = &y; + + + p_x->a = 3; + p_x = p_y; + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure2.c b/src/plugins/alias/tests/offsets/structure2.c new file mode 100644 index 0000000000000000000000000000000000000000..92ff3a41783f5e35b94622b1ebe1553946938e7a --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure2.c @@ -0,0 +1,26 @@ +// structure with initialisation and pointer +// no alias + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int c; +} st_2_t; + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_2_t y = {&x1,4}; + + y.s = &x2; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure3.c b/src/plugins/alias/tests/offsets/structure3.c new file mode 100644 index 0000000000000000000000000000000000000000..9582ccd3f86dfe6b9b186213836c29aee37a600f --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure3.c @@ -0,0 +1,39 @@ +// double structure with initialisation and pointer +// no alias + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int d; +} st_3_t; + + + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_2_t y1 = {&x1,3}; + st_2_t y2 = {&x2,4}; + st_3_t z = {&y1,5}; + + z.t = &y2; + y1.c = z.d; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure4.c b/src/plugins/alias/tests/offsets/structure4.c new file mode 100644 index 0000000000000000000000000000000000000000..c33bce757fec2a73fa1a55d075081c9955fa14a7 --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure4.c @@ -0,0 +1,41 @@ +// structure with malloc +// {z->s, y1} are aliased + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int d; +} st_3_t; + + + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_1_t *y1 = malloc(sizeof(st_1_t)); + st_2_t *z = malloc(sizeof(st_2_t)); + + y1 = &x1; + z->s = y1; + z->c = 6; + + return 0; +} diff --git a/src/plugins/alias/tests/offsets/structure5.c b/src/plugins/alias/tests/offsets/structure5.c new file mode 100644 index 0000000000000000000000000000000000000000..eeeefafd63d3518a65fbc88f0f96bb456104f94d --- /dev/null +++ b/src/plugins/alias/tests/offsets/structure5.c @@ -0,0 +1,48 @@ +// another structure, more complex +// {z->s, y1} are aliased +// {t->t, z} are aliased +// {z->c, t->d, a} are aliased + + +#include <stdlib.h> + +typedef struct +{ + int a; + int b; +} st_1_t; + +typedef struct +{ + struct struct_1_t* s; + int* c; +} st_2_t; + + +typedef struct +{ + struct struct_2_t* t; + int* d; +} st_3_t; + + + +int main () { + + st_1_t x1 = {0,1}; + st_1_t x2 = {1,2}; + st_1_t *y1 = malloc(sizeof(st_1_t)); + st_2_t *z = malloc(sizeof(st_2_t)); + st_3_t *t = malloc(sizeof(st_3_t)); + int* a = malloc(sizeof(int)); + + *a = 0; + y1 = &x1; + z->s = y1; + z->c = a; + t->t = z; + t->d = a; + + + return 0; +} diff --git a/src/plugins/alias/tests/ptests_config b/src/plugins/alias/tests/ptests_config new file mode 100644 index 0000000000000000000000000000000000000000..364f24e63e59237f7800393fbdf9829fc9330471 --- /dev/null +++ b/src/plugins/alias/tests/ptests_config @@ -0,0 +1 @@ +DEFAULT_SUITES=basic real_world offsets fixed_bugs diff --git a/src/plugins/alias/tests/real_world/example1.c b/src/plugins/alias/tests/real_world/example1.c new file mode 100644 index 0000000000000000000000000000000000000000..a3709a6736725db096563ff80de05329276ef3aa --- /dev/null +++ b/src/plugins/alias/tests/real_world/example1.c @@ -0,0 +1,108 @@ +// real world example +// {a->t1[0], b->t1[0]} are aliased +// {a->t2[0], b->t2[0]} are aliased +// {a->n1, b->n1} are aliased +// {a->n2, b->n2} are aliased + + +#include <stdlib.h> +#include <math.h> + +typedef struct { + double *t1[2]; + double *t2[2]; + int *n1; + int *n2; +} ty; + +void swap(int *n) +{ + if ((*n) == 1) { + (*n) = 0; + } + else { + (*n)++; + } +} + + +void *f1(ty *x) +{ + ty *tmp = x; + double *idata; + double *odata; + int idx; + + idata = (double *)malloc(10 * sizeof(double)); + + while (1) { + + idata = tmp->t2[*tmp->n2]; + + odata = tmp->t1[*tmp->n1]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 0.5*sin(idata[idx]); + } + swap(tmp->n1); + } + return (void *) NULL; +} + + +void *f2(ty *x) +{ + ty *tmp = x; + int idx; + double *idata; + double *odata; + + idata = (double*)malloc(10* sizeof(double)); + + while (1) { + + idata = tmp->t1[*tmp->n1]; + + odata = tmp->t2[*tmp->n2]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 3*idata[idx] + 1; + } + swap(tmp->n2); + } + + return (void *) NULL; +} + + +int main(void) +{ + ty *a; + ty *b; + + a = (ty *)malloc(sizeof(ty)); + b = (ty *)malloc(sizeof(ty)); + + int i; + for (i = 0; i < 2; i++) { + a->t1[i] = (double *)malloc(10 * sizeof(double)); + a->t2[i] = (double *)malloc(10 * sizeof(double)); + } + + a->n1 = (int *)malloc(sizeof(int)); + a->n2 = (int *)malloc(sizeof(int)); + *a->n1 = 1; + *a->n2 = 1; + + for (i = 0; i < 2; i++) { + b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; + } + b->n1 = a->n1; + b->n2 = a->n2; + + f1(a); + f2(b); + + return 0; +} diff --git a/src/plugins/alias/tests/real_world/example2.c b/src/plugins/alias/tests/real_world/example2.c new file mode 100644 index 0000000000000000000000000000000000000000..18e08504e7c44a69853a32bf94ed52404942a5ec --- /dev/null +++ b/src/plugins/alias/tests/real_world/example2.c @@ -0,0 +1,108 @@ +// real world example +// {a->t1[0], b->t1[0]} are aliased +// {a->t2[0], b->t2[0]} are aliased +// {a->n1, b->n1} are aliased +// {a->n2, b->n2} are aliased + + +#include <stdlib.h> +#include <math.h> + +typedef struct { + double *t1[2]; + double *t2[2]; + int *n1; + int *n2; +} ty; + +void swap(int *n) +{ + if ((*n) == 1) { + (*n) = 0; + } + else { + (*n)++; + } +} + + +void *f1(ty *x) +{ + ty *tmp = x; + double *idata; + double *odata; + int idx; + + idata = (double *)malloc(10 * sizeof(double)); + + for (int i = 0; i < 2; i++) { + + idata = tmp->t2[*tmp->n2]; + + odata = tmp->t1[*tmp->n1]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 0.5*sin(idata[idx]); + } + swap(tmp->n1); + } + return (void *) NULL; +} + + +void *f2(ty *x) +{ + ty *tmp = x; + int idx; + double *idata; + double *odata; + + idata = (double*)malloc(10* sizeof(double)); + + for (int i = 0; i < 2; i++) { + + idata = tmp->t1[*tmp->n1]; + + odata = tmp->t2[*tmp->n2]; + + for (idx = 0; idx < 10; idx++) { + odata[idx] = 3*idata[idx] + 1; + } + swap(tmp->n2); + } + + return (void *) NULL; +} + + +int main(void) +{ + ty *a; + ty *b; + + a = (ty *)malloc(sizeof(ty)); + b = (ty *)malloc(sizeof(ty)); + + int i; + for (i = 0; i < 2; i++) { + a->t1[i] = (double *)malloc(10 * sizeof(double)); + a->t2[i] = (double *)malloc(10 * sizeof(double)); + } + + a->n1 = (int *)malloc(sizeof(int)); + a->n2 = (int *)malloc(sizeof(int)); + *a->n1 = 1; + *a->n2 = 1; + + for (i = 0; i < 2; i++) { + b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; + } + b->n1 = a->n1; + b->n2 = a->n2; + + f1(a); + f2(b); + + return 0; +} diff --git a/src/plugins/alias/tests/real_world/function1_v2.c b/src/plugins/alias/tests/real_world/function1_v2.c new file mode 100644 index 0000000000000000000000000000000000000000..3187998b7574e374a2a14dfa89ff10f8f6342763 --- /dev/null +++ b/src/plugins/alias/tests/real_world/function1_v2.c @@ -0,0 +1,26 @@ +// function with no return +// {a, b} are aliased +// {c, d} are aliased +//#include <stdio.h> +#include <stdlib.h> + +void alias(int **x, int **y) { + *x = *y; +} + + +int main(void) +{ + int *a = malloc(sizeof(int)); + *a = 0; + int *b = malloc(sizeof(int));; + *b = 42; + + alias(&a,&b); + + *a = 7; + //printf("a = %d && b = %d\n",*a,*b); + + + return 0; +} diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.old b/src/plugins/alias/tests/real_world/oracle/example1.res.old new file mode 100644 index 0000000000000000000000000000000000000000..97708d154b7fc3fc196c5926743747fe2f6276d9 --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/example1.res.old @@ -0,0 +1,403 @@ +[kernel] Parsing example1.c (with preprocessing) +[alias] Parsing done +[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] In a function call, parameter (x <- *(idata + idx)) is ignored) +[alias] Warning: a function with no return is employed in an assignment +[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2) +[alias] In a function call, parameter (x <- *(idata + idx)) is ignored) +[alias] Warning: a function with no return is employed in an assignment +[alias] Skipping assignment *(odata + idx) = 0.5 * tmp_1 (BUG do_assignment 2) +[alias] Skipping assignment idata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Skipping assignment odata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] Warning: DEBUG return stmt of f1 not in table +[alias] Warning: Analysis is continuing but will not be sound +[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2) +[alias] Skipping assignment *(odata + idx) = (double)3 * *(idata + idx) + (double)1 (BUG do_assignment 2) +[alias] Skipping assignment idata = tmp->t1[*(tmp->n1)] (not implemented) +[alias] Skipping assignment odata = tmp->t2[*(tmp->n2)] (not implemented) +[alias] Warning: DEBUG return stmt of f2 not in table +[alias] Warning: Analysis is continuing but will not be sound +[alias] Skipping assignment a->t1[i] = malloc() (not implemented) +[alias] Skipping assignment a->t2[i] = malloc() (not implemented) +[alias] Skipping assignment a->t1[i] = malloc() (not implemented) +[alias] Skipping assignment a->t2[i] = malloc() (not implemented) +[alias] Skipping assignment a->n1 = malloc() (not implemented) +[alias] Skipping assignment a->n2 = malloc() (not implemented) +[alias] May-aliases at the end of function main: + <list of may-alias> + {b.n1; b; } are aliased + {b.n1; b.n2; b; } are aliased + {*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased + <end of list> +[alias] Functions done +Before statement b->t1[i] = a->t1[i]; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idx = 0; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement b->t2[i] = a->t2[i]; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement while (idx < 10) { + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; + idx ++; + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement if (*n == 1) *n = 0; else (*n) ++; : + <list of may-alias> +<end of list> + +Before statement i ++; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement if (*n == 1) *n = 0; else (*n) ++; : + <list of may-alias> +<end of list> + +Before statement b->n1 = a->n1; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement if (! (idx < 10)) break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement *n = 0; : + <list of may-alias> +<end of list> + +Before statement b->n2 = a->n2; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b; } are aliased +{b.n1; b; } are aliased +<end of list> + +Before statement break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement (*n) ++; : + <list of may-alias> +<end of list> + +Before statement f1(a); : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +<end of list> + +Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement f2(b); : + <list of may-alias> +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +<end of list> + +Before statement *(odata + idx) = (double)3 * *(idata + idx) + (double)1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement __retres = 0; : + <list of may-alias> +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +<end of list> + +Before statement idx ++; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement ty *tmp = x; : + <list of may-alias> +<end of list> + +Before statement swap(tmp->n2); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement return; : + <list of may-alias> +<end of list> + +Before statement while (1) { + idata = tmp->t2[*(tmp->n2)]; + odata = tmp->t1[*(tmp->n1)]; + idx = 0; + while (idx < 10) { + { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } + idx ++; + } + swap(tmp->n1); + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement idata = tmp->t2[*(tmp->n2)]; + odata = tmp->t1[*(tmp->n1)]; + idx = 0; + while (idx < 10) { + { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } + idx ++; + } + swap(tmp->n1); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a = (ty *)malloc(sizeof(ty)); : + <list of may-alias> +<end of list> + +Before statement idata = tmp->t2[*(tmp->n2)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement b = (ty *)malloc(sizeof(ty)); : + <list of may-alias> +<end of list> + +Before statement odata = tmp->t1[*(tmp->n1)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement i = 0; : + <list of may-alias> +<end of list> + +Before statement idx = 0; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement while (i < 2) { + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); + i ++; + } : + <list of may-alias> +<end of list> + +Before statement while (idx < 10) { + { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } + idx ++; + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement return __retres; : + <list of may-alias> +{b.n1; b; } are aliased +{b.n1; b.n2; b; } are aliased +{*a; *b.t1[i]; *b.t2[i]; *b.n1; *b.n2; *b; } are aliased +<end of list> + +Before statement if (! (i < 2)) break; : + <list of may-alias> +<end of list> + +Before statement if (! (idx < 10)) break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement break; : + <list of may-alias> +<end of list> + +Before statement break; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +<end of list> + +Before statement { + double tmp_1; + tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +<end of list> + +Before statement tmp_1 = sin(*(idata + idx)); + *(odata + idx) = 0.5 * tmp_1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +<end of list> + +Before statement tmp_1 = sin(*(idata + idx)); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement i ++; : + <list of may-alias> +<end of list> + +Before statement *(odata + idx) = 0.5 * tmp_1; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->n1 = (int *)malloc(sizeof(int)); : + <list of may-alias> +<end of list> + +Before statement idx ++; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement a->n2 = (int *)malloc(sizeof(int)); : + <list of may-alias> +<end of list> + +Before statement swap(tmp->n1); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement *(a->n1) = 1; : + <list of may-alias> +<end of list> + +Before statement *(a->n2) = 1; : + <list of may-alias> +<end of list> + +Before statement i = 0; : + <list of may-alias> +<end of list> + +Before statement ty *tmp = x; : + <list of may-alias> +<end of list> + +Before statement while (i < 2) { + b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; + i ++; + } : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idata = (double *)malloc((unsigned long)10 * sizeof(double)); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement while (1) { + idata = tmp->t1[*(tmp->n1)]; + odata = tmp->t2[*(tmp->n2)]; + idx = 0; + while (idx < 10) { + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; + idx ++; + } + swap(tmp->n2); + } : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement if (! (i < 2)) break; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idata = tmp->t1[*(tmp->n1)]; + odata = tmp->t2[*(tmp->n2)]; + idx = 0; + while (idx < 10) { + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; + idx ++; + } + swap(tmp->n2); : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement break; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement idata = tmp->t1[*(tmp->n1)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +Before statement b->t1[i] = a->t1[i]; + b->t2[i] = a->t2[i]; : + <list of may-alias> +{*a; *b.t1[i]; *b.t2[i]; } are aliased +<end of list> + +Before statement odata = tmp->t2[*(tmp->n2)]; : + <list of may-alias> +{x; tmp; } are aliased +<end of list> + +[alias] Analysis complete diff --git a/src/plugins/alias/tests/real_world/oracle/example1.res.oracle b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2184e66ef66ccd9e68cdee8db84944dbaa773d5f --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/example1.res.oracle @@ -0,0 +1,412 @@ +[kernel] Parsing example1.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: __fc_fpclassify +[alias] May-aliases at the end of function __fc_fpclassify: ⊥ +[alias] analysing function: __fc_fpclassifyf +[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥ +[alias] analysing function: __fc_infinity +[alias] May-aliases at the end of function __fc_infinity: ⊥ +[alias] analysing function: __fc_nan +[alias] May-aliases at the end of function __fc_nan: ⊥ +[alias] analysing function: __finite +[alias] May-aliases at the end of function __finite: ⊥ +[alias] analysing function: __finitef +[alias] May-aliases at the end of function __finitef: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: acos +[alias] May-aliases at the end of function acos: ⊥ +[alias] analysing function: acosf +[alias] May-aliases at the end of function acosf: ⊥ +[alias] analysing function: acosh +[alias] May-aliases at the end of function acosh: ⊥ +[alias] analysing function: acoshf +[alias] May-aliases at the end of function acoshf: ⊥ +[alias] analysing function: acoshl +[alias] May-aliases at the end of function acoshl: ⊥ +[alias] analysing function: acosl +[alias] May-aliases at the end of function acosl: ⊥ +[alias] analysing function: asin +[alias] May-aliases at the end of function asin: ⊥ +[alias] analysing function: asinf +[alias] May-aliases at the end of function asinf: ⊥ +[alias] analysing function: asinl +[alias] May-aliases at the end of function asinl: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atan +[alias] May-aliases at the end of function atan: ⊥ +[alias] analysing function: atan2 +[alias] May-aliases at the end of function atan2: ⊥ +[alias] analysing function: atan2f +[alias] May-aliases at the end of function atan2f: ⊥ +[alias] analysing function: atan2l +[alias] May-aliases at the end of function atan2l: ⊥ +[alias] analysing function: atanf +[alias] May-aliases at the end of function atanf: ⊥ +[alias] analysing function: atanl +[alias] May-aliases at the end of function atanl: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: ceil +[alias] May-aliases at the end of function ceil: ⊥ +[alias] analysing function: ceilf +[alias] May-aliases at the end of function ceilf: ⊥ +[alias] analysing function: ceill +[alias] May-aliases at the end of function ceill: ⊥ +[alias] analysing function: cos +[alias] May-aliases at the end of function cos: ⊥ +[alias] analysing function: cosf +[alias] May-aliases at the end of function cosf: ⊥ +[alias] analysing function: cosl +[alias] May-aliases at the end of function cosl: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: exp +[alias] May-aliases at the end of function exp: ⊥ +[alias] analysing function: expf +[alias] May-aliases at the end of function expf: ⊥ +[alias] analysing function: f1 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: tmp_1 = sin(*(idata + idx)); +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias:undefined:fn] example1.c:45: Warning: function sin has no definition +[alias] May-aliases after instruction tmp_1 = sin(*(idata + idx)); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1; +[alias] May-aliases after instruction *(odata + idx) = 0.5 * tmp_1; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: swap(tmp->n1); +[alias] analysing function: swap +[alias] analysing instruction: *n = 0; +[alias] May-aliases after instruction *n = 0; are <none> +[alias] analysing instruction: (*n) ++; +[alias] May-aliases after instruction (*n) ++; are <none> +[alias] May-aliases at the end of function swap: <none> +[alias] May-aliases after instruction swap(tmp->n1); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias:no-return] example1.c:29: Warning: + function f1 does not return; analysis may be unsound +[alias] May-aliases at the end of function f1: <none> +[alias] analysing function: f2 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; +[alias] May-aliases after instruction + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: swap(tmp->n2); +[alias] May-aliases after instruction swap(tmp->n2); are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias:no-return] example1.c:53: Warning: + function f2 does not return; analysis may be unsound +[alias] May-aliases at the end of function f2: <none> +[alias] analysing function: fabs +[alias] May-aliases at the end of function fabs: ⊥ +[alias] analysing function: fabsf +[alias] May-aliases at the end of function fabsf: ⊥ +[alias] analysing function: fabsl +[alias] May-aliases at the end of function fabsl: ⊥ +[alias] analysing function: floor +[alias] May-aliases at the end of function floor: ⊥ +[alias] analysing function: floorf +[alias] May-aliases at the end of function floorf: ⊥ +[alias] analysing function: floorl +[alias] May-aliases at the end of function floorl: ⊥ +[alias] analysing function: fmod +[alias] May-aliases at the end of function fmod: ⊥ +[alias] analysing function: fmodf +[alias] May-aliases at the end of function fmodf: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: frexp +[alias] May-aliases at the end of function frexp: ⊥ +[alias] analysing function: frexpf +[alias] May-aliases at the end of function frexpf: ⊥ +[alias] analysing function: frexpl +[alias] May-aliases at the end of function frexpl: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldexp +[alias] May-aliases at the end of function ldexp: ⊥ +[alias] analysing function: ldexpf +[alias] May-aliases at the end of function ldexpf: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: log +[alias] May-aliases at the end of function log: ⊥ +[alias] analysing function: log10 +[alias] May-aliases at the end of function log10: ⊥ +[alias] analysing function: log10f +[alias] May-aliases at the end of function log10f: ⊥ +[alias] analysing function: log10l +[alias] May-aliases at the end of function log10l: ⊥ +[alias] analysing function: log2 +[alias] May-aliases at the end of function log2: ⊥ +[alias] analysing function: log2f +[alias] May-aliases at the end of function log2f: ⊥ +[alias] analysing function: log2l +[alias] May-aliases at the end of function log2l: ⊥ +[alias] analysing function: logf +[alias] May-aliases at the end of function logf: ⊥ +[alias] analysing function: logl +[alias] May-aliases at the end of function logl: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: a = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction a = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: b = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction b = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n1 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n2 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: *(a->n1) = 1; +[alias] May-aliases after instruction *(a->n1) = 1; are <none> +[alias] analysing instruction: *(a->n2) = 1; +[alias] May-aliases after instruction *(a->n2) = 1; are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->n1 = a->n1; +[alias] May-aliases after instruction b->n1 = a->n1; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} +[alias] analysing instruction: b->n2 = a->n2; +[alias] May-aliases after instruction b->n2 = a->n2; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f1(a); +[alias] May-aliases after instruction f1(a); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f2(b); +[alias] May-aliases after instruction f2(b); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] May-aliases at the end of function main: + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nan +[alias] May-aliases at the end of function nan: ⊥ +[alias] analysing function: nanf +[alias] May-aliases at the end of function nanf: ⊥ +[alias] analysing function: nanl +[alias] May-aliases at the end of function nanl: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: pow +[alias] May-aliases at the end of function pow: ⊥ +[alias] analysing function: powf +[alias] May-aliases at the end of function powf: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: round +[alias] May-aliases at the end of function round: ⊥ +[alias] analysing function: roundf +[alias] May-aliases at the end of function roundf: ⊥ +[alias] analysing function: roundl +[alias] May-aliases at the end of function roundl: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias] analysing function: sinf +[alias] May-aliases at the end of function sinf: ⊥ +[alias] analysing function: sinl +[alias] May-aliases at the end of function sinl: ⊥ +[alias] analysing function: sqrt +[alias] May-aliases at the end of function sqrt: ⊥ +[alias] analysing function: sqrtf +[alias] May-aliases at the end of function sqrtf: ⊥ +[alias] analysing function: sqrtl +[alias] May-aliases at the end of function sqrtl: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: swap +[alias] May-aliases at the end of function swap: <none> +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: tan +[alias] May-aliases at the end of function tan: ⊥ +[alias] analysing function: tanf +[alias] May-aliases at the end of function tanf: ⊥ +[alias] analysing function: tanl +[alias] May-aliases at the end of function tanl: ⊥ +[alias] analysing function: trunc +[alias] May-aliases at the end of function trunc: ⊥ +[alias] analysing function: truncf +[alias] May-aliases at the end of function truncf: ⊥ +[alias] analysing function: truncl +[alias] May-aliases at the end of function truncl: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/real_world/oracle/example2.res.oracle b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..21f8829b4dc8c670f933cedca6281dd899cd434f --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/example2.res.oracle @@ -0,0 +1,426 @@ +[kernel] Parsing example2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: __fc_fpclassify +[alias] May-aliases at the end of function __fc_fpclassify: ⊥ +[alias] analysing function: __fc_fpclassifyf +[alias] May-aliases at the end of function __fc_fpclassifyf: ⊥ +[alias] analysing function: __fc_infinity +[alias] May-aliases at the end of function __fc_infinity: ⊥ +[alias] analysing function: __fc_nan +[alias] May-aliases at the end of function __fc_nan: ⊥ +[alias] analysing function: __finite +[alias] May-aliases at the end of function __finite: ⊥ +[alias] analysing function: __finitef +[alias] May-aliases at the end of function __finitef: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: acos +[alias] May-aliases at the end of function acos: ⊥ +[alias] analysing function: acosf +[alias] May-aliases at the end of function acosf: ⊥ +[alias] analysing function: acosh +[alias] May-aliases at the end of function acosh: ⊥ +[alias] analysing function: acoshf +[alias] May-aliases at the end of function acoshf: ⊥ +[alias] analysing function: acoshl +[alias] May-aliases at the end of function acoshl: ⊥ +[alias] analysing function: acosl +[alias] May-aliases at the end of function acosl: ⊥ +[alias] analysing function: asin +[alias] May-aliases at the end of function asin: ⊥ +[alias] analysing function: asinf +[alias] May-aliases at the end of function asinf: ⊥ +[alias] analysing function: asinl +[alias] May-aliases at the end of function asinl: ⊥ +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atan +[alias] May-aliases at the end of function atan: ⊥ +[alias] analysing function: atan2 +[alias] May-aliases at the end of function atan2: ⊥ +[alias] analysing function: atan2f +[alias] May-aliases at the end of function atan2f: ⊥ +[alias] analysing function: atan2l +[alias] May-aliases at the end of function atan2l: ⊥ +[alias] analysing function: atanf +[alias] May-aliases at the end of function atanf: ⊥ +[alias] analysing function: atanl +[alias] May-aliases at the end of function atanl: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: ceil +[alias] May-aliases at the end of function ceil: ⊥ +[alias] analysing function: ceilf +[alias] May-aliases at the end of function ceilf: ⊥ +[alias] analysing function: ceill +[alias] May-aliases at the end of function ceill: ⊥ +[alias] analysing function: cos +[alias] May-aliases at the end of function cos: ⊥ +[alias] analysing function: cosf +[alias] May-aliases at the end of function cosf: ⊥ +[alias] analysing function: cosl +[alias] May-aliases at the end of function cosl: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: exp +[alias] May-aliases at the end of function exp: ⊥ +[alias] analysing function: expf +[alias] May-aliases at the end of function expf: ⊥ +[alias] analysing function: f1 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are {x, tmp} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: tmp_1 = sin(*(idata + idx)); +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias:undefined:fn] example2.c:45: Warning: function sin has no definition +[alias] May-aliases after instruction tmp_1 = sin(*(idata + idx)); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: *(odata + idx) = 0.5 * tmp_1; +[alias] May-aliases after instruction *(odata + idx) = 0.5 * tmp_1; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: swap(tmp->n1); +[alias] analysing function: swap +[alias] analysing instruction: *n = 0; +[alias] May-aliases after instruction *n = 0; are <none> +[alias] analysing instruction: (*n) ++; +[alias] May-aliases after instruction (*n) ++; are <none> +[alias] May-aliases at the end of function swap: <none> +[alias] May-aliases after instruction swap(tmp->n1); are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: idata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction idata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: odata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction odata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing instruction: __retres = (void *)0; +[alias] May-aliases after instruction __retres = (void *)0; are + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] May-aliases at the end of function f1: + {x, tmp} {tmp->t2[0], idata} {tmp->t1[0], odata} +[alias] analysing function: f2 +[alias] analysing instruction: ty *tmp = x; +[alias] May-aliases after instruction ty *tmp = x; are {x, tmp} +[alias] analysing instruction: + idata = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + idata = (double *)malloc((unsigned long)10 * sizeof(double)); are {x, tmp} +[alias] analysing instruction: int i = 0; +[alias] May-aliases after instruction int i = 0; are {x, tmp} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx = 0; +[alias] May-aliases after instruction idx = 0; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; +[alias] May-aliases after instruction + *(odata + idx) = (double)3 * *(idata + idx) + (double)1; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idx ++; +[alias] May-aliases after instruction idx ++; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: swap(tmp->n2); +[alias] May-aliases after instruction swap(tmp->n2); are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: idata = tmp->t1[*(tmp->n1)]; +[alias] May-aliases after instruction idata = tmp->t1[*(tmp->n1)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: odata = tmp->t2[*(tmp->n2)]; +[alias] May-aliases after instruction odata = tmp->t2[*(tmp->n2)]; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing instruction: __retres = (void *)0; +[alias] May-aliases after instruction __retres = (void *)0; are + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] May-aliases at the end of function f2: + {x, tmp} {tmp->t1[0], idata} {tmp->t2[0], odata} +[alias] analysing function: fabs +[alias] May-aliases at the end of function fabs: ⊥ +[alias] analysing function: fabsf +[alias] May-aliases at the end of function fabsf: ⊥ +[alias] analysing function: fabsl +[alias] May-aliases at the end of function fabsl: ⊥ +[alias] analysing function: floor +[alias] May-aliases at the end of function floor: ⊥ +[alias] analysing function: floorf +[alias] May-aliases at the end of function floorf: ⊥ +[alias] analysing function: floorl +[alias] May-aliases at the end of function floorl: ⊥ +[alias] analysing function: fmod +[alias] May-aliases at the end of function fmod: ⊥ +[alias] analysing function: fmodf +[alias] May-aliases at the end of function fmodf: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: frexp +[alias] May-aliases at the end of function frexp: ⊥ +[alias] analysing function: frexpf +[alias] May-aliases at the end of function frexpf: ⊥ +[alias] analysing function: frexpl +[alias] May-aliases at the end of function frexpl: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldexp +[alias] May-aliases at the end of function ldexp: ⊥ +[alias] analysing function: ldexpf +[alias] May-aliases at the end of function ldexpf: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: log +[alias] May-aliases at the end of function log: ⊥ +[alias] analysing function: log10 +[alias] May-aliases at the end of function log10: ⊥ +[alias] analysing function: log10f +[alias] May-aliases at the end of function log10f: ⊥ +[alias] analysing function: log10l +[alias] May-aliases at the end of function log10l: ⊥ +[alias] analysing function: log2 +[alias] May-aliases at the end of function log2: ⊥ +[alias] analysing function: log2f +[alias] May-aliases at the end of function log2f: ⊥ +[alias] analysing function: log2l +[alias] May-aliases at the end of function log2l: ⊥ +[alias] analysing function: logf +[alias] May-aliases at the end of function logf: ⊥ +[alias] analysing function: logl +[alias] May-aliases at the end of function logl: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: a = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction a = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: b = (ty *)malloc(sizeof(ty)); +[alias] May-aliases after instruction b = (ty *)malloc(sizeof(ty)); are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are <none> +[alias] analysing instruction: + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t1[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); +[alias] May-aliases after instruction + a->t2[i] = (double *)malloc((unsigned long)10 * sizeof(double)); are + <none> +[alias] analysing instruction: a->n1 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n1 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: a->n2 = (int *)malloc(sizeof(int)); +[alias] May-aliases after instruction a->n2 = (int *)malloc(sizeof(int)); are + <none> +[alias] analysing instruction: *(a->n1) = 1; +[alias] May-aliases after instruction *(a->n1) = 1; are <none> +[alias] analysing instruction: *(a->n2) = 1; +[alias] May-aliases after instruction *(a->n2) = 1; are <none> +[alias] analysing instruction: i = 0; +[alias] May-aliases after instruction i = 0; are <none> +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: i ++; +[alias] May-aliases after instruction i ++; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t1[i] = a->t1[i]; +[alias] May-aliases after instruction b->t1[i] = a->t1[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->t2[i] = a->t2[i]; +[alias] May-aliases after instruction b->t2[i] = a->t2[i]; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} +[alias] analysing instruction: b->n1 = a->n1; +[alias] May-aliases after instruction b->n1 = a->n1; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} +[alias] analysing instruction: b->n2 = a->n2; +[alias] May-aliases after instruction b->n2 = a->n2; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f1(a); +[alias] May-aliases after instruction f1(a); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: f2(b); +[alias] May-aliases after instruction f2(b); are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] May-aliases at the end of function main: + {a->t1[0], b->t1[0]} {a->t2[0], b->t2[0]} {a->n1, b->n1} {a->n2, b->n2} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nan +[alias] May-aliases at the end of function nan: ⊥ +[alias] analysing function: nanf +[alias] May-aliases at the end of function nanf: ⊥ +[alias] analysing function: nanl +[alias] May-aliases at the end of function nanl: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: pow +[alias] May-aliases at the end of function pow: ⊥ +[alias] analysing function: powf +[alias] May-aliases at the end of function powf: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: round +[alias] May-aliases at the end of function round: ⊥ +[alias] analysing function: roundf +[alias] May-aliases at the end of function roundf: ⊥ +[alias] analysing function: roundl +[alias] May-aliases at the end of function roundl: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: sin +[alias] May-aliases at the end of function sin: ⊥ +[alias] analysing function: sinf +[alias] May-aliases at the end of function sinf: ⊥ +[alias] analysing function: sinl +[alias] May-aliases at the end of function sinl: ⊥ +[alias] analysing function: sqrt +[alias] May-aliases at the end of function sqrt: ⊥ +[alias] analysing function: sqrtf +[alias] May-aliases at the end of function sqrtf: ⊥ +[alias] analysing function: sqrtl +[alias] May-aliases at the end of function sqrtl: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: swap +[alias] May-aliases at the end of function swap: <none> +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: tan +[alias] May-aliases at the end of function tan: ⊥ +[alias] analysing function: tanf +[alias] May-aliases at the end of function tanf: ⊥ +[alias] analysing function: tanl +[alias] May-aliases at the end of function tanl: ⊥ +[alias] analysing function: trunc +[alias] May-aliases at the end of function trunc: ⊥ +[alias] analysing function: truncf +[alias] May-aliases at the end of function truncf: ⊥ +[alias] analysing function: truncl +[alias] May-aliases at the end of function truncl: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..029211f36e3c5e5788b1656bc41836f8e6628d8b --- /dev/null +++ b/src/plugins/alias/tests/real_world/oracle/function1_v2.res.oracle @@ -0,0 +1,133 @@ +[kernel] Parsing function1_v2.c (with preprocessing) +[alias] analysing function: _Exit +[alias] May-aliases at the end of function _Exit: ⊥ +[alias] analysing function: abort +[alias] May-aliases at the end of function abort: ⊥ +[alias] analysing function: abs +[alias] May-aliases at the end of function abs: ⊥ +[alias] analysing function: alias +[alias] analysing instruction: *x = *y; +[alias] May-aliases after instruction *x = *y; are {x, y} +[alias] May-aliases at the end of function alias: {x, y} +[alias] analysing function: at_quick_exit +[alias] May-aliases at the end of function at_quick_exit: ⊥ +[alias] analysing function: atexit +[alias] May-aliases at the end of function atexit: ⊥ +[alias] analysing function: atof +[alias] May-aliases at the end of function atof: ⊥ +[alias] analysing function: atoi +[alias] May-aliases at the end of function atoi: ⊥ +[alias] analysing function: atol +[alias] May-aliases at the end of function atol: ⊥ +[alias] analysing function: atoll +[alias] May-aliases at the end of function atoll: ⊥ +[alias] analysing function: bsearch +[alias] May-aliases at the end of function bsearch: ⊥ +[alias] analysing function: calloc +[alias] May-aliases at the end of function calloc: ⊥ +[alias] analysing function: div +[alias] May-aliases at the end of function div: ⊥ +[alias] analysing function: drand48 +[alias] May-aliases at the end of function drand48: ⊥ +[alias] analysing function: erand48 +[alias] May-aliases at the end of function erand48: ⊥ +[alias] analysing function: exit +[alias] May-aliases at the end of function exit: ⊥ +[alias] analysing function: free +[alias] May-aliases at the end of function free: ⊥ +[alias] analysing function: getenv +[alias] May-aliases at the end of function getenv: ⊥ +[alias] analysing function: jrand48 +[alias] May-aliases at the end of function jrand48: ⊥ +[alias] analysing function: labs +[alias] May-aliases at the end of function labs: ⊥ +[alias] analysing function: lcong48 +[alias] May-aliases at the end of function lcong48: ⊥ +[alias] analysing function: ldiv +[alias] May-aliases at the end of function ldiv: ⊥ +[alias] analysing function: llabs +[alias] May-aliases at the end of function llabs: ⊥ +[alias] analysing function: lldiv +[alias] May-aliases at the end of function lldiv: ⊥ +[alias] analysing function: lrand48 +[alias] May-aliases at the end of function lrand48: ⊥ +[alias] analysing function: main +[alias] analysing instruction: int *a = malloc(sizeof(int)); +[alias] May-aliases after instruction int *a = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *a = 0; +[alias] May-aliases after instruction *a = 0; are <none> +[alias] analysing instruction: int *b = malloc(sizeof(int)); +[alias] May-aliases after instruction int *b = malloc(sizeof(int)); are <none> +[alias] analysing instruction: *b = 42; +[alias] May-aliases after instruction *b = 42; are <none> +[alias] analysing instruction: alias(& a,& b); +[alias] May-aliases after instruction alias(& a,& b); are {a, b} +[alias] analysing instruction: *a = 7; +[alias] May-aliases after instruction *a = 7; are {a, b} +[alias] analysing instruction: __retres = 0; +[alias] May-aliases after instruction __retres = 0; are {a, b} +[alias] May-aliases at the end of function main: {a, b} +[alias] analysing function: malloc +[alias] May-aliases at the end of function malloc: ⊥ +[alias] analysing function: mblen +[alias] May-aliases at the end of function mblen: ⊥ +[alias] analysing function: mbstowcs +[alias] May-aliases at the end of function mbstowcs: ⊥ +[alias] analysing function: mbtowc +[alias] May-aliases at the end of function mbtowc: ⊥ +[alias] analysing function: mkstemp +[alias] May-aliases at the end of function mkstemp: ⊥ +[alias] analysing function: mkstemps +[alias] May-aliases at the end of function mkstemps: ⊥ +[alias] analysing function: mrand48 +[alias] May-aliases at the end of function mrand48: ⊥ +[alias] analysing function: nrand48 +[alias] May-aliases at the end of function nrand48: ⊥ +[alias] analysing function: posix_memalign +[alias] May-aliases at the end of function posix_memalign: ⊥ +[alias] analysing function: putenv +[alias] May-aliases at the end of function putenv: ⊥ +[alias] analysing function: qsort +[alias] May-aliases at the end of function qsort: ⊥ +[alias] analysing function: quick_exit +[alias] May-aliases at the end of function quick_exit: ⊥ +[alias] analysing function: rand +[alias] May-aliases at the end of function rand: ⊥ +[alias] analysing function: random +[alias] May-aliases at the end of function random: ⊥ +[alias] analysing function: realloc +[alias] May-aliases at the end of function realloc: ⊥ +[alias] analysing function: reallocarray +[alias] May-aliases at the end of function reallocarray: ⊥ +[alias] analysing function: seed48 +[alias] May-aliases at the end of function seed48: ⊥ +[alias] analysing function: setenv +[alias] May-aliases at the end of function setenv: ⊥ +[alias] analysing function: srand +[alias] May-aliases at the end of function srand: ⊥ +[alias] analysing function: srand48 +[alias] May-aliases at the end of function srand48: ⊥ +[alias] analysing function: srandom +[alias] May-aliases at the end of function srandom: ⊥ +[alias] analysing function: strtod +[alias] May-aliases at the end of function strtod: ⊥ +[alias] analysing function: strtof +[alias] May-aliases at the end of function strtof: ⊥ +[alias] analysing function: strtol +[alias] May-aliases at the end of function strtol: ⊥ +[alias] analysing function: strtold +[alias] May-aliases at the end of function strtold: ⊥ +[alias] analysing function: strtoll +[alias] May-aliases at the end of function strtoll: ⊥ +[alias] analysing function: strtoul +[alias] May-aliases at the end of function strtoul: ⊥ +[alias] analysing function: strtoull +[alias] May-aliases at the end of function strtoull: ⊥ +[alias] analysing function: system +[alias] May-aliases at the end of function system: ⊥ +[alias] analysing function: unsetenv +[alias] May-aliases at the end of function unsetenv: ⊥ +[alias] analysing function: wcstombs +[alias] May-aliases at the end of function wcstombs: ⊥ +[alias] analysing function: wctomb +[alias] May-aliases at the end of function wctomb: ⊥ diff --git a/src/plugins/alias/tests/test_config b/src/plugins/alias/tests/test_config new file mode 100644 index 0000000000000000000000000000000000000000..e14c0a6d24720b60c9a29eb36a4bb4cd432e5b55 --- /dev/null +++ b/src/plugins/alias/tests/test_config @@ -0,0 +1,2 @@ +PLUGIN: alias +OPT: -alias -alias-verbose 3 diff --git a/src/plugins/alias/tests/unsupported/asm.c b/src/plugins/alias/tests/unsupported/asm.c new file mode 100644 index 0000000000000000000000000000000000000000..ba2e80cb752079eb603e6a82baf938ea40e72804 --- /dev/null +++ b/src/plugins/alias/tests/unsupported/asm.c @@ -0,0 +1,4 @@ +int main () { + asm("movq %0, %%rsi"); + return 0; +} diff --git a/src/plugins/alias/tests/unsupported/explicit_pointer.c b/src/plugins/alias/tests/unsupported/explicit_pointer.c new file mode 100644 index 0000000000000000000000000000000000000000..a0b5e8f2c516d9f042cb31a6870bf803430a770c --- /dev/null +++ b/src/plugins/alias/tests/unsupported/explicit_pointer.c @@ -0,0 +1,3 @@ +int main () { + return *((int*)1); +} diff --git a/src/plugins/alias/tests/unsupported/pointer_call.c b/src/plugins/alias/tests/unsupported/pointer_call.c new file mode 100644 index 0000000000000000000000000000000000000000..448ec0f752f68628673aafccdb70969d51f5a381 --- /dev/null +++ b/src/plugins/alias/tests/unsupported/pointer_call.c @@ -0,0 +1,8 @@ +int f () { + return 0; +} + +int main () { + int (*p)() = &f; + return ((*p)()); +} diff --git a/src/plugins/aorai/aorai_utils.ml b/src/plugins/aorai/aorai_utils.ml index 573db999ec22e60c90ab492d18531f505abb1695..23685c5dde7f246d2bc7d5a4e0e9a82308f19d3d 100644 --- a/src/plugins/aorai/aorai_utils.ml +++ b/src/plugins/aorai/aorai_utils.ml @@ -399,8 +399,14 @@ let rec term_to_exp t res = | TConst (LWStr l) -> new_exp ~loc (Const (CWStr l)) | TConst (LChr c) -> new_exp ~loc (Const (CChr c)) | TConst (LReal l_real) -> - (* r_nearest is by definition in double precision. *) - new_exp ~loc (Const (CReal (l_real.r_nearest, FDouble, None))) + let fk,_ = Floating_point.parse l_real.r_literal in + let cst = + if Cil.isExactFloat fk l_real then + (CReal (l_real.r_nearest, fk, Some l_real.r_literal)) + else (* fallback to double, r_nearest being in that format anyways *) + (CReal (l_real.r_nearest, FDouble, None)) + in + new_exp ~loc (Const cst) | TConst (LEnum e) -> new_exp ~loc (Const (CEnum e)) | TLval tlval -> new_exp ~loc (Lval (tlval_to_lval tlval res)) | TSizeOf ty -> new_exp ~loc (SizeOf ty) @@ -413,6 +419,14 @@ let rec term_to_exp t res = | TBinOp (binop, t1, t2)-> new_exp ~loc (BinOp(binop, term_to_exp t1 res, term_to_exp t2 res, Cil.intType)) + | TCastE(ty, {term_node = TConst(LReal lreal)}) when Cil.isFloatingType ty -> + (match Cil.unrollType ty with + | TFloat(fk,_) -> + new_exp ~loc + (Const (CReal (lreal.r_nearest,fk,Some lreal.r_literal))) + | _ -> + Aorai_option.fatal + "A floating-point type was expected, got %a." Printer.pp_typ ty) | TCastE (ty, t) -> new_exp ~loc (CastE (ty, term_to_exp t res)) | TAddrOf tlval -> new_exp ~loc (AddrOf (tlval_to_lval tlval res)) | TStartOf tlval -> new_exp ~loc (StartOf (tlval_to_lval tlval res)) @@ -691,7 +705,7 @@ let mk_gvar ?init ~ty name = let vi = try let ty' = typeAddAttributes [Attr ("ghost", [])] ty in - let vi = Globals.Vars.find_from_astinfo name VGlobal in + let vi = Globals.Vars.find_from_astinfo name Global in if not (Cil_datatype.Typ.equal vi.vtype ty') then Aorai_option.abort "Global %s is declared with type %a instead of %a" name Cil_printer.pp_typ vi.vtype Cil_printer.pp_typ ty'; @@ -1092,7 +1106,8 @@ let make_enum_states () = (id, item)) state_list in - set_enum mapping + set_enum mapping; + enum let getInitialState () = let loc = Cil_datatype.Location.unknown in @@ -1107,7 +1122,11 @@ let initGlobals root complete = mk_global_comment "//* "; mk_global_comment "//* "; mk_global_comment "//* Some constants"; - if Aorai_option.Deterministic.get () then make_enum_states (); + let states_typ = + if Aorai_option.Deterministic.get () + then Some (TEnum (make_enum_states (), [])) + else None + in (* non deterministic mode uses one variable for each possible state *) mk_global_c_enum_type listOp @@ -1121,7 +1140,7 @@ let initGlobals root complete = mk_global_comment "//* "; mk_global_comment "//* States and Trans Variables"; if Aorai_option.Deterministic.get () then begin - mk_gvar_scalar ~init:(getInitialState()) curState; + mk_gvar_scalar ?ty:states_typ ~init:(getInitialState()) curState; let init = getInitialState() (* TODO a distinct initial value for history *) and history = Data_for_aorai.whole_history () in List.iter (fun name -> mk_gvar_scalar ~init name) history diff --git a/src/plugins/aorai/aorai_utils.mli b/src/plugins/aorai/aorai_utils.mli index 56342ff89887091c242b6916b0c9a94f411640a0..bdbec9e51989210ea99a9a93f866795f3f0feea4 100644 --- a/src/plugins/aorai/aorai_utils.mli +++ b/src/plugins/aorai/aorai_utils.mli @@ -192,8 +192,6 @@ val mk_offseted_array_states_as_enum : (usually a fresh quantified variable). *) val mk_term_from_vi : Cil_types.varinfo -> Cil_types.term -val make_enum_states: unit -> unit - (* Local Variables: compile-command: "make -C ../../.." diff --git a/src/plugins/aorai/data_for_aorai.ml b/src/plugins/aorai/data_for_aorai.ml index 946814ea430bd373bd35fd4c41f79f64985de108..919b0cc253acadb481fc44a9495fe281ec351663 100644 --- a/src/plugins/aorai/data_for_aorai.ml +++ b/src/plugins/aorai/data_for_aorai.ml @@ -258,7 +258,7 @@ let getNumberOfStates () = let is_c_global name = - try ignore (Globals.Vars.find_from_astinfo name VGlobal); true + try ignore (Globals.Vars.find_from_astinfo name Global); true with Not_found -> try ignore (Globals.Functions.find_by_name name); true with Not_found -> false @@ -580,11 +580,11 @@ let memo_aux_variable tr counter used_prms vi = let check_one top info counter s = match info with | ECall (kf,used_prms,tr) -> - (try - let vi = Globals.Vars.find_from_astinfo s (VFormal kf) in - if top then Some (Logic_const.tvar (Cil.cvar_to_lvar vi)) - else Some (memo_aux_variable tr counter used_prms vi) - with Not_found -> None) + Globals.Syntactic_search.find_in_scope ~strict:true s (Formal kf) |> + (Fun.flip Option.bind + (fun vi -> + if top then Some (Logic_const.tvar (Cil.cvar_to_lvar vi)) + else Some (memo_aux_variable tr counter used_prms vi))) | EReturn kf when top && ( Datatype.String.equal s "return" || Datatype.String.equal s "\\result") -> let rt = Kernel_function.get_return_type kf in @@ -619,11 +619,11 @@ let find_in_env env counter s = None -> () | Some lv -> raise (M.Found lv)) stack; - let vi = Globals.Vars.find_from_astinfo s VGlobal in - Logic_const.tvar (Cil.cvar_to_lvar vi) + (match Globals.Syntactic_search.find_in_scope s Program with + | Some vi -> Logic_const.tvar (Cil.cvar_to_lvar vi) + | None -> Aorai_option.abort "Unknown variable %s" s) with - M.Found lv -> lv - | Not_found -> Aorai_option.abort "Unknown variable %s" s) + M.Found lv -> lv) let find_prm_in_env env ?tr counter f x = let kf = @@ -669,9 +669,11 @@ let find_prm_in_env env ?tr counter f x = (TCall (kf,None)) in let vi = - try Globals.Vars.find_from_astinfo x (VFormal kf) - with Not_found -> - Aorai_option.abort "Function %s has no parameter %s" f x + match + Globals.Syntactic_search.find_in_scope ~strict:true x (Formal kf) + with + | Some vi -> vi + | None -> Aorai_option.abort "Function %s has no parameter %s" f x in (* By definition, we are at the call event: no need to store it in an aux variable or array here. @@ -908,11 +910,15 @@ let type_expr metaenv env ?tr ?current e = let type_cond needs_pebble metaenv env tr cond = let current = if needs_pebble then Some tr.stop else None in + let loc = Cil_datatype.Location.unknown in let rec aux pos env = function | PRel(rel,e1,e2) -> let env, e1, c1 = type_expr metaenv env ~tr ?current e1 in let env, e2, c2 = type_expr metaenv env ~tr ?current e2 in + let rt = LTyping.conditional_conversion loc (Some rel) e1 e2 in + let e1 = LTyping.mk_cast e1 rt in + let e2 = LTyping.mk_cast e2 rt in let call_cond = if pos then tand c1 c2 else tor (tnot c1) (tnot c2) in let rel = TRel(Logic_typing.type_rel rel,e1,e2) in let cond = if pos then tand call_cond rel else tor call_cond rel in diff --git a/src/plugins/aorai/tests/Aorai_test.ml b/src/plugins/aorai/tests/Aorai_test.ml index c151f0839ac55b440e2113a5ee07d7b3aa39a2dd..5cd54943e86d5589f36fa80cd8d86f13d30b4266 100644 --- a/src/plugins/aorai/tests/Aorai_test.ml +++ b/src/plugins/aorai/tests/Aorai_test.ml @@ -121,8 +121,10 @@ let extend () = if InternalWpShare.is_set() then Wp.Wp_parameters.Share.set (InternalWpShare.get()); Wp.Wp_parameters.Let.off(); - Wp.Wp_parameters.Split.on(); + Wp.Wp_parameters.SplitBranch.on(); + Wp.Wp_parameters.SplitConj.on(); Wp.Wp_parameters.SplitMax.set 32; + Wp.Wp_parameters.Model.As_string.set "+real"; if not (Wp.Wp_parameters.Verbose.is_set()) then Wp.Wp_parameters.Verbose.set 0; Globals.Functions.iter check_auto_func; diff --git a/src/plugins/aorai/tests/ya/floats.i b/src/plugins/aorai/tests/ya/floats.i new file mode 100644 index 0000000000000000000000000000000000000000..84879fa708d3368a90685b68d1fb5bbcba28dfd1 --- /dev/null +++ b/src/plugins/aorai/tests/ya/floats.i @@ -0,0 +1,21 @@ +/* run.config* + STDOPT: -aorai-automata %{dep:@PTEST_DIR@/@PTEST_NAME@.ya} -then-last -eva +*/ + +//@ assigns \result \from x, n; +float square_root_aux(float x, float n) { + float y = (x + n / x) / 2.0f; + if (x - y > 0.001) + return y; + else + return square_root_aux(y, n); +} + +float square_root(float n) { + return square_root_aux(1.0, n); +} + +void main(void) +{ + float r = square_root(2.0f); +} diff --git a/src/plugins/aorai/tests/ya/floats.ya b/src/plugins/aorai/tests/ya/floats.ya new file mode 100644 index 0000000000000000000000000000000000000000..241b8126042ef68f60fc118cab80b824102e68a5 --- /dev/null +++ b/src/plugins/aorai/tests/ya/floats.ya @@ -0,0 +1,16 @@ +%init : I; +%deterministic; + +I: { CALL(main) } -> A; + +A: { CALL(square_root) } -> B; + +B: + { square_root_aux().x >= 1.0f && square_root_aux().x <= square_root_aux().n } -> B +| { RETURN(square_root_aux) } -> B +| { RETURN(square_root) } -> C +; + +C: { RETURN(main) } -> E; + +E: -> E; diff --git a/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle b/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle index e8f31d7d12c410b9fe704537bb36d02eeb706b05..37b9968d9332e932d18bd4d961fe0c8606140abc 100644 --- a/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/aorai_ptr_field.res.oracle @@ -44,6 +44,7 @@ enum aorai_OpStatusList { int S0_tmp; int S1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S0_tmp = S0; @@ -93,6 +94,7 @@ enum aorai_OpStatusList { int S0_tmp; int S1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S0_tmp = S0; diff --git a/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle b/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle index 6f35fd44384ee6713e2fcba2b8c8141febfdc79c..4c3791659969fb3fd12b879ac0ec78ad55269c7a 100644 --- a/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/assigns.0.res.oracle @@ -74,6 +74,7 @@ int X; int Sf_tmp; int in_main_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; S1_tmp = S1; @@ -153,6 +154,7 @@ int X; int Sf_tmp; int in_main_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; S1_tmp = S1; @@ -247,6 +249,7 @@ void f(void) int Sf_tmp; int in_main_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S1_tmp = S1; @@ -326,6 +329,7 @@ void f(void) int Sf_tmp; int in_main_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S1_tmp = S1; diff --git a/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle b/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle index 27d4f62301443e0894f519fc111dbdbd7132e1e9..d5aa249647d0f929f15b6ea15f3079409953728e 100644 --- a/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/assigns.1.res.oracle @@ -32,7 +32,7 @@ enum aorai_OpStatusList { int X; /*@ ghost enum aorai_ListOper aorai_CurOperation; */ /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */ -/*@ ghost int aorai_CurStates = S1; */ +/*@ ghost enum aorai_States aorai_CurStates = S1; */ /*@ ghost /@ requires aorai_CurStates ≡ Sf; ensures aorai_CurOpStatus ≡ aorai_Called; @@ -71,9 +71,10 @@ int X; void f_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; - if (3 == aorai_CurStates) aorai_CurStates = S_in_f; + if ((unsigned int)3 == aorai_CurStates) aorai_CurStates = S_in_f; else aorai_CurStates = aorai_reject; return; } @@ -118,9 +119,10 @@ int X; void f_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; - if (2 == aorai_CurStates) aorai_CurStates = in_main; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = in_main; else aorai_CurStates = aorai_reject; return; } @@ -178,9 +180,10 @@ void f(void) void main_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (0 == aorai_CurStates) aorai_CurStates = Sf; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = Sf; else aorai_CurStates = aorai_reject; return; } @@ -225,9 +228,10 @@ void f(void) void main_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (5 == aorai_CurStates) aorai_CurStates = S2; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = S2; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle b/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle index b0cac6b01b25d96355241a543e34d95d5818b2ca..6c033979bd1de21bc5c66b78abefa5fbbecd8e26 100644 --- a/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/bts1289.0.res.oracle @@ -31,6 +31,7 @@ enum aorai_OpStatusList { { int S_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_a; S_tmp = S; @@ -59,6 +60,7 @@ enum aorai_OpStatusList { { int S_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_a; S_tmp = S; @@ -98,6 +100,7 @@ void a(void) { int S_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S_tmp = S; @@ -126,6 +129,7 @@ void a(void) { int S_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S_tmp = S; diff --git a/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle b/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle index a721d8db11216ab7be3d6b63317fa08393df9473..f123a10ea1d4899ff824644d1c5a355cbde2c03f 100644 --- a/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/bts1289.1.res.oracle @@ -79,6 +79,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_0_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_a; S_tmp = S; @@ -166,6 +167,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_0_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_a; S_tmp = S; @@ -284,6 +286,7 @@ void a(void) int aorai_intermediate_state_0_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S_tmp = S; @@ -364,6 +367,7 @@ void a(void) int aorai_intermediate_state_0_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S_tmp = S; diff --git a/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle b/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle index 8f274a98c57bbb554137167b38888f9cb9ad3ca4..bc1980f8dd6c6868c498af6df66a1fe4807b206b 100644 --- a/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/declared_function.res.oracle @@ -45,7 +45,7 @@ check lemma I_deterministic_trans{L}: __retres_f ≡ 1 + 2 ∧ \at(aorai_CurOperation,L) ≡ op_f ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧ __retres_f ≡ 0)); */ -/*@ ghost int aorai_CurStates = I; */ +/*@ ghost enum aorai_States aorai_CurStates = I; */ /*@ ghost /@ requires aorai_CurStates ≡ I; ensures aorai_CurOpStatus ≡ aorai_Called; @@ -72,9 +72,10 @@ check lemma I_deterministic_trans{L}: void main_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (0 == aorai_CurStates) aorai_CurStates = I; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = I; else aorai_CurStates = aorai_reject; return; } @@ -107,9 +108,10 @@ check lemma I_deterministic_trans{L}: void main_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (0 == aorai_CurStates) aorai_CurStates = I; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = I; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle b/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle index 8ad803dbd2282bf19797613d2ed3d27a25325221..923b8de4a8696df470651d5d6c41c73eb33aaa98 100644 --- a/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/deterministic.res.oracle @@ -62,7 +62,7 @@ check lemma S0_deterministic_trans{L}: \at(aorai_CurOperation,L) ≡ op_real_main ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ c ≡ 0); */ -/*@ ghost int aorai_CurStates = Si; */ +/*@ ghost enum aorai_States aorai_CurStates = Si; */ /*@ ghost /@ requires aorai_CurStates ≡ S3; requires aorai_CurStates ≡ S3 ⇒ x ≡ 5 ∨ x ≡ 4; @@ -116,14 +116,15 @@ check lemma S0_deterministic_trans{L}: void g_pre_func(int x) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; - if (3 == aorai_CurStates) { + if ((unsigned int)3 == aorai_CurStates) { if (x == 4) aorai_CurStates = S4; else goto __aorai_label; } else { __aorai_label: ; - if (3 == aorai_CurStates) + if ((unsigned int)3 == aorai_CurStates) if (x == 5) aorai_CurStates = S5; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; @@ -185,11 +186,12 @@ check lemma S0_deterministic_trans{L}: void g_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; - if (5 == aorai_CurStates) aorai_CurStates = S1; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = S1; else - if (4 == aorai_CurStates) aorai_CurStates = S3; + if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = S3; else aorai_CurStates = aorai_reject; return; } @@ -263,9 +265,10 @@ void g(int x) void f_pre_func(int x) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; - if (1 == aorai_CurStates) + if ((unsigned int)1 == aorai_CurStates) if (x == 4) aorai_CurStates = S3; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; return; @@ -321,9 +324,10 @@ void g(int x) void f_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; - if (1 == aorai_CurStates) + if ((unsigned int)1 == aorai_CurStates) if (res == 0) if (X == 5) aorai_CurStates = S2; else aorai_CurStates = aorai_reject; @@ -407,14 +411,15 @@ int f(int x) void real_main_pre_func(int c) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_real_main; - if (0 == aorai_CurStates) { + if ((unsigned int)0 == aorai_CurStates) { if (c != 0) aorai_CurStates = S1; else goto __aorai_label_0; } else { __aorai_label_0: ; - if (0 == aorai_CurStates) + if ((unsigned int)0 == aorai_CurStates) if (c == 0) aorai_CurStates = S2; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; @@ -471,9 +476,10 @@ int f(int x) void real_main_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_real_main; - if (2 == aorai_CurStates) aorai_CurStates = Sf; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = Sf; else aorai_CurStates = aorai_reject; return; } @@ -543,9 +549,10 @@ int real_main(int c) void main_pre_func(int c) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (7 == aorai_CurStates) aorai_CurStates = S0; + if ((unsigned int)7 == aorai_CurStates) aorai_CurStates = S0; else aorai_CurStates = aorai_reject; return; } @@ -599,9 +606,10 @@ int real_main(int c) void main_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (6 == aorai_CurStates) aorai_CurStates = Sf; + if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = Sf; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/floats.res.oracle b/src/plugins/aorai/tests/ya/oracle/floats.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c813ffb28c36688e5a55a25d199070d18baa59e1 --- /dev/null +++ b/src/plugins/aorai/tests/ya/oracle/floats.res.oracle @@ -0,0 +1,487 @@ +[kernel] Parsing floats.i (no preprocessing) +[kernel:parser:decimal-float] floats.i:8: Warning: + Floating-point constant 0.001 is not represented exactly. Will use 0x1.0624dd2f1a9fcp-10. + (warn-once: no further messages from category 'parser:decimal-float' will be emitted) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {I} +[eva:recursion] floats.i:11: + detected recursive call of function square_root_aux. +[eva] floats.i:11: Warning: + Using specification of function square_root_aux for recursive calls. + Analysis of function square_root_aux is thus incomplete and its soundness + relies on the written specification. +[eva] using specification for function square_root_aux +[eva] floats.i:6: Warning: + no \from part + for clause 'assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;' +[eva:alarm] :0: Warning: + function square_root_aux, behavior Buchi_property_behavior: postcondition got status unknown. +[eva:alarm] floats.i:11: Warning: + non-finite float value. + assert \is_finite(tmp); + (tmp from square_root_aux(y, n)) +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main_post_func: + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {E} +[eva:final-states] Values at end of function main_pre_func: + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {A} +[eva:final-states] Values at end of function square_root_aux_post_func: + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root_aux_pre_func: + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root_post_func: + aorai_CurOperation ∈ {op_square_root} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {C} +[eva:final-states] Values at end of function square_root_pre_func: + aorai_CurOperation ∈ {op_square_root} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root_aux: + y ∈ {1.5} + __retres ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root: + aorai_CurOperation ∈ {op_square_root} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {C} +[eva:final-states] Values at end of function main: + r ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {E} +[eva:summary] ====== ANALYSIS SUMMARY ====== + ---------------------------------------------------------------------------- + 9 functions analyzed (out of 9): 100% coverage. + In these functions, 53 statements reached (out of 67): 79% coverage. + ---------------------------------------------------------------------------- + Some errors and warnings have been raised during the analysis: + by the Eva analyzer: 0 errors 2 warnings + by the Frama-C kernel: 0 errors 0 warnings + ---------------------------------------------------------------------------- + 1 alarm generated by the analysis: + 1 nan or infinite floating-point value + ---------------------------------------------------------------------------- + Evaluation of the logical properties reached by the analysis: + Assertions 0 valid 0 unknown 0 invalid 0 total + Preconditions 10 valid 2 unknown 0 invalid 12 total + 83% of the logical properties reached have been proven. + ---------------------------------------------------------------------------- +[kernel] Parsing TMPDIR/aorai_floats_0.i (no preprocessing) +/* Generated by Frama-C */ +enum aorai_States { + A = 0, + B = 1, + C = 2, + E = 3, + I = 4, + aorai_reject = 5 +}; +enum aorai_ListOper { + op_main = 2, + op_square_root = 1, + op_square_root_aux = 0 +}; +enum aorai_OpStatusList { + aorai_Terminated = 1, + aorai_Called = 0 +}; +/*@ check lemma aorai_reject_deterministic_trans{L}: \true; + */ +/*@ check lemma I_deterministic_trans{L}: \true; + */ +/*@ check lemma E_deterministic_trans{L}: \true; + */ +/*@ check lemma C_deterministic_trans{L}: \true; + */ +/*@ check lemma A_deterministic_trans{L}: \true; + */ +/*@ ghost enum aorai_ListOper aorai_CurOperation; */ +/*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */ +/*@ +check lemma B_deterministic_trans{L}: + (∀ float n, float x; + ¬(\at(aorai_CurOperation,L) ≡ op_square_root_aux ∧ + \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧ + \at(aorai_CurOperation,L) ≡ op_square_root_aux ∧ + \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≥ 1.0f ∧ + x ≤ n)) ∧ + (∀ float n, float x; + ¬(\at(aorai_CurOperation,L) ≡ op_square_root ∧ + \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧ + \at(aorai_CurOperation,L) ≡ op_square_root_aux ∧ + \at(aorai_CurOpStatus,L) ≡ aorai_Called ∧ x ≥ 1.0f ∧ + x ≤ n)) ∧ + ¬(\at(aorai_CurOperation,L) ≡ op_square_root ∧ + \at(aorai_CurOpStatus,L) ≡ aorai_Terminated ∧ + \at(aorai_CurOperation,L) ≡ op_square_root_aux ∧ + \at(aorai_CurOpStatus,L) ≡ aorai_Terminated); + */ +/*@ ghost enum aorai_States aorai_CurStates = I; */ +/*@ ghost + /@ requires aorai_CurStates ≡ B; + requires aorai_CurStates ≡ B ⇒ x ≥ 1.0f ∧ x ≤ n; + ensures aorai_CurOpStatus ≡ aorai_Called; + ensures aorai_CurOperation ≡ op_square_root_aux; + assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOpStatus + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates, n, x; + assigns aorai_CurOperation + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates, n, x; + assigns aorai_CurStates + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates, n, x; + + behavior buch_state_A_out: + ensures aorai_CurStates ≢ A; + + behavior buch_state_B_in: + assumes aorai_CurStates ≡ B ∧ x ≥ 1.0f ∧ x ≤ n; + ensures aorai_CurStates ≡ B; + + behavior buch_state_B_out: + assumes aorai_CurStates ≢ B ∨ ¬(x ≥ 1.0f ∧ x ≤ n); + ensures aorai_CurStates ≢ B; + + behavior buch_state_C_out: + ensures aorai_CurStates ≢ C; + + behavior buch_state_E_out: + ensures aorai_CurStates ≢ E; + + behavior buch_state_I_out: + ensures aorai_CurStates ≢ I; + + behavior buch_state_aorai_reject_out: + ensures aorai_CurStates ≢ aorai_reject; + @/ + void square_root_aux_pre_func(float x, float n) + { + /@ slevel full; @/ + ; + aorai_CurOpStatus = aorai_Called; + aorai_CurOperation = op_square_root_aux; + if ((unsigned int)1 == aorai_CurStates) + if (x >= 1.0f) + if (x <= n) aorai_CurStates = B; else aorai_CurStates = aorai_reject; + else aorai_CurStates = aorai_reject; + else aorai_CurStates = aorai_reject; + return; + } + +*/ + +/*@ ghost + /@ requires aorai_CurStates ≡ B; + ensures aorai_CurOpStatus ≡ aorai_Terminated; + ensures aorai_CurOperation ≡ op_square_root_aux; + assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOpStatus + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOperation + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurStates + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + + behavior buch_state_A_out: + ensures aorai_CurStates ≢ A; + + behavior buch_state_B_in: + assumes aorai_CurStates ≡ B; + ensures aorai_CurStates ≡ B; + + behavior buch_state_B_out: + assumes aorai_CurStates ≢ B; + ensures aorai_CurStates ≢ B; + + behavior buch_state_C_out: + ensures aorai_CurStates ≢ C; + + behavior buch_state_E_out: + ensures aorai_CurStates ≢ E; + + behavior buch_state_I_out: + ensures aorai_CurStates ≢ I; + + behavior buch_state_aorai_reject_out: + ensures aorai_CurStates ≢ aorai_reject; + @/ + void square_root_aux_post_func(float res) + { + /@ slevel full; @/ + ; + aorai_CurOpStatus = aorai_Terminated; + aorai_CurOperation = op_square_root_aux; + if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = B; + else aorai_CurStates = aorai_reject; + return; + } + +*/ + +/*@ requires aorai_CurStates ≡ B; + requires aorai_CurStates ≡ B ⇒ x ≥ 1.0f ∧ x ≤ n; + assigns \result, aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns \result \from x, n; + + behavior Buchi_property_behavior: + ensures aorai_CurStates ≡ B; + */ +float square_root_aux(float x, float n) +{ + float __retres; + /*@ ghost square_root_aux_pre_func(x,n); */ + float y = (x + n / x) / 2.0f; + if ((double)(x - y) > 0.001) { + __retres = y; + goto return_label; + } + else { + float tmp; + tmp = square_root_aux(y,n); + /*@ assert Eva: is_nan_or_infinite: \is_finite(tmp); */ ; + __retres = tmp; + goto return_label; + } + return_label: + { + /*@ ghost square_root_aux_post_func(__retres); */ + return __retres; + } +} + +/*@ ghost + /@ requires aorai_CurStates ≡ A; + ensures aorai_CurOpStatus ≡ aorai_Called; + ensures aorai_CurOperation ≡ op_square_root; + assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOpStatus + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOperation + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurStates + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + + behavior buch_state_A_out: + ensures aorai_CurStates ≢ A; + + behavior buch_state_B_in: + assumes aorai_CurStates ≡ A; + ensures aorai_CurStates ≡ B; + + behavior buch_state_B_out: + assumes aorai_CurStates ≢ A; + ensures aorai_CurStates ≢ B; + + behavior buch_state_C_out: + ensures aorai_CurStates ≢ C; + + behavior buch_state_E_out: + ensures aorai_CurStates ≢ E; + + behavior buch_state_I_out: + ensures aorai_CurStates ≢ I; + + behavior buch_state_aorai_reject_out: + ensures aorai_CurStates ≢ aorai_reject; + @/ + void square_root_pre_func(float n) + { + /@ slevel full; @/ + ; + aorai_CurOpStatus = aorai_Called; + aorai_CurOperation = op_square_root; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = B; + else aorai_CurStates = aorai_reject; + return; + } + +*/ + +/*@ ghost + /@ requires aorai_CurStates ≡ B; + ensures aorai_CurOpStatus ≡ aorai_Terminated; + ensures aorai_CurOperation ≡ op_square_root; + assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOpStatus + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOperation + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurStates + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + + behavior buch_state_A_out: + ensures aorai_CurStates ≢ A; + + behavior buch_state_B_out: + ensures aorai_CurStates ≢ B; + + behavior buch_state_C_in: + assumes aorai_CurStates ≡ B; + ensures aorai_CurStates ≡ C; + + behavior buch_state_C_out: + assumes aorai_CurStates ≢ B; + ensures aorai_CurStates ≢ C; + + behavior buch_state_E_out: + ensures aorai_CurStates ≢ E; + + behavior buch_state_I_out: + ensures aorai_CurStates ≢ I; + + behavior buch_state_aorai_reject_out: + ensures aorai_CurStates ≢ aorai_reject; + @/ + void square_root_post_func(float res) + { + /@ slevel full; @/ + ; + aorai_CurOpStatus = aorai_Terminated; + aorai_CurOperation = op_square_root; + if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = C; + else aorai_CurStates = aorai_reject; + return; + } + +*/ + +/*@ requires aorai_CurStates ≡ A; + + behavior Buchi_property_behavior: + ensures aorai_CurStates ≡ C; + */ +float square_root(float n) +{ + float tmp; + /*@ ghost square_root_pre_func(n); */ + tmp = square_root_aux((float)1.0,n); + /*@ ghost square_root_post_func(tmp); */ + return tmp; +} + +/*@ ghost + /@ requires aorai_CurStates ≡ I; + ensures aorai_CurOpStatus ≡ aorai_Called; + ensures aorai_CurOperation ≡ op_main; + assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOpStatus + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOperation + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurStates + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + + behavior buch_state_A_in: + assumes aorai_CurStates ≡ I; + ensures aorai_CurStates ≡ A; + + behavior buch_state_A_out: + assumes aorai_CurStates ≢ I; + ensures aorai_CurStates ≢ A; + + behavior buch_state_B_out: + ensures aorai_CurStates ≢ B; + + behavior buch_state_C_out: + ensures aorai_CurStates ≢ C; + + behavior buch_state_E_out: + ensures aorai_CurStates ≢ E; + + behavior buch_state_I_out: + ensures aorai_CurStates ≢ I; + + behavior buch_state_aorai_reject_out: + ensures aorai_CurStates ≢ aorai_reject; + @/ + void main_pre_func(void) + { + /@ slevel full; @/ + ; + aorai_CurOpStatus = aorai_Called; + aorai_CurOperation = op_main; + if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = A; + else aorai_CurStates = aorai_reject; + return; + } + +*/ + +/*@ ghost + /@ requires aorai_CurStates ≡ C; + ensures aorai_CurOpStatus ≡ aorai_Terminated; + ensures aorai_CurOperation ≡ op_main; + assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOpStatus + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurOperation + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + assigns aorai_CurStates + \from aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates; + + behavior buch_state_A_out: + ensures aorai_CurStates ≢ A; + + behavior buch_state_B_out: + ensures aorai_CurStates ≢ B; + + behavior buch_state_C_out: + ensures aorai_CurStates ≢ C; + + behavior buch_state_E_in: + assumes aorai_CurStates ≡ C; + ensures aorai_CurStates ≡ E; + + behavior buch_state_E_out: + assumes aorai_CurStates ≢ C; + ensures aorai_CurStates ≢ E; + + behavior buch_state_I_out: + ensures aorai_CurStates ≢ I; + + behavior buch_state_aorai_reject_out: + ensures aorai_CurStates ≢ aorai_reject; + @/ + void main_post_func(void) + { + /@ slevel full; @/ + ; + aorai_CurOpStatus = aorai_Terminated; + aorai_CurOperation = op_main; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = E; + else aorai_CurStates = aorai_reject; + return; + } + +*/ + +/*@ requires aorai_CurStates ≡ I; + + behavior Buchi_property_behavior: + ensures aorai_CurStates ≡ E; + */ +void main(void) +{ + /*@ ghost main_pre_func(); */ + float r = square_root(2.0f); + /*@ ghost main_post_func(); */ + return; +} + + diff --git a/src/plugins/aorai/tests/ya/oracle/formals.res.oracle b/src/plugins/aorai/tests/ya/oracle/formals.res.oracle index c37d669f42245f94696ce437ea63e1b5637551d2..3e76cd392c78a6744e7ab6e97911684a0353a815 100644 --- a/src/plugins/aorai/tests/ya/oracle/formals.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/formals.res.oracle @@ -43,7 +43,7 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}: ¬(\at(aorai_CurOperation,L) ≡ op_g ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Called)); */ -/*@ ghost int aorai_CurStates = init; */ +/*@ ghost enum aorai_States aorai_CurStates = init; */ /*@ ghost int aorai_x_0 = 0; */ /*@ check lemma aorai_intermediate_state_2_deterministic_trans{L}: @@ -139,9 +139,10 @@ check lemma aorai_intermediate_state_deterministic_trans{L}: void f_pre_func(int x) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; - if (7 == aorai_CurStates) { + if ((unsigned int)7 == aorai_CurStates) { if (x == 1) { aorai_CurStates = aorai_intermediate_state; aorai_x = x; @@ -150,7 +151,7 @@ check lemma aorai_intermediate_state_deterministic_trans{L}: } else { __aorai_label: ; - if (7 == aorai_CurStates) + if ((unsigned int)7 == aorai_CurStates) if (x == 3) { aorai_CurStates = aorai_intermediate_state_2; aorai_x_0 = x; @@ -238,26 +239,27 @@ check lemma aorai_intermediate_state_deterministic_trans{L}: void f_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; - if (4 == aorai_CurStates) { + if ((unsigned int)4 == aorai_CurStates) { if (aorai_x_0 == 3) aorai_CurStates = OK; else goto __aorai_label_2; } else { __aorai_label_2: ; - if (1 == aorai_CurStates) { + if ((unsigned int)1 == aorai_CurStates) { if (aorai_x == 1) aorai_CurStates = aorai_intermediate_state_0; else goto __aorai_label_1; } else { __aorai_label_1: ; - if (4 == aorai_CurStates) { + if ((unsigned int)4 == aorai_CurStates) { if (aorai_x_0 != 3) aorai_CurStates = aorai_reject; else goto __aorai_label_0; } else { __aorai_label_0: ; - if (1 == aorai_CurStates) + if ((unsigned int)1 == aorai_CurStates) if (aorai_x != 1) aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; @@ -394,16 +396,17 @@ int f(int x) void g_pre_func(int y) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; - if (0 == aorai_CurStates) aorai_CurStates = OK; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = OK; else - if (2 == aorai_CurStates) { + if ((unsigned int)2 == aorai_CurStates) { aorai_CurStates = aorai_intermediate_state_1; aorai_y = y; } else - if (5 == aorai_CurStates) aorai_CurStates = aorai_reject; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; return; } @@ -474,18 +477,19 @@ int f(int x) void g_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; - if (3 == aorai_CurStates) { + if ((unsigned int)3 == aorai_CurStates) { if (aorai_y == 2) aorai_CurStates = OK; else goto __aorai_label_3; } else { __aorai_label_3: ; - if (0 == aorai_CurStates) aorai_CurStates = OK; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = OK; else - if (5 == aorai_CurStates) aorai_CurStates = aorai_reject; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_reject; else - if (3 == aorai_CurStates) + if ((unsigned int)3 == aorai_CurStates) if (aorai_y != 2) aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; @@ -575,9 +579,10 @@ int g(int y) void main_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (6 == aorai_CurStates) aorai_CurStates = main_0; + if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = main_0; else aorai_CurStates = aorai_reject; return; } @@ -633,11 +638,12 @@ int g(int y) void main_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (0 == aorai_CurStates) aorai_CurStates = OK; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = OK; else - if (5 == aorai_CurStates) aorai_CurStates = aorai_reject; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle b/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle index 16e5de830ac2b2f7e5c0161f7f79d538e4b30200..d3769b352d33da71077733114223d69059d67c7a 100644 --- a/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/function_ptr.res.oracle @@ -65,7 +65,7 @@ check lemma aorai_intermediate_state_deterministic_trans{L}: ¬(\at(aorai_CurOperation,L) ≡ op_f ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Terminated)); */ -/*@ ghost int aorai_CurStates = i; */ +/*@ ghost enum aorai_States aorai_CurStates = i; */ /*@ ghost /@ requires aorai_CurStates ≡ g_called ∨ aorai_CurStates ≡ s1; ensures aorai_CurOpStatus ≡ aorai_Called; @@ -121,11 +121,12 @@ check lemma aorai_intermediate_state_deterministic_trans{L}: void f_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; - if (9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state; + if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state; else - if (6 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_2; + if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_2; else aorai_CurStates = aorai_reject; return; } @@ -189,11 +190,12 @@ check lemma aorai_intermediate_state_deterministic_trans{L}: void f_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; - if (0 == aorai_CurStates) aorai_CurStates = f_called; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = f_called; else - if (3 == aorai_CurStates) aorai_CurStates = ok; + if ((unsigned int)3 == aorai_CurStates) aorai_CurStates = ok; else aorai_CurStates = aorai_reject; return; } @@ -275,11 +277,12 @@ void f(void) void g_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; - if (9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0; + if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0; else - if (5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1; else aorai_CurStates = aorai_reject; return; } @@ -343,11 +346,12 @@ void f(void) void g_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; - if (1 == aorai_CurStates) aorai_CurStates = g_called; + if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = g_called; else - if (2 == aorai_CurStates) aorai_CurStates = ok; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = ok; else aorai_CurStates = aorai_reject; return; } @@ -424,9 +428,10 @@ void g(void) void main_pre_func(int c) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (7 == aorai_CurStates) aorai_CurStates = s1; + if ((unsigned int)7 == aorai_CurStates) aorai_CurStates = s1; else aorai_CurStates = aorai_reject; return; } @@ -483,9 +488,10 @@ void g(void) void main_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (8 == aorai_CurStates) aorai_CurStates = ok; + if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = ok; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle b/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle index 34366aa9fd40d3c26130b980494067d8a27b055a..2f0e7ce8e84ab43d8cba663cecc7766c1d3d8f73 100644 --- a/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/generate_assigns_bts1290.res.oracle @@ -34,6 +34,7 @@ enum aorai_OpStatusList { { int S_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S_tmp = S; @@ -67,6 +68,7 @@ enum aorai_OpStatusList { { int S_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S_tmp = S; diff --git a/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle b/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle index 0c22ea3ad2c717deed55f7fd804d2d8cf012610d..1a40c608459f2eabd9189ba8c1374eb87f5663b3 100644 --- a/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/hoare_seq.res.oracle @@ -116,6 +116,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_reject_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; S0_tmp = S0; @@ -244,6 +245,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_reject_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; S0_tmp = S0; @@ -440,6 +442,7 @@ int main_bhv_bhv(int c); */ int aorai_intermediate_state_2_tmp; int aorai_reject_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S0_tmp = S0; @@ -584,6 +587,7 @@ int main_bhv_bhv(int c); */ int aorai_intermediate_state_2_tmp; int aorai_reject_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S0_tmp = S0; diff --git a/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle b/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle index e69f85f246c1dd25aac610260ab32ce16e9b29a4..4e77b2b2d82c624882c4cf7e1996d96a3a3a53f2 100644 --- a/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/incorrect.res.oracle @@ -22,7 +22,7 @@ int f(void); /*@ ghost enum aorai_ListOper aorai_CurOperation; */ /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */ -/*@ ghost int aorai_CurStates = s0; */ +/*@ ghost enum aorai_States aorai_CurStates = s0; */ /*@ ghost /@ requires \false; ensures aorai_CurOpStatus ≡ aorai_Called; @@ -44,6 +44,7 @@ int f(void); void main_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; aorai_CurStates = aorai_reject; @@ -73,6 +74,7 @@ int f(void); void main_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; aorai_CurStates = aorai_reject; diff --git a/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle b/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle index 4aa48e2ee5d7fa37f6d81627004ac5e7f4955b9d..9257d2c5d17a1376ece0f36e6266d24c35657853 100644 --- a/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/logical_operators.res.oracle @@ -36,6 +36,7 @@ enum aorai_OpStatusList { { int I_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; I_tmp = I; @@ -77,6 +78,7 @@ enum aorai_OpStatusList { { int I_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; I_tmp = I; @@ -124,6 +126,7 @@ void f(int x) { int I_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; I_tmp = I; @@ -157,6 +160,7 @@ void f(int x) { int I_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; I_tmp = I; diff --git a/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle b/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle index 260cb460abb1c282a351d5544b232ff3f342f913..7d8927d391b2e483f1aacb22b9387b8794098d3c 100644 --- a/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/loop_bts1050.res.oracle @@ -129,6 +129,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; S0_tmp = S0; @@ -259,6 +260,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; S0_tmp = S0; @@ -415,6 +417,7 @@ void f(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; S0_tmp = S0; @@ -538,6 +541,7 @@ void f(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; S0_tmp = S0; @@ -680,6 +684,7 @@ void g(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S0_tmp = S0; @@ -804,6 +809,7 @@ void g(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S0_tmp = S0; diff --git a/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle b/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle index c09d670113547f3b377d5e31c0bee83e0959f4cf..67b68e9ab8ce82621e6b83f8ddc7066482f4d57c 100644 --- a/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/metavariables-right.res.oracle @@ -49,7 +49,7 @@ check lemma b_deterministic_trans{L}: \at(aorai_CurOperation,L) ≡ op_f ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Called); */ -/*@ ghost int aorai_CurStates = a; */ +/*@ ghost enum aorai_States aorai_CurStates = a; */ /*@ ghost int aorai_x = 0; */ /*@ check lemma e_deterministic_trans{L}: @@ -120,9 +120,10 @@ check lemma e_deterministic_trans{L}: void f_pre_func(int x) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; - if (2 == aorai_CurStates) { + if ((unsigned int)2 == aorai_CurStates) { aorai_CurStates = c; aorai_x = x; aorai_y = aorai_x; @@ -183,9 +184,10 @@ check lemma e_deterministic_trans{L}: void f_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; - if (3 == aorai_CurStates) aorai_CurStates = e; + if ((unsigned int)3 == aorai_CurStates) aorai_CurStates = e; else aorai_CurStates = aorai_reject; return; } @@ -260,9 +262,10 @@ void f(int x) void g_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; - if (2 == aorai_CurStates) aorai_CurStates = d; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = d; else aorai_CurStates = aorai_reject; return; } @@ -319,9 +322,10 @@ void f(int x) void g_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; - if (4 == aorai_CurStates) aorai_CurStates = g_0; + if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = g_0; else aorai_CurStates = aorai_reject; return; } @@ -391,9 +395,10 @@ void g(void) void h_pre_func(int x) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_h; - if (5 == aorai_CurStates) + if ((unsigned int)5 == aorai_CurStates) if (aorai_x > 0) aorai_CurStates = f_0; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; @@ -452,9 +457,10 @@ void g(void) void h_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_h; - if (6 == aorai_CurStates) aorai_CurStates = g_0; + if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = g_0; else aorai_CurStates = aorai_reject; return; } @@ -524,9 +530,10 @@ void h(int x) void i_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_i; - if (7 == aorai_CurStates) aorai_CurStates = h_0; + if ((unsigned int)7 == aorai_CurStates) aorai_CurStates = h_0; else aorai_CurStates = aorai_reject; return; } @@ -594,9 +601,10 @@ void h(int x) void i_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_i; - if (8 == aorai_CurStates) { + if ((unsigned int)8 == aorai_CurStates) { aorai_CurStates = e; aorai_y = 0; aorai_x = 1; @@ -675,9 +683,10 @@ void i(void) void main_pre_func(int t) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (0 == aorai_CurStates) aorai_CurStates = b; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = b; else aorai_CurStates = aorai_reject; return; } @@ -734,9 +743,10 @@ void i(void) void main_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (5 == aorai_CurStates) aorai_CurStates = i_0; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = i_0; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle b/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle index 925e912d1aedd0f75d769fd62f3649e84bad8447..eb4fbb3195124e602785ea9f55efa0161e20105b 100644 --- a/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/monostate.res.oracle @@ -35,7 +35,7 @@ check lemma Init_deterministic_trans{L}: ¬(\at(aorai_CurOperation,L) ≡ op_main ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Called)); */ -/*@ ghost int aorai_CurStates = Init; */ +/*@ ghost enum aorai_States aorai_CurStates = Init; */ /*@ ghost /@ requires \false; ensures aorai_CurOpStatus ≡ aorai_Called; @@ -69,11 +69,12 @@ check lemma Init_deterministic_trans{L}: void f_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; - if (2 == aorai_CurStates) aorai_CurStates = aorai_reject; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = aorai_reject; else - if (1 == aorai_CurStates) aorai_CurStates = aorai_reject; + if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; return; } @@ -109,9 +110,10 @@ check lemma Init_deterministic_trans{L}: void f_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; - if (2 == aorai_CurStates) aorai_CurStates = aorai_reject; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; return; } @@ -160,6 +162,7 @@ void f(void) void main_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; aorai_CurStates = aorai_reject; @@ -192,6 +195,7 @@ void f(void) void main_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; aorai_CurStates = aorai_reject; diff --git a/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle b/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle index 3caffe84fad47612be18e7e4c3fec7446a18c2c2..36fba5e9a2d04d52b622e0a3b0568d069c3e8b55 100644 --- a/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/not_prm.res.oracle @@ -41,6 +41,7 @@ enum aorai_OpStatusList { int S0_tmp; int Sf_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; S0_tmp = S0; @@ -84,6 +85,7 @@ enum aorai_OpStatusList { int S0_tmp; int Sf_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; S0_tmp = S0; diff --git a/src/plugins/aorai/tests/ya/oracle/observed.res.oracle b/src/plugins/aorai/tests/ya/oracle/observed.res.oracle index e2e3a4fe94ea87191bbb7caa3162cf0bc7f927e5..05170397e238edc619affe696d5404119fa60430 100644 --- a/src/plugins/aorai/tests/ya/oracle/observed.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/observed.res.oracle @@ -74,6 +74,7 @@ enum aorai_OpStatusList { int first_step_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; aorai_intermediate_state_tmp = aorai_intermediate_state; @@ -156,6 +157,7 @@ enum aorai_OpStatusList { int first_step_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; aorai_intermediate_state_tmp = aorai_intermediate_state; @@ -325,6 +327,7 @@ void g(void) int first_step_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_h; aorai_intermediate_state_tmp = aorai_intermediate_state; @@ -407,6 +410,7 @@ void g(void) int first_step_tmp; int init_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_h; aorai_intermediate_state_tmp = aorai_intermediate_state; diff --git a/src/plugins/aorai/tests/ya/oracle/other.res.oracle b/src/plugins/aorai/tests/ya/oracle/other.res.oracle index f83db815ae931852f8760e80e33016d64bfa76e4..7879583a70dd773cd54f39c03ff52d1251861310 100644 --- a/src/plugins/aorai/tests/ya/oracle/other.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/other.res.oracle @@ -70,6 +70,7 @@ int x = 0; int last_tmp; int step1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; init_tmp = init; @@ -173,6 +174,7 @@ int x = 0; int last_tmp; int step1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; init_tmp = init; @@ -340,6 +342,7 @@ void f(void) int last_tmp; int step1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; init_tmp = init; @@ -443,6 +446,7 @@ void f(void) int last_tmp; int step1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; init_tmp = init; @@ -597,6 +601,7 @@ void g(void) int last_tmp; int step1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; init_tmp = init; @@ -671,6 +676,7 @@ void g(void) int last_tmp; int step1_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; init_tmp = init; diff --git a/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt b/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt index 7f7a57a4bac7e68a702ddc8dc1f4a1c8ae4bce31..58fd37adca9999eea9a8a09024059ced1f1c642d 100644 --- a/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt +++ b/src/plugins/aorai/tests/ya/oracle/saveload.res.1.log.txt @@ -4,37 +4,37 @@ [eva] Computing initial state [eva] Initial state computed [eva:initial-state] Values of globals at initialization - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {0} - aorai_CurStates ∈ {2} + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {init} [aorai] saveload.i:14: accept [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function f_post_func: - aorai_CurOperation ∈ {1} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {0} + aorai_CurOperation ∈ {op_f} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {accept} [eva:final-states] Values at end of function f_pre_func: - aorai_CurOperation ∈ {1} - aorai_CurOpStatus ∈ {0} - aorai_CurStates ∈ {0} + aorai_CurOperation ∈ {op_f} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {accept} [eva:final-states] Values at end of function f: - aorai_CurOperation ∈ {1} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {0} + aorai_CurOperation ∈ {op_f} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {accept} [eva:final-states] Values at end of function main_post_func: - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {0} + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {accept} [eva:final-states] Values at end of function main_pre_func: - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {0} - aorai_CurStates ∈ {0} + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {accept} [eva:final-states] Values at end of function main: __retres ∈ {0} - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {0} + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {accept} [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- 6 functions analyzed (out of 6): 100% coverage. diff --git a/src/plugins/aorai/tests/ya/oracle/seq.res.oracle b/src/plugins/aorai/tests/ya/oracle/seq.res.oracle index b2f0a865f3d5c032ce7fbb3fca1f315091ada68d..4c0723689a86db3c32bfe5df30121f87991842ed 100644 --- a/src/plugins/aorai/tests/ya/oracle/seq.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/seq.res.oracle @@ -114,6 +114,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; S0_tmp = S0; @@ -237,6 +238,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; S0_tmp = S0; @@ -406,6 +408,7 @@ void f(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; S0_tmp = S0; @@ -539,6 +542,7 @@ void f(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; S0_tmp = S0; @@ -705,6 +709,7 @@ void g(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S0_tmp = S0; @@ -829,6 +834,7 @@ void g(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S0_tmp = S0; diff --git a/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle b/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle index bae62a6316898061fab0f135c5d8568de8d0e381..b256e59ddb8d0654c2d0c6a2a794045b9ac22c13 100644 --- a/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/seq_loop.res.oracle @@ -129,6 +129,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_f; S0_tmp = S0; @@ -259,6 +260,7 @@ enum aorai_OpStatusList { int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_f; S0_tmp = S0; @@ -415,6 +417,7 @@ void f(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_g; S0_tmp = S0; @@ -538,6 +541,7 @@ void f(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_g; S0_tmp = S0; @@ -680,6 +684,7 @@ void g(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S0_tmp = S0; @@ -804,6 +809,7 @@ void g(void) int aorai_intermediate_state_2_tmp; int aorai_intermediate_state_3_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S0_tmp = S0; diff --git a/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle b/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle index db603fa1ec63d19e7e6156d9048b95b17d41d13b..0b47507c6a2054e9e7352bfdce2a60e6174ba412 100644 --- a/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/seq_unlimited.res.oracle @@ -48,7 +48,7 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}: \at(aorai_CurOperation,L) ≡ op_main ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Terminated); */ -/*@ ghost int aorai_CurStates = fst; */ +/*@ ghost enum aorai_States aorai_CurStates = fst; */ /*@ ghost /@ requires aorai_CurStates ≡ b; ensures aorai_CurOpStatus ≡ aorai_Called; @@ -93,9 +93,10 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}: void init_pre_func(int *a, int n) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_init; - if (4 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state; + if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state; else aorai_CurStates = aorai_reject; return; } @@ -146,9 +147,10 @@ check lemma aorai_intermediate_state_0_deterministic_trans{L}: void init_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_init; - if (0 == aorai_CurStates) aorai_CurStates = c; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = c; else aorai_CurStates = aorai_reject; return; } @@ -235,11 +237,12 @@ void init(int *a, int n) void find_pre_func(int *a, int n, int k) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_find; - if (5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1; + if ((unsigned int)5 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1; else - if (1 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1; + if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_1; else aorai_CurStates = aorai_reject; return; } @@ -290,9 +293,10 @@ void init(int *a, int n) void find_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_find; - if (2 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = aorai_intermediate_state_0; else aorai_CurStates = aorai_reject; return; } @@ -394,9 +398,10 @@ int find(int *a, int n, int k) void main_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (6 == aorai_CurStates) aorai_CurStates = b; + if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = b; else aorai_CurStates = aorai_reject; return; } @@ -447,9 +452,10 @@ int find(int *a, int n, int k) void main_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (1 == aorai_CurStates) aorai_CurStates = ok; + if ((unsigned int)1 == aorai_CurStates) aorai_CurStates = ok; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/serial.res.oracle b/src/plugins/aorai/tests/ya/oracle/serial.res.oracle index f6cbbacc42cbecac9183de261ba17490eddb4cf3..843d3f17a658bb06d8c331b1b18d58f9c03ef5a7 100644 --- a/src/plugins/aorai/tests/ya/oracle/serial.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/serial.res.oracle @@ -12,267 +12,125 @@ aorai_x2 ∈ {0} aorai_y1 ∈ {0} aorai_y2 ∈ {0} - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {0} - aorai_CurStates ∈ {19} + aorai_CurOperation ∈ {op_output} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {Wait1} aorai_StatesHistory_1 ∈ {19} aorai_StatesHistory_2 ∈ {19} [eva] using specification for function Frama_C_interval [eva] serial.c:58: starting to merge loop iterations [eva] serial.c:63: Trace partitioning superposing up to 100 states -[eva] serial.c:63: Trace partitioning superposing up to 300 states +[eva] serial.c:63: Trace partitioning superposing up to 200 states [eva:alarm] serial.c:33: Warning: assertion 'Aorai,aorai_smoke_test' got status invalid (stopping propagation). [aorai] serial.c:92: Wait1 <- Wait1 <- Complete -[aorai] serial.c:92: n in {5},x in [0..16383],y in [8192..16383] -[aorai] serial.c:92: Wait1 <- Wait1 <- Complete -[aorai] serial.c:92: n in {5},x in [0..16383],y in [0..8191] -[eva] serial.c:63: Trace partitioning superposing up to 500 states -[eva] serial.c:63: Trace partitioning superposing up to 700 states +[aorai] serial.c:92: n in {5},x in [0..16383],y in [0..16383] +[eva] serial.c:63: Trace partitioning superposing up to 400 states +[eva] serial.c:63: Trace partitioning superposing up to 600 states +[eva] serial.c:63: Trace partitioning superposing up to 800 states [eva] serial.c:63: Trace partitioning superposing up to 900 states -[eva] serial.c:63: Trace partitioning superposing up to 1200 states -[eva] serial.c:63: Trace partitioning superposing up to 1400 states -[eva] serial.c:63: Trace partitioning superposing up to 1500 states -[eva] serial.c:63: Trace partitioning superposing up to 1600 states -[eva] serial.c:63: Trace partitioning superposing up to 1700 states +[eva] serial.c:63: Trace partitioning superposing up to 1000 states +[eva] serial.c:63: Trace partitioning superposing up to 1100 states [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function input_data_post_func: - aorai_x1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_x2 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y2 ∈ [0..2147483647] - aorai_CurOperation ∈ {2} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {0; 19; 20; 21; 22; 23} + aorai_x1 ∈ [0..127] + aorai_x2 ∈ [0..127] + aorai_y1 ∈ [0..127] + aorai_y2 ∈ [0..127] + aorai_CurOperation ∈ {op_input_data} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5} aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6} aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13} [eva:final-states] Values at end of function input_data_pre_func: - aorai_CurOperation ∈ {2} - aorai_CurOpStatus ∈ {0} - aorai_CurStates ∈ {1; 2; 3; 4; 5; 6} + aorai_CurOperation ∈ {op_input_data} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ + {DataReq1; DataReq2; DataReq3; DataReq4; DataReq5; DataReqE} aorai_StatesHistory_1 ∈ {8; 9; 10; 11; 12; 13} aorai_StatesHistory_2 ∈ {14; 15; 16; 17; 18} [eva:final-states] Values at end of function input_data: Frama_C_entropy_source ∈ [--..--] - aorai_x1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_x2 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y2 ∈ [0..2147483647] - aorai_CurOperation ∈ {2} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {0; 19; 20; 21; 22; 23} + aorai_x1 ∈ [0..127] + aorai_x2 ∈ [0..127] + aorai_y1 ∈ [0..127] + aorai_y2 ∈ [0..127] + aorai_CurOperation ∈ {op_input_data} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5} aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6} aorai_StatesHistory_2 ∈ {8; 9; 10; 11; 12; 13} [eva:final-states] Values at end of function input_status_post_func: - aorai_CurOperation ∈ {1} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23} + aorai_CurOperation ∈ {op_input_status} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ + {StatusError; StatusOk1; StatusOk2; StatusOk3; StatusOk4; + StatusOk5; Wait1; Wait2; Wait3; Wait4; Wait5} aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18} aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23} [eva:final-states] Values at end of function input_status_pre_func: - aorai_CurOperation ∈ {1} - aorai_CurOpStatus ∈ {0} - aorai_CurStates ∈ {14; 15; 16; 17; 18} + aorai_CurOperation ∈ {op_input_status} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ + {StatusReq1; StatusReq2; StatusReq3; StatusReq4; StatusReq5} aorai_StatesHistory_1 ∈ {0; 19; 20; 21; 22; 23} - aorai_StatesHistory_2 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18; 19} + aorai_StatesHistory_2 ∈ [1..6] ∪ [14..19] [eva:final-states] Values at end of function input_status: Frama_C_entropy_source ∈ [--..--] - aorai_CurOperation ∈ {1} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23} + aorai_CurOperation ∈ {op_input_status} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ + {StatusError; StatusOk1; StatusOk2; StatusOk3; StatusOk4; + StatusOk5; Wait1; Wait2; Wait3; Wait4; Wait5} aorai_StatesHistory_1 ∈ {14; 15; 16; 17; 18} aorai_StatesHistory_2 ∈ {0; 19; 20; 21; 22; 23} [eva:final-states] Values at end of function output_post_func: - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {19; 24} + aorai_CurOperation ∈ {op_output} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {Wait1; aorai_reject} aorai_StatesHistory_1 ∈ {7; 19} aorai_StatesHistory_2 ∈ {0} [eva:final-states] Values at end of function output_pre_func: - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {0} - aorai_CurStates ∈ {7; 19; 24} + aorai_CurOperation ∈ {op_output} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {Error; Wait1; aorai_reject} aorai_StatesHistory_1 ∈ {0} aorai_StatesHistory_2 ∈ {5} [eva:final-states] Values at end of function output: - aorai_CurOperation ∈ {0} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {19} + aorai_CurOperation ∈ {op_output} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {Wait1} aorai_StatesHistory_1 ∈ {19} aorai_StatesHistory_2 ∈ {0} [eva:final-states] Values at end of function read: Frama_C_entropy_source ∈ [--..--] - s ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19; 20; - 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; 35; 36; 37; 38; - 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; 51; 52; 53; 54; 55; 56; - 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; 67; 68; 69; 70; 71; 72; 73; 74; - 75; 76; 77; 78; 79; 80; 81; 82; 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; - 93; 94; 95; 96; 97; 98; 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; - 109; 110; 111; 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; - 123; 124; 125; 126; 127; 128; 129; 130; 131; 132; 133; 134; 135; 136; - 137; 138; 139; 140; 141; 142; 143; 144; 145; 146; 147; 148; 149; 150; - 151; 152; 153; 154; 155; 156; 157; 158; 159; 160; 161; 162; 163; 164; - 165; 166; 167; 168; 169; 170; 171; 172; 173; 174; 175; 176; 177; 178; - 179; 180; 181; 182; 183; 184; 185; 186; 187; 188; 189; 190; 191; 192; - 193; 194; 195; 196; 197; 198; 199; 200; 201; 202; 203; 204; 205; 206; - 207; 208; 209; 210; 211; 212; 213; 214; 215; 216; 217; 218; 219; 220; - 221; 222; 223; 224; 225; 226; 227; 228; 229; 230; 231; 232; 233; 234; - 235; 236; 237; 238; 239; 240; 241; 242; 243; 244; 245; 246; 247; 248; - 249; 250; 251; 252; 253; 254; 255} + s ∈ [0..255] status ∈ {0; 2; 4; 6; 8; 10; 12; 14} or UNINITIALIZED __retres ∈ [-1..255] - aorai_x1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_x2 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y2 ∈ [0..2147483647] - aorai_CurOperation ∈ {1; 2} - aorai_CurOpStatus ∈ {1} - aorai_CurStates ∈ {0; 19; 20; 21; 22; 23} - aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18} - aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23} + aorai_x1 ∈ [0..127] + aorai_x2 ∈ [0..127] + aorai_y1 ∈ [0..127] + aorai_y2 ∈ [0..127] + aorai_CurOperation ∈ {op_input_status; op_input_data} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5} + aorai_StatesHistory_1 ∈ [1..6] ∪ [14..18] + aorai_StatesHistory_2 ∈ {0} ∪ [8..13] ∪ [19..23] [eva:final-states] Values at end of function main: Frama_C_entropy_source ∈ [--..--] - buffer[0] ∈ - {0; 128; 129; 130; 131; 132; 133; 134; 135; 136; 137; 138; 139; 140; - 141; 142; 143; 144; 145; 146; 147; 148; 149; 150; 151; 152; 153; - 154; 155; 156; 157; 158; 159; 160; 161; 162; 163; 164; 165; 166; - 167; 168; 169; 170; 171; 172; 173; 174; 175; 176; 177; 178; 179; - 180; 181; 182; 183; 184; 185; 186; 187; 188; 189; 190; 191; 192; - 193; 194; 195; 196; 197; 198; 199; 200; 201; 202; 203; 204; 205; - 206; 207; 208; 209; 210; 211; 212; 213; 214; 215; 216; 217; 218; - 219; 220; 221; 222; 223; 224; 225; 226; 227; 228; 229; 230; 231; - 232; 233; 234; 235; 236; 237; 238; 239; 240; 241; 242; 243; 244; - 245; 246; 247; 248; 249; 250; 251; 252; 253; 254; 255} - [1..2] ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; 35; - 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; 51; 52; - 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; 67; 68; 69; - 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; 83; 84; 85; 86; - 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; 99; 100; 101; 102; - 103; 104; 105; 106; 107; 108; 109; 110; 111; 112; 113; 114; 115; - 116; 117; 118; 119; 120; 121; 122; 123; 124; 125; 126; 127} - [3..4] ∈ [0..2147483647] + buffer[0] ∈ {0} ∪ [128..255] + [1..4] ∈ [0..127] n ∈ {0; 1; 2; 3; 4} - aorai_x1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_x2 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y1 ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47; 48; 49; 50; - 51; 52; 53; 54; 55; 56; 57; 58; 59; 60; 61; 62; 63; 64; 65; 66; - 67; 68; 69; 70; 71; 72; 73; 74; 75; 76; 77; 78; 79; 80; 81; 82; - 83; 84; 85; 86; 87; 88; 89; 90; 91; 92; 93; 94; 95; 96; 97; 98; - 99; 100; 101; 102; 103; 104; 105; 106; 107; 108; 109; 110; 111; - 112; 113; 114; 115; 116; 117; 118; 119; 120; 121; 122; 123; 124; - 125; 126; 127} - aorai_y2 ∈ [0..2147483647] - aorai_CurOperation ∈ {0; 1; 2} - aorai_CurOpStatus ∈ {0; 1} - aorai_CurStates ∈ {0; 19; 20; 21; 22; 23} - aorai_StatesHistory_1 ∈ {1; 2; 3; 4; 5; 6; 14; 15; 16; 17; 18; 19} - aorai_StatesHistory_2 ∈ {0; 8; 9; 10; 11; 12; 13; 19; 20; 21; 22; 23} + aorai_x1 ∈ [0..127] + aorai_x2 ∈ [0..127] + aorai_y1 ∈ [0..127] + aorai_y2 ∈ [0..127] + aorai_CurOperation ∈ {op_output; op_input_status; op_input_data} + aorai_CurOpStatus ∈ {aorai_Called; aorai_Terminated} + aorai_CurStates ∈ {Complete; Wait1; Wait2; Wait3; Wait4; Wait5} + aorai_StatesHistory_1 ∈ [1..6] ∪ [14..19] + aorai_StatesHistory_2 ∈ {0} ∪ [8..13] ∪ [19..23] [eva:summary] ====== ANALYSIS SUMMARY ====== ---------------------------------------------------------------------------- 11 functions analyzed (out of 11): 100% coverage. @@ -344,7 +202,7 @@ int buffer[5]; int n = 0; /*@ ghost enum aorai_ListOper aorai_CurOperation; */ /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */ -/*@ ghost int aorai_CurStates = Wait1; */ +/*@ ghost enum aorai_States aorai_CurStates = Wait1; */ /*@ ghost int aorai_StatesHistory_1 = Wait1; */ /*@ ghost int aorai_StatesHistory_2 = Wait1; */ /*@ ghost int aorai_x1 = 0; */ @@ -355,33 +213,34 @@ int n = 0; void input_status_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_input_status; aorai_StatesHistory_2 = aorai_StatesHistory_1; - aorai_StatesHistory_1 = aorai_CurStates; - if (19 == aorai_CurStates) aorai_CurStates = StatusReq1; + aorai_StatesHistory_1 = (int)aorai_CurStates; + if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = StatusReq1; else - if (9 == aorai_CurStates) aorai_CurStates = StatusReq1; + if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = StatusReq1; else - if (8 == aorai_CurStates) aorai_CurStates = StatusReq1; + if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = StatusReq1; else - if (0 == aorai_CurStates) aorai_CurStates = StatusReq1; + if ((unsigned int)0 == aorai_CurStates) aorai_CurStates = StatusReq1; else - if (20 == aorai_CurStates) aorai_CurStates = StatusReq2; + if ((unsigned int)20 == aorai_CurStates) aorai_CurStates = StatusReq2; else - if (10 == aorai_CurStates) aorai_CurStates = StatusReq2; + if ((unsigned int)10 == aorai_CurStates) aorai_CurStates = StatusReq2; else - if (21 == aorai_CurStates) aorai_CurStates = StatusReq3; + if ((unsigned int)21 == aorai_CurStates) aorai_CurStates = StatusReq3; else - if (11 == aorai_CurStates) aorai_CurStates = StatusReq3; + if ((unsigned int)11 == aorai_CurStates) aorai_CurStates = StatusReq3; else - if (22 == aorai_CurStates) aorai_CurStates = StatusReq4; + if ((unsigned int)22 == aorai_CurStates) aorai_CurStates = StatusReq4; else - if (12 == aorai_CurStates) aorai_CurStates = StatusReq4; + if ((unsigned int)12 == aorai_CurStates) aorai_CurStates = StatusReq4; else - if (23 == aorai_CurStates) aorai_CurStates = StatusReq5; + if ((unsigned int)23 == aorai_CurStates) aorai_CurStates = StatusReq5; else - if (13 == aorai_CurStates) aorai_CurStates = StatusReq5; + if ((unsigned int)13 == aorai_CurStates) aorai_CurStates = StatusReq5; else aorai_CurStates = aorai_reject; /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/ ; @@ -394,111 +253,112 @@ int n = 0; void input_status_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_input_status; aorai_StatesHistory_2 = aorai_StatesHistory_1; - aorai_StatesHistory_1 = aorai_CurStates; - if (18 == aorai_CurStates) { - if ((res & 15) != 1) { - if ((res & 1) != 0) aorai_CurStates = StatusError; + aorai_StatesHistory_1 = (int)aorai_CurStates; + if ((unsigned int)18 == aorai_CurStates) { + if ((res & 0b1111) != 1) { + if ((res & 0b0001) != 0) aorai_CurStates = StatusError; else goto __aorai_label_12; } else goto __aorai_label_12; } else { __aorai_label_12: ; - if (17 == aorai_CurStates) { - if ((res & 15) != 1) { - if ((res & 1) != 0) aorai_CurStates = StatusError; + if ((unsigned int)17 == aorai_CurStates) { + if ((res & 0b1111) != 1) { + if ((res & 0b0001) != 0) aorai_CurStates = StatusError; else goto __aorai_label_11; } else goto __aorai_label_11; } else { __aorai_label_11: ; - if (16 == aorai_CurStates) { - if ((res & 15) != 1) { - if ((res & 1) != 0) aorai_CurStates = StatusError; + if ((unsigned int)16 == aorai_CurStates) { + if ((res & 0b1111) != 1) { + if ((res & 0b0001) != 0) aorai_CurStates = StatusError; else goto __aorai_label_10; } else goto __aorai_label_10; } else { __aorai_label_10: ; - if (15 == aorai_CurStates) { - if ((res & 15) != 1) { - if ((res & 1) != 0) aorai_CurStates = StatusError; + if ((unsigned int)15 == aorai_CurStates) { + if ((res & 0b1111) != 1) { + if ((res & 0b0001) != 0) aorai_CurStates = StatusError; else goto __aorai_label_9; } else goto __aorai_label_9; } else { __aorai_label_9: ; - if (14 == aorai_CurStates) { - if ((res & 15) != 1) { - if ((res & 1) != 0) aorai_CurStates = StatusError; + if ((unsigned int)14 == aorai_CurStates) { + if ((res & 0b1111) != 1) { + if ((res & 0b0001) != 0) aorai_CurStates = StatusError; else goto __aorai_label_8; } else goto __aorai_label_8; } else { __aorai_label_8: ; - if (14 == aorai_CurStates) { - if ((res & 15) == 1) aorai_CurStates = StatusOk1; + if ((unsigned int)14 == aorai_CurStates) { + if ((res & 0b1111) == 1) aorai_CurStates = StatusOk1; else goto __aorai_label_7; } else { __aorai_label_7: ; - if (15 == aorai_CurStates) { - if ((res & 15) == 1) aorai_CurStates = StatusOk2; + if ((unsigned int)15 == aorai_CurStates) { + if ((res & 0b1111) == 1) aorai_CurStates = StatusOk2; else goto __aorai_label_6; } else { __aorai_label_6: ; - if (16 == aorai_CurStates) { - if ((res & 15) == 1) aorai_CurStates = StatusOk3; + if ((unsigned int)16 == aorai_CurStates) { + if ((res & 0b1111) == 1) aorai_CurStates = StatusOk3; else goto __aorai_label_5; } else { __aorai_label_5: ; - if (17 == aorai_CurStates) { - if ((res & 15) == 1) aorai_CurStates = StatusOk4; + if ((unsigned int)17 == aorai_CurStates) { + if ((res & 0b1111) == 1) aorai_CurStates = StatusOk4; else goto __aorai_label_4; } else { __aorai_label_4: ; - if (18 == aorai_CurStates) { - if ((res & 15) == 1) aorai_CurStates = StatusOk5; + if ((unsigned int)18 == aorai_CurStates) { + if ((res & 0b1111) == 1) aorai_CurStates = StatusOk5; else goto __aorai_label_3; } else { __aorai_label_3: ; - if (14 == aorai_CurStates) { - if ((res & 1) == 0) aorai_CurStates = Wait1; + if ((unsigned int)14 == aorai_CurStates) { + if ((res & 0b0001) == 0) aorai_CurStates = Wait1; else goto __aorai_label_2; } else { __aorai_label_2: ; - if (15 == aorai_CurStates) { - if ((res & 1) == 0) aorai_CurStates = Wait2; + if ((unsigned int)15 == aorai_CurStates) { + if ((res & 0b0001) == 0) aorai_CurStates = Wait2; else goto __aorai_label_1; } else { __aorai_label_1: ; - if (16 == aorai_CurStates) { - if ((res & 1) == 0) aorai_CurStates = Wait3; + if ((unsigned int)16 == aorai_CurStates) { + if ((res & 0b0001) == 0) aorai_CurStates = Wait3; else goto __aorai_label_0; } else { __aorai_label_0: ; - if (17 == aorai_CurStates) { - if ((res & 1) == 0) aorai_CurStates = Wait4; + if ((unsigned int)17 == aorai_CurStates) { + if ((res & 0b0001) == 0) aorai_CurStates = Wait4; else goto __aorai_label; } else { __aorai_label: ; - if (18 == aorai_CurStates) - if ((res & 1) == 0) aorai_CurStates = Wait5; + if ((unsigned int)18 == aorai_CurStates) + if ((res & 0b0001) == 0) aorai_CurStates = Wait5; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; } @@ -540,31 +400,32 @@ int input_status(void) void input_data_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_input_data; aorai_StatesHistory_2 = aorai_StatesHistory_1; - aorai_StatesHistory_1 = aorai_CurStates; - if (9 == aorai_CurStates) aorai_CurStates = DataReq1; + aorai_StatesHistory_1 = (int)aorai_CurStates; + if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = DataReq1; else - if (10 == aorai_CurStates) aorai_CurStates = DataReq2; + if ((unsigned int)10 == aorai_CurStates) aorai_CurStates = DataReq2; else - if (11 == aorai_CurStates) aorai_CurStates = DataReq3; + if ((unsigned int)11 == aorai_CurStates) aorai_CurStates = DataReq3; else - if (12 == aorai_CurStates) aorai_CurStates = DataReq4; + if ((unsigned int)12 == aorai_CurStates) aorai_CurStates = DataReq4; else - if (13 == aorai_CurStates) aorai_CurStates = DataReq5; + if ((unsigned int)13 == aorai_CurStates) aorai_CurStates = DataReq5; else - if (8 == aorai_CurStates) aorai_CurStates = DataReqE; + if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = DataReqE; else - if (23 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)23 == aorai_CurStates) aorai_CurStates = Error; else - if (22 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)22 == aorai_CurStates) aorai_CurStates = Error; else - if (21 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)21 == aorai_CurStates) aorai_CurStates = Error; else - if (20 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)20 == aorai_CurStates) aorai_CurStates = Error; else - if (19 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = Error; else aorai_CurStates = aorai_reject; /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/ ; @@ -577,12 +438,13 @@ int input_status(void) void input_data_post_func(int res) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_input_data; aorai_StatesHistory_2 = aorai_StatesHistory_1; - aorai_StatesHistory_1 = aorai_CurStates; - if (5 == aorai_CurStates) { - if ((res & 128) == 0) { + aorai_StatesHistory_1 = (int)aorai_CurStates; + if ((unsigned int)5 == aorai_CurStates) { + if ((res & 0b10000000) == 0b00000000) { aorai_CurStates = Complete; aorai_y2 = res; } @@ -590,76 +452,76 @@ int input_status(void) } else __aorai_label_26: - if (6 == aorai_CurStates) aorai_CurStates = Wait1; + if ((unsigned int)6 == aorai_CurStates) aorai_CurStates = Wait1; else - if (5 == aorai_CurStates) { - if ((res & 192) == 192) aorai_CurStates = Wait1; + if ((unsigned int)5 == aorai_CurStates) { + if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1; else goto __aorai_label_25; } else { __aorai_label_25: ; - if (4 == aorai_CurStates) { - if ((res & 192) == 192) aorai_CurStates = Wait1; + if ((unsigned int)4 == aorai_CurStates) { + if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1; else goto __aorai_label_24; } else { __aorai_label_24: ; - if (3 == aorai_CurStates) { - if ((res & 192) == 192) aorai_CurStates = Wait1; + if ((unsigned int)3 == aorai_CurStates) { + if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1; else goto __aorai_label_23; } else { __aorai_label_23: ; - if (2 == aorai_CurStates) { - if ((res & 192) == 192) aorai_CurStates = Wait1; + if ((unsigned int)2 == aorai_CurStates) { + if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1; else goto __aorai_label_22; } else { __aorai_label_22: ; - if (1 == aorai_CurStates) { - if ((res & 128) == 0) aorai_CurStates = Wait1; + if ((unsigned int)1 == aorai_CurStates) { + if ((res & 0b10000000) == 0b00000000) aorai_CurStates = Wait1; else goto __aorai_label_21; } else { __aorai_label_21: ; - if (1 == aorai_CurStates) { - if ((res & 192) == 192) aorai_CurStates = Wait1; + if ((unsigned int)1 == aorai_CurStates) { + if ((res & 0b11000000) == 0b11000000) aorai_CurStates = Wait1; else goto __aorai_label_20; } else { __aorai_label_20: ; - if (5 == aorai_CurStates) { - if ((res & 192) == 128) aorai_CurStates = Wait2; + if ((unsigned int)5 == aorai_CurStates) { + if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2; else goto __aorai_label_19; } else { __aorai_label_19: ; - if (4 == aorai_CurStates) { - if ((res & 192) == 128) aorai_CurStates = Wait2; + if ((unsigned int)4 == aorai_CurStates) { + if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2; else goto __aorai_label_18; } else { __aorai_label_18: ; - if (3 == aorai_CurStates) { - if ((res & 192) == 128) aorai_CurStates = Wait2; + if ((unsigned int)3 == aorai_CurStates) { + if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2; else goto __aorai_label_17; } else { __aorai_label_17: ; - if (2 == aorai_CurStates) { - if ((res & 192) == 128) aorai_CurStates = Wait2; + if ((unsigned int)2 == aorai_CurStates) { + if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2; else goto __aorai_label_16; } else { __aorai_label_16: ; - if (1 == aorai_CurStates) { - if ((res & 192) == 128) aorai_CurStates = Wait2; + if ((unsigned int)1 == aorai_CurStates) { + if ((res & 0b11000000) == 0b10000000) aorai_CurStates = Wait2; else goto __aorai_label_15; } else { __aorai_label_15: ; - if (2 == aorai_CurStates) { - if ((res & 128) == 0) { + if ((unsigned int)2 == aorai_CurStates) { + if ((res & 0b10000000) == 0b00000000) { aorai_CurStates = Wait3; aorai_x1 = res; } @@ -667,8 +529,8 @@ int input_status(void) } else { __aorai_label_14: ; - if (3 == aorai_CurStates) { - if ((res & 128) == 0) { + if ((unsigned int)3 == aorai_CurStates) { + if ((res & 0b10000000) == 0b00000000) { aorai_CurStates = Wait4; aorai_x2 = res; } @@ -676,8 +538,8 @@ int input_status(void) } else { __aorai_label_13: ; - if (4 == aorai_CurStates) - if ((res & 128) == 0) { + if ((unsigned int)4 == aorai_CurStates) + if ((res & 0b10000000) == 0b00000000) { aorai_CurStates = Wait5; aorai_y1 = res; } @@ -721,33 +583,34 @@ int input_data(void) void output_pre_func(int x, int y) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_output; aorai_StatesHistory_2 = aorai_StatesHistory_1; - aorai_StatesHistory_1 = aorai_CurStates; - if (23 == aorai_CurStates) aorai_CurStates = Error; + aorai_StatesHistory_1 = (int)aorai_CurStates; + if ((unsigned int)23 == aorai_CurStates) aorai_CurStates = Error; else - if (22 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)22 == aorai_CurStates) aorai_CurStates = Error; else - if (21 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)21 == aorai_CurStates) aorai_CurStates = Error; else - if (20 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)20 == aorai_CurStates) aorai_CurStates = Error; else - if (19 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = Error; else - if (13 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)13 == aorai_CurStates) aorai_CurStates = Error; else - if (12 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)12 == aorai_CurStates) aorai_CurStates = Error; else - if (11 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)11 == aorai_CurStates) aorai_CurStates = Error; else - if (10 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)10 == aorai_CurStates) aorai_CurStates = Error; else - if (9 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)9 == aorai_CurStates) aorai_CurStates = Error; else - if (8 == aorai_CurStates) aorai_CurStates = Error; + if ((unsigned int)8 == aorai_CurStates) aorai_CurStates = Error; else - if (0 == aorai_CurStates) { + if ((unsigned int)0 == aorai_CurStates) { if (y != aorai_y1 + 128 * aorai_y2) aorai_CurStates = Error; else if (x != aorai_x1 + 128 * aorai_x2) aorai_CurStates = Error; @@ -755,7 +618,7 @@ int input_data(void) } else { __aorai_label_27: ; - if (0 == aorai_CurStates) + if ((unsigned int)0 == aorai_CurStates) if (x == aorai_x1 + 128 * aorai_x2) if (y == aorai_y1 + 128 * aorai_y2) aorai_CurStates = Wait1; else aorai_CurStates = aorai_reject; @@ -773,11 +636,12 @@ int input_data(void) void output_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_output; aorai_StatesHistory_2 = aorai_StatesHistory_1; - aorai_StatesHistory_1 = aorai_CurStates; - if (19 == aorai_CurStates) aorai_CurStates = Wait1; + aorai_StatesHistory_1 = (int)aorai_CurStates; + if ((unsigned int)19 == aorai_CurStates) aorai_CurStates = Wait1; else aorai_CurStates = aorai_reject; /@ assert Aorai: aorai_smoke_test: aorai_CurStates ≢ aorai_reject; @/ ; @@ -827,11 +691,10 @@ void main(void) n = 0; continue; } - } - else { /*@ split data & 0x40; */ ; - if (n == 0) continue; } + else + if (n == 0) continue; tmp_0 = n; n ++; buffer[tmp_0] = data; diff --git a/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle b/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle index 2b50360158fb85efec7991a9ae0405c2d4cf4af8..e59b671a435d7944dbe7c3aa9757b967206ebaad 100644 --- a/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/single_call.res.oracle @@ -55,6 +55,7 @@ enum aorai_OpStatusList { int Sf_tmp; int aorai_intermediate_state_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S0_tmp = S0; @@ -114,6 +115,7 @@ enum aorai_OpStatusList { int Sf_tmp; int aorai_intermediate_state_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S0_tmp = S0; diff --git a/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle b/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle index d717c70ab7b748be473e7a0955c84cfcc0b6db66..da7359cdf61dccd1fcf9f8ce3f6696cc4032efb4 100644 --- a/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/singleassignment-right.res.oracle @@ -24,7 +24,7 @@ enum aorai_OpStatusList { */ /*@ ghost enum aorai_ListOper aorai_CurOperation; */ /*@ ghost enum aorai_OpStatusList aorai_CurOpStatus; */ -/*@ ghost int aorai_CurStates = a; */ +/*@ ghost enum aorai_States aorai_CurStates = a; */ /*@ ghost int aorai_x = 0; */ /*@ ghost int aorai_y = 0; */ /*@ ghost @@ -70,9 +70,10 @@ enum aorai_OpStatusList { void main_pre_func(int *x, int *y) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (0 == aorai_CurStates) { + if ((unsigned int)0 == aorai_CurStates) { aorai_CurStates = b; aorai_x = *x; aorai_y = *y; @@ -126,9 +127,10 @@ enum aorai_OpStatusList { void main_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (2 == aorai_CurStates) { + if ((unsigned int)2 == aorai_CurStates) { aorai_CurStates = c; aorai_x = aorai_y; aorai_y = aorai_x; diff --git a/src/plugins/aorai/tests/ya/oracle/stack.res.oracle b/src/plugins/aorai/tests/ya/oracle/stack.res.oracle index cb79a5bd6d3f22ae4aa1fa8937b34a8114114863..4071686554d5628c250e63e0f5ae8ba494fb2903 100644 --- a/src/plugins/aorai/tests/ya/oracle/stack.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/stack.res.oracle @@ -37,7 +37,7 @@ check lemma empty_stack_deterministic_trans{L}: \at(aorai_CurOperation,L) ≡ op_main ∧ \at(aorai_CurOpStatus,L) ≡ aorai_Terminated); */ -/*@ ghost int aorai_CurStates = init; */ +/*@ ghost enum aorai_States aorai_CurStates = init; */ /*@ ghost int aorai_n = 0; */ /*@ check lemma filled_stack_deterministic_trans{L}: @@ -97,11 +97,12 @@ check lemma emptying_stack_deterministic_trans{L}: void push_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_push; - if (4 == aorai_CurStates) aorai_CurStates = filling_stack; + if ((unsigned int)4 == aorai_CurStates) aorai_CurStates = filling_stack; else - if (2 == aorai_CurStates) aorai_CurStates = filling_stack; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = filling_stack; else aorai_CurStates = aorai_reject; return; } @@ -155,9 +156,10 @@ check lemma emptying_stack_deterministic_trans{L}: void push_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_push; - if (5 == aorai_CurStates) { + if ((unsigned int)5 == aorai_CurStates) { aorai_CurStates = filled_stack; aorai_n ++; } @@ -235,9 +237,10 @@ void push(void) void pop_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_pop; - if (4 == aorai_CurStates) + if ((unsigned int)4 == aorai_CurStates) if (aorai_n > 0) aorai_CurStates = emptying_stack; else aorai_CurStates = aorai_reject; else aorai_CurStates = aorai_reject; @@ -301,9 +304,10 @@ void push(void) void pop_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_pop; - if (3 == aorai_CurStates) { + if ((unsigned int)3 == aorai_CurStates) { if (aorai_n == 1) { aorai_CurStates = empty_stack; aorai_n --; @@ -312,7 +316,7 @@ void push(void) } else { __aorai_label: ; - if (3 == aorai_CurStates) + if ((unsigned int)3 == aorai_CurStates) if (aorai_n > 1) { aorai_CurStates = filled_stack; aorai_n --; @@ -398,9 +402,10 @@ void pop(void) void main_pre_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; - if (6 == aorai_CurStates) { + if ((unsigned int)6 == aorai_CurStates) { aorai_CurStates = empty_stack; aorai_n = 0; } @@ -451,9 +456,10 @@ void pop(void) void main_post_func(void) { /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; - if (2 == aorai_CurStates) aorai_CurStates = accept; + if ((unsigned int)2 == aorai_CurStates) aorai_CurStates = accept; else aorai_CurStates = aorai_reject; return; } diff --git a/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle index c2fc72913e5f6c258e29064424942812828bf85e..e31ea6083264fd52bf1004dc3636195c6286f40f 100644 --- a/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/test_acces_params.res.oracle @@ -88,6 +88,7 @@ int rr = 1; int SF_tmp; int mainst_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_opa; S1_tmp = S1; @@ -180,6 +181,7 @@ int rr = 1; int SF_tmp; int mainst_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_opa; S1_tmp = S1; @@ -292,6 +294,7 @@ void opa(int i, int j) int SF_tmp; int mainst_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_opb; S1_tmp = S1; @@ -383,6 +386,7 @@ void opa(int i, int j) int SF_tmp; int mainst_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_opb; S1_tmp = S1; @@ -495,6 +499,7 @@ int opb(void) int SF_tmp; int mainst_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S1_tmp = S1; @@ -585,6 +590,7 @@ int opb(void) int SF_tmp; int mainst_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S1_tmp = S1; diff --git a/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle index 59019d29de575c9d3c002abce06057b5d09f7361..6b1289c2a6d4bd4088ecc020cf530f9a0f6afbb1 100644 --- a/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/test_acces_params2.res.oracle @@ -96,6 +96,7 @@ int rr = 1; int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_opa; S1_tmp = S1; @@ -199,6 +200,7 @@ int rr = 1; int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_opa; S1_tmp = S1; @@ -326,6 +328,7 @@ int opa(int r) int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_opb; S1_tmp = S1; @@ -426,6 +429,7 @@ int opa(int r) int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_opb; S1_tmp = S1; @@ -541,6 +545,7 @@ void opb(void) int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_opc; S1_tmp = S1; @@ -634,6 +639,7 @@ void opb(void) int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_opc; S1_tmp = S1; @@ -768,6 +774,7 @@ void opc(void) int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S1_tmp = S1; @@ -868,6 +875,7 @@ void opc(void) int S6_tmp; int S7_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S1_tmp = S1; diff --git a/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle index 1431fa716c3b4d91756d07526ea2c633f1174e1f..bc444e4bbcc155c9a6583fa490dc91905ea42ea4 100644 --- a/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/test_boucle_rechercheTableau.res.oracle @@ -55,6 +55,7 @@ enum aorai_OpStatusList { int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_isPresent; End_tmp = End; @@ -113,6 +114,7 @@ enum aorai_OpStatusList { int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_isPresent; End_tmp = End; @@ -225,6 +227,7 @@ int isPresent(int *t, int max, int val) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_foo; End_tmp = End; @@ -277,6 +280,7 @@ int isPresent(int *t, int max, int val) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_foo; End_tmp = End; @@ -342,6 +346,7 @@ void foo(void) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; End_tmp = End; @@ -394,6 +399,7 @@ void foo(void) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; End_tmp = End; diff --git a/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle index 56ba35bfc725a9e244a5be663abe9017446ccff9..429ca9bc1e86351a9db4ad2e0433457dd3de6063 100644 --- a/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/test_factorial.res.oracle @@ -49,6 +49,7 @@ enum aorai_OpStatusList { int S2_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_decode_int; S1_tmp = S1; @@ -104,6 +105,7 @@ enum aorai_OpStatusList { int S2_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_decode_int; S1_tmp = S1; @@ -234,6 +236,7 @@ int decode_int(char *s) int S2_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_factorial; S1_tmp = S1; @@ -291,6 +294,7 @@ int decode_int(char *s) int S2_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_factorial; S1_tmp = S1; @@ -372,6 +376,7 @@ int factorial(int value) int S2_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S1_tmp = S1; @@ -427,6 +432,7 @@ int factorial(int value) int S2_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S1_tmp = S1; diff --git a/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle index 8c9faad26773d78513719836e6856f9cfd4abbb8..58125fc6e68b3c1c0076f63159238ddf0660ea4e 100644 --- a/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/test_recursion4.res.oracle @@ -52,6 +52,7 @@ enum aorai_OpStatusList { int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_isPresent; End_tmp = End; @@ -116,6 +117,7 @@ enum aorai_OpStatusList { int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_isPresent; End_tmp = End; @@ -231,6 +233,7 @@ int isPresent(int *t, int size, int val) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_foo; End_tmp = End; @@ -283,6 +286,7 @@ int isPresent(int *t, int size, int val) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_foo; End_tmp = End; @@ -348,6 +352,7 @@ void foo(void) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; End_tmp = End; @@ -400,6 +405,7 @@ void foo(void) int Idle_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; End_tmp = End; diff --git a/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle index c7e017d08d504c11ddbf2c410794c4ab96b2c667..84601f1f62169f47d3e5cd4cebb7a384a421f840 100644 --- a/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/test_recursion5.res.oracle @@ -71,6 +71,7 @@ enum aorai_OpStatusList { int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_isPresentRec; End_tmp = End; @@ -154,6 +155,7 @@ enum aorai_OpStatusList { int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_isPresentRec; End_tmp = End; @@ -285,6 +287,7 @@ int isPresentRec(int *t, int i, int max, int val) int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_isPresent; End_tmp = End; @@ -361,6 +364,7 @@ int isPresentRec(int *t, int i, int max, int val) int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_isPresent; End_tmp = End; @@ -463,6 +467,7 @@ int isPresent(int *t, int max, int val) int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_foo; End_tmp = End; @@ -532,6 +537,7 @@ int isPresent(int *t, int max, int val) int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_foo; End_tmp = End; @@ -615,6 +621,7 @@ void foo(void) int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; End_tmp = End; @@ -684,6 +691,7 @@ void foo(void) int IgnoreFoo_tmp; int WillDoFoo_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; End_tmp = End; diff --git a/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle b/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle index 541b2c925a348a01a2ed36158f45f14207a5d55a..ecdc65fc67cbbff2acf74871a9420f36ed70efc1 100644 --- a/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle +++ b/src/plugins/aorai/tests/ya/oracle/test_struct.res.oracle @@ -50,6 +50,7 @@ int myAge = 0; int S1_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_increment; S1_tmp = S1; @@ -96,6 +97,7 @@ int myAge = 0; int S1_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_increment; S1_tmp = S1; @@ -159,6 +161,7 @@ void increment(void) int S1_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Called; aorai_CurOperation = op_main; S1_tmp = S1; @@ -205,6 +208,7 @@ void increment(void) int S1_tmp; int main_0_tmp; /@ slevel full; @/ + ; aorai_CurOpStatus = aorai_Terminated; aorai_CurOperation = op_main; S1_tmp = S1; diff --git a/src/plugins/aorai/tests/ya/oracle_prove/floats.res.oracle b/src/plugins/aorai/tests/ya/oracle_prove/floats.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..28b4a5aa18615ebfd8af4e80290b8e8385453f1c --- /dev/null +++ b/src/plugins/aorai/tests/ya/oracle_prove/floats.res.oracle @@ -0,0 +1,87 @@ +[kernel] Parsing floats.i (no preprocessing) +[kernel:parser:decimal-float] floats.i:8: Warning: + Floating-point constant 0.001 is not represented exactly. Will use 0x1.0624dd2f1a9fcp-10. + (warn-once: no further messages from category 'parser:decimal-float' will be emitted) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {I} +[eva:recursion] floats.i:11: + detected recursive call of function square_root_aux. +[eva] floats.i:11: Warning: + Using specification of function square_root_aux for recursive calls. + Analysis of function square_root_aux is thus incomplete and its soundness + relies on the written specification. +[eva] using specification for function square_root_aux +[eva] floats.i:6: Warning: + no \from part + for clause 'assigns aorai_CurOpStatus, aorai_CurOperation, aorai_CurStates;' +[eva:alarm] :0: Warning: + function square_root_aux, behavior Buchi_property_behavior: postcondition got status unknown. +[eva:alarm] floats.i:11: Warning: + non-finite float value. + assert \is_finite(tmp); + (tmp from square_root_aux(y, n)) +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main_post_func: + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {E} +[eva:final-states] Values at end of function main_pre_func: + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {A} +[eva:final-states] Values at end of function square_root_aux_post_func: + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root_aux_pre_func: + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root_post_func: + aorai_CurOperation ∈ {op_square_root} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {C} +[eva:final-states] Values at end of function square_root_pre_func: + aorai_CurOperation ∈ {op_square_root} + aorai_CurOpStatus ∈ {aorai_Called} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root_aux: + y ∈ {1.5} + __retres ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + aorai_CurOperation ∈ {op_square_root_aux} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {B} +[eva:final-states] Values at end of function square_root: + aorai_CurOperation ∈ {op_square_root} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {C} +[eva:final-states] Values at end of function main: + r ∈ [-3.40282346639e+38 .. 3.40282346639e+38] + aorai_CurOperation ∈ {op_main} + aorai_CurOpStatus ∈ {aorai_Terminated} + aorai_CurStates ∈ {E} +[eva:summary] ====== ANALYSIS SUMMARY ====== + ---------------------------------------------------------------------------- + 9 functions analyzed (out of 9): 100% coverage. + In these functions, 53 statements reached (out of 67): 79% coverage. + ---------------------------------------------------------------------------- + Some errors and warnings have been raised during the analysis: + by the Eva analyzer: 0 errors 2 warnings + by the Frama-C kernel: 0 errors 0 warnings + ---------------------------------------------------------------------------- + 1 alarm generated by the analysis: + 1 nan or infinite floating-point value + ---------------------------------------------------------------------------- + Evaluation of the logical properties reached by the analysis: + Assertions 0 valid 0 unknown 0 invalid 0 total + Preconditions 10 valid 2 unknown 0 invalid 12 total + 83% of the logical properties reached have been proven. + ---------------------------------------------------------------------------- +[kernel] Parsing TMPDIR/aorai_floats_0_prove.i (no preprocessing) +[wp] Warning: Missing RTE guards diff --git a/src/plugins/aorai/tests/ya/serial.ya b/src/plugins/aorai/tests/ya/serial.ya index 6e893819100f43bfb1a18da1cd6e2ecdfdf44bc7..adeff98b92d49c535e3f8588b31cfcaa14041f4b 100644 --- a/src/plugins/aorai/tests/ya/serial.ya +++ b/src/plugins/aorai/tests/ya/serial.ya @@ -9,6 +9,9 @@ $y2 : int; Error : { 0 == 1 } -> Error; +/* In these states, the program is waiting for a status indicating that + data can be read */ + Wait1 : { CALL(input_status) } -> StatusReq1 | { CALL(input_data) } -> Error @@ -44,33 +47,35 @@ Wait5 : | other -> Wait5 ; +// The status have been requested, waiting for response + StatusReq1 : - { input_status().\result & 1 == 0 } -> Wait1 -| { input_status().\result & 15 == 1 } -> StatusOk1 + { input_status().\result & 0b0001 == 0 } -> Wait1 +| { input_status().\result & 0b1111 == 1 } -> StatusOk1 | other -> StatusError ; StatusReq2 : - { input_status().\result & 1 == 0 } -> Wait2 -| { input_status().\result & 15 == 1 } -> StatusOk2 + { input_status().\result & 0b0001 == 0 } -> Wait2 +| { input_status().\result & 0b1111 == 1 } -> StatusOk2 | other -> StatusError ; StatusReq3 : - { input_status().\result & 1 == 0 } -> Wait3 -| { input_status().\result & 15 == 1 } -> StatusOk3 + { input_status().\result & 0b0001 == 0 } -> Wait3 +| { input_status().\result & 0b1111 == 1 } -> StatusOk3 | other -> StatusError ; StatusReq4 : - { input_status().\result & 1 == 0 } -> Wait4 -| { input_status().\result & 15 == 1 } -> StatusOk4 + { input_status().\result & 0b0001 == 0 } -> Wait4 +| { input_status().\result & 0b1111 == 1 } -> StatusOk4 | other -> StatusError ; StatusReq5 : - { input_status().\result & 1 == 0 } -> Wait5 -| { input_status().\result & 15 == 1 } -> StatusOk5 + { input_status().\result & 0b0001 == 0 } -> Wait5 +| { input_status().\result & 0b1111 == 1 } -> StatusOk5 | other -> StatusError ; @@ -81,6 +86,8 @@ StatusError : | other -> StatusError ; +// Ok status have been received, data can be read + StatusOk1 : { CALL(input_status) } -> StatusReq1 | { CALL(input_data) } -> DataReq1 @@ -116,40 +123,44 @@ StatusOk5 : | other -> StatusOk5 ; +// Data have been requested + DataReqE : { RETURN(input_data) } -> Wait1 ; DataReq1 : - { input_data().\result & 192 == 128 } -> Wait2 -| { input_data().\result & 192 == 192 } -> Wait1 -| { input_data().\result & 128 == 0 } -> Wait1 + { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2 +| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1 +| { input_data().\result & 0b10000000 == 0b00000000 } -> Wait1 ; DataReq2 : - { input_data().\result & 192 == 128 } -> Wait2 -| { input_data().\result & 192 == 192 } -> Wait1 -| { input_data().\result & 128 == 0 } $x1 := \result; -> Wait3 + { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2 +| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1 +| { input_data().\result & 0b10000000 == 0b00000000 } $x1 := \result; -> Wait3 ; DataReq3 : - { input_data().\result & 192 == 128 } -> Wait2 -| { input_data().\result & 192 == 192 } -> Wait1 -| { input_data().\result & 128 == 0 } $x2 := \result; -> Wait4 + { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2 +| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1 +| { input_data().\result & 0b10000000 == 0b00000000 } $x2 := \result; -> Wait4 ; DataReq4 : - { input_data().\result & 192 == 128 } -> Wait2 -| { input_data().\result & 192 == 192 } -> Wait1 -| { input_data().\result & 128 == 0 } $y1 := \result; -> Wait5 + { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2 +| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1 +| { input_data().\result & 0b10000000 == 0b00000000 } $y1 := \result; -> Wait5 ; DataReq5 : - { input_data().\result & 192 == 128 } -> Wait2 -| { input_data().\result & 192 == 192 } -> Wait1 -| { input_data().\result & 128 == 0 } $y2 := \result; -> Complete + { input_data().\result & 0b11000000 == 0b10000000 } -> Wait2 +| { input_data().\result & 0b11000000 == 0b11000000 } -> Wait1 +| { input_data().\result & 0b10000000 == 0b00000000 } $y2 := \result; -> Complete ; +/* The sequence of 5 bytes read is complete */ + Complete : { CALL(output) && output().x == $x1 + 128 * $x2 && output().y == $y1 + 128 * $y2 } -> Wait1 | { CALL(output) && (output().x != $x1 + 128 * $x2 || output().y != $y1 + 128 * $y2) } -> Error diff --git a/src/plugins/aorai/utils_parser.ml b/src/plugins/aorai/utils_parser.ml index d84bf49a1871ae97d520841f78fdfa7c19c3f0d8..e12815ab464a6ec87380121b1c7dbb4425a73680 100644 --- a/src/plugins/aorai/utils_parser.ml +++ b/src/plugins/aorai/utils_parser.ml @@ -43,3 +43,7 @@ let newline lexbuf = let pos = lexbuf.lex_curr_p in lexbuf.lex_curr_p <- { pos with pos_lnum = pos.pos_lnum + 1; pos_bol = pos.pos_cnum } + +let unterminated_comment lexbuf = + abort_current lexbuf + "Unterminated C comment" diff --git a/src/plugins/aorai/utils_parser.mli b/src/plugins/aorai/utils_parser.mli index 7b4b696bd7b8021e109f1607d4dccfed07bfd773..94495b62110040746c4b95118a696feec6cc7c6d 100644 --- a/src/plugins/aorai/utils_parser.mli +++ b/src/plugins/aorai/utils_parser.mli @@ -39,3 +39,6 @@ val unknown_token: Lexing.lexbuf -> 'a (** initiate a new line in the lexbuf *) val newline: Lexing.lexbuf -> unit + +(** aborts in case of an unterminated comment *) +val unterminated_comment: Lexing.lexbuf -> 'a diff --git a/src/plugins/aorai/yalexer.mll b/src/plugins/aorai/yalexer.mll index 61042e3a8f6e71ddad87f078b1cd0a610dcc01b7..23ce704ca926df24cb7426e823638ffdf466d337 100644 --- a/src/plugins/aorai/yalexer.mll +++ b/src/plugins/aorai/yalexer.mll @@ -33,11 +33,54 @@ let alpha = ['a'-'z' 'A'-'Z'] let ident = alpha (num | alpha | '_')* let string = ([^ '"' '\\']|'\\'_)* +let decdigit = ['0'-'9'] +let octdigit = ['0'-'7'] +let hexdigit = ['0'-'9' 'a'-'f' 'A'-'F'] +let binarydigit = ['0' '1'] +let letter = ['a'- 'z' 'A'-'Z'] + +let usuffix = ['u' 'U'] +let lsuffix = "l"|"L"|"ll"|"LL" +let intsuffix = + lsuffix | usuffix | usuffix lsuffix | lsuffix usuffix +| usuffix ? "i64" + +let hexprefix = '0' ['x' 'X'] +let binaryprefix = '0' ['b' 'B'] + +let intnum = decdigit+ intsuffix? +let octnum = '0' octdigit+ intsuffix? +let hexnum = hexprefix hexdigit+ intsuffix? +let binarynum = binaryprefix binarydigit+ intsuffix? + +let exponent = ['e' 'E']['+' '-']? decdigit+ +let fraction = '.' decdigit+ +let decfloat = + (intnum? fraction) +| (intnum exponent) +| (intnum? fraction exponent) +| (intnum '.') +| (intnum '.' exponent) + +let hexfraction = hexdigit* '.' hexdigit+ | hexdigit+ '.' +let binexponent = ['p' 'P'] ['+' '-']? decdigit+ +let hexfloat = + hexprefix hexfraction binexponent +| hexprefix hexdigit+ binexponent + +let floatsuffix = ['f' 'F' 'l' 'L'] +let floatnum = (decfloat | hexfloat) floatsuffix? rule token = parse [' ' '\t' ] { token lexbuf } (* skip blanks *) | '\n' { Utils_parser.newline lexbuf; token lexbuf } - | ['0'-'9']+ as lxm { INT(lxm) } + | "/*" { comment lexbuf ; token lexbuf } + | "//" { onelinecomment lexbuf ; token lexbuf } + | floatnum as lxm { FLOAT(lxm) } + | hexnum as lxm { INT(lxm) } + | octnum as lxm { INT(lxm) } + | binarynum as lxm { INT(lxm) } + | intnum as lxm { INT(lxm) } | "CALL" { CALL_OF } | "RETURN" { RETURN_OF } | "COR" { CALLORRETURN_OF } @@ -82,3 +125,12 @@ rule token = parse | eof { EOF } | ":=" { AFF } | _ { Utils_parser.unknown_token lexbuf } + +and comment = parse + | "*/" { } + | eof { Utils_parser.unterminated_comment lexbuf } + | _ { comment lexbuf } + +and onelinecomment = parse + | '\n'|eof { } + | _ { onelinecomment lexbuf } diff --git a/src/plugins/aorai/yaparser.mly b/src/plugins/aorai/yaparser.mly index f900b6350c7783a4a1c2ccbcaf14e522033a5af4..1fbcaa6d72eecd249324feb7a4adc898e44e5b9f 100644 --- a/src/plugins/aorai/yaparser.mly +++ b/src/plugins/aorai/yaparser.mly @@ -154,6 +154,7 @@ type pre_cond = Behavior of string | Pre of Automaton_ast.condition %token <string> IDENTIFIER %token <string> METAVAR %token <string> INT +%token <string> FLOAT %token AFF %token LCURLY RCURLY LPAREN RPAREN LSQUARE RSQUARE LBRACELBRACE RBRACERBRACE %token RARROW @@ -388,7 +389,9 @@ arith_relation_bw /* returns a Lval exp or a Const exp*/ access_or_const : INT { PCst (IntConstant $1) } + | FLOAT { PCst (FloatConstant $1) } | MINUS INT { PUnop (Uminus, PCst (IntConstant $2)) } + | MINUS FLOAT { PUnop (Uminus, PCst (FloatConstant $2)) } | access { $1 } ; diff --git a/src/plugins/callgraph/callgraph_api.ml b/src/plugins/callgraph/callgraph_api.ml index 712ccd11aed0a5ecd49c658f5e3973f8574bcb6b..8ae2e7c7fca02cb0f65f6ff832b96ecad84799a3 100644 --- a/src/plugins/callgraph/callgraph_api.ml +++ b/src/plugins/callgraph/callgraph_api.ml @@ -43,6 +43,9 @@ module type Graph = sig val is_computed: unit -> bool (** Is the graph already built? *) + val add_hook: (G.t -> unit) -> unit + (** Call registered hook each time the graph is computed *) + val self: State.t end @@ -60,7 +63,6 @@ module type Services = sig val entry_point: unit -> G.V.t option val is_root: Kernel_function.t -> bool - end (* diff --git a/src/plugins/callgraph/cg.ml b/src/plugins/callgraph/cg.ml index 24c12d9a2ea69474d83e03035708ec5161c69154..1d0816867404ecbe6f0b4d0135e33702d3e57f56 100644 --- a/src/plugins/callgraph/cg.ml +++ b/src/plugins/callgraph/cg.ml @@ -66,8 +66,11 @@ module State = let dependencies = [ Eva.Analysis.self; Globals.Functions.self ] end) +module StateHook = Hook.Build (D) + let self = State.self let is_computed () = State.is_computed () +let add_hook = StateHook.extend (** @return the list of functions which address is taken.*) let get_pointed_kfs = @@ -101,7 +104,6 @@ let get_pointed_kfs = match !res with | None -> let l = compute () in - State.mark_as_computed (); res := Some l; l | Some l -> l @@ -232,6 +234,8 @@ let compute () = semantic_compute g end else (if Eva.Analysis.is_computed () then semantic_compute else syntactic_compute) g; + State.mark_as_computed (); + StateHook.apply g; g let get () = State.memo compute diff --git a/src/plugins/callgraph/requests.ml b/src/plugins/callgraph/requests.ml new file mode 100644 index 0000000000000000000000000000000000000000..cdef7f503d12adab16126d22d094cecf24057518 --- /dev/null +++ b/src/plugins/callgraph/requests.ml @@ -0,0 +1,179 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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 Server + +module G = Services.G + +(* --- Package declaration --- *) + +let package = Package.package ~plugin:"callgraph" ~title:"Callgraph" () + + +(* --- Helper modules --- *) + +module Record () = +struct + module Record = Data.Record + type record + let record : record Record.signature = Record.signature () + let field name ?(descr = name) = + Record.field record ~name ~descr:(Markdown.plain descr) + let publish ?descr name = + let descr = Option.map Markdown.plain descr in + Record.publish record ~package ~name ?descr +end + +module Enum (X: sig type t end) = +struct + module Enum = Data.Enum + let dictionary: X.t Enum.dictionary = Enum.dictionary () + let tag name descr = Enum.tag ~name ~descr:(Markdown.plain descr) dictionary + let publish lookup name descr = + Enum.set_lookup dictionary lookup; + Request.dictionary ~package ~name ~descr:(Markdown.plain descr) dictionary +end + + +(* --- Types --- *) + +module Vertex = +struct + include Record () + + let kf = field "kf" (module Kernel_ast.Function) + ~descr: "The function represented by the node" + let is_root = field "is_root" Data.jbool + ~descr: "whether this node is the root of a service" + let root = field "root" (module Kernel_ast.Function) + ~descr: "the root of this node's service" + + include (val publish "vertex") + type t = Cil_types.kernel_function Service_graph.vertex + + let to_json (v : Cil_types.kernel_function Service_graph.vertex) = + default |> + set kf v.node |> + set is_root v.is_root |> + set root v.root.node |> + to_json + + let of_json _js = Data.failure "Vertex.of_json not implemented" +end + +module EdgeKind = +struct + include Enum (struct type t = Service_graph.edge end) + + let inter_services = tag "inter_services" "a call between two services" + let inter_functions = tag "inter_functions" "a call inside a service" + let both = tag "both" "both cases above" + + let lookup = function + | Service_graph.Inter_services -> inter_services + | Inter_functions -> inter_functions + | Both -> both + + include (val publish lookup + "edgeKind" "Whether the call goes through services or not") +end + +module Edge = +struct + include Record () + + let src = field "src" (module Kernel_ast.Function) + let dst = field "dst" (module Kernel_ast.Function) + let kind = field "kind" (module EdgeKind) + + include (val publish "edge") + type t = G.E.t + + let to_json (e : t) = + default |> + set src (G.E.src e).node |> + set dst (G.E.dst e).node |> + set kind (G.E.label e) |> + to_json + + let of_json _js = Data.failure "Edge.of_json not implemented" +end + +module Graph = +struct + include Record () + + let vertices = field "vertices" (module Data.Jlist (Vertex)) + let edges = field "edges" (module Data.Jlist (Edge)) + + include (val publish "graph" ~descr:"The callgraph of the current project") + type t = G.t + + let get_vertices (g : t) = + G.fold_vertex (fun v acc -> v :: acc ) g [] + + let get_edges (g : t) = + G.fold_edges_e (fun v acc -> v :: acc ) g [] + + let to_json (g : t) = + default |> + set vertices (get_vertices g) |> + set edges (get_edges g) |> + to_json + + let of_json _js = Data.failure "Graph.of_json not implemented" +end + + +(* --- Requests --- *) + +let _signal = + States.register_value + ~package ~name:"callgraph" + ~descr:(Markdown.plain + "The current callgraph or an empty graph if it has not been computed yet") + ~output:(module Data.Joption (Graph)) + ~add_hook:Services.add_hook + ~get: + begin fun () -> + if Services.is_computed () then + Some (Services.get ()) + else + None + end + () + +let _signal = + States.register_value + ~package ~name:"isComputed" + ~descr:(Markdown.plain + "This boolean is true if the graph has been computed") + ~output:(module Data.Jbool) + ~add_hook:Services.add_hook + ~get:Services.is_computed + () + +let () = Request.register ~package + ~kind:`EXEC ~name:"compute" + ~descr:(Markdown.plain "Compute the callgraph for the current project") + ~input:(module Data.Junit) ~output:(module Data.Junit) + (fun () -> ignore (Services.get ())) diff --git a/src/plugins/gui/debug_manager.ko.ml b/src/plugins/callgraph/requests.mli similarity index 95% rename from src/plugins/gui/debug_manager.ko.ml rename to src/plugins/callgraph/requests.mli index 14207880c6263d2e85a2992f62c80dd8cc23cd2e..d68abd32119990046a8bed6a36cfb5e6c3b8c264 100644 --- a/src/plugins/gui/debug_manager.ko.ml +++ b/src/plugins/callgraph/requests.mli @@ -20,4 +20,4 @@ (* *) (**************************************************************************) -(* empty file *) +(* This module only register requests for Frama-C Server. Nothing is exported *) diff --git a/src/plugins/callgraph/services.ml b/src/plugins/callgraph/services.ml index b2d3f2893fbb6f37313b3472a20777c936386867..1345b6fcdf985cdd78322a2a91fa205a253dc58f 100644 --- a/src/plugins/callgraph/services.ml +++ b/src/plugins/callgraph/services.ml @@ -77,9 +77,12 @@ module State = let dependencies = [ Cg.self; Kernel.MainFunction.self ] end) +module StateHook = Hook.Build (S.Service_graph.Datatype) + (* eta-expansion required to mask optional argument [?project] *) let is_computed () = State.is_computed () let self = State.self +let add_hook = StateHook.extend let compute () = let cg = Cg.get () in @@ -92,6 +95,7 @@ let compute () = in let sg = S.compute cg isr_names in State.mark_as_computed (); + StateHook.apply sg; sg let get () = State.memo compute diff --git a/src/plugins/dive/build.ml b/src/plugins/dive/build.ml index 6116da7e18d2b5b186d55d1727ba695d59240969..acfa92afaa6498c25af003240e6b683123fe89b6 100644 --- a/src/plugins/dive/build.ml +++ b/src/plugins/dive/build.ml @@ -32,6 +32,16 @@ end let dkey = Self.register_category "build" +type locstack = Cil_types.stmt * Callstack.t + +(* Generalized statements *) + +(* used to *localize* (defines in which functions/file rectangles the node must + be placed) nodes *) +type gstmt = + | Local of locstack (* Function statement in a specific callstack *) + | Global of Cil_types.varinfo (* Initialization of a global variable *) + (* --- Lval enumeration --- *) @@ -89,9 +99,12 @@ struct let at_start_of = at_start_of let after = after - let after_kinstr = function - | Kglobal -> at_start (* After global initialization *) - | Kstmt stmt -> after stmt + let before_gstmt = function + | Global _ -> at_start + | Local (stmt,_) -> before stmt + let after_gstmt = function + | Global _ -> at_start (* After global initialization *) + | Local (stmt,_) -> after stmt let to_kf_list kinstr callee = before_kinstr kinstr |> eval_callee callee |> @@ -100,11 +113,11 @@ struct let to_cvalue request lval = eval_lval lval request |> as_cvalue - let to_location kinstr lval = - before_kinstr kinstr |> eval_address lval |> as_location + let to_location gstmt lval = + before_gstmt gstmt |> eval_address lval |> as_location - let to_zone kinstr lval = - before_kinstr kinstr |> eval_address lval |> as_zone + let to_zone gstmt lval = + before_gstmt gstmt |> eval_address lval |> as_zone let to_callstacks stmt = before stmt |> callstacks @@ -113,28 +126,20 @@ struct let zone = eval_address lval request |> as_zone in is_tainted zone request |> Result.to_option - let studia_direct_effect = function - | e, { Studia.Writes.direct = true } -> Some e - | _ -> None - - let writes kinstr lval = - let zone = to_zone kinstr lval in - Self.debug ~dkey "computing writes for %a" Cil_printer.pp_lval lval; - let result = Studia.Writes.compute zone in - let writes = List.filter_map studia_direct_effect result in + let writes zone = + Self.debug ~dkey "computing writes for %a" Locations.Zone.pretty zone; + let writes = Studia.Writes.compute zone in Self.debug ~dkey "%d found" (List.length writes); writes - let reads kinstr lval = - let zone = to_zone kinstr lval in - Self.debug ~dkey "computing reads for %a" Cil_printer.pp_lval lval; - let result = Studia.Reads.compute zone in - let reads = List.filter_map studia_direct_effect result in + let reads zone = + Self.debug ~dkey "computing reads for %a" Locations.Zone.pretty zone; + let reads = Studia.Reads.compute zone in Self.debug ~dkey "%d found" (List.length reads); reads let does_lval_read_zone zone stmt lval = - let zone' = to_zone (Kstmt stmt) lval in + let zone' = to_zone (Local (stmt,[])) lval in Locations.Zone.intersects zone' zone let does_exp_read_zone zone stmt exp = @@ -148,14 +153,14 @@ end (* --- Precision evaluation --- *) (* For folded bases, lval may be strictly included in the node zone *) -let update_node_values node ?(lval=Node_kind.to_lval node.node_kind) rq = +let update_node_values context node ?(lval=Node_kind.to_lval node.node_kind) rq = match lval with | None -> () (* can't evaluate node *) | Some lval -> let typ = Cil.typeOfLval lval and cvalue = Eval.to_cvalue rq lval and taint = Eval.is_tainted rq lval in - Graph.update_node_values node ~typ ~cvalue ~taint + Context.update_node_values context node ~typ ~cvalue ~taint (* --- Locations handling --- *) @@ -171,10 +176,10 @@ let is_foldable_type typ = | TNamed _ -> assert false (* the type have been unrolled *) -let enumerate_cells ~is_folded_base lval kinstr = +let enumerate_cells ~is_folded_base gstmt lval = (* If possible, refine the lval to a non-symbolic one *) let typ = Cil.typeOfLval lval in - let location = Eval.to_location kinstr lval in + let location = Eval.to_location gstmt lval in let open Locations in let map_base (base,ival) = match base with @@ -201,43 +206,58 @@ let enumerate_cells ~is_folded_base lval kinstr = try Location_Bits.to_seq_i location.loc |> Seq.flat_map map_base with Abstract_interp.Error_Top -> - Seq.return (Unknown (lval, kinstr)) + match gstmt with + | Local (stmt,_) -> Seq.return (Unknown (lval, stmt)) + | Global _vi -> + Seq.return (Error "Global initialization address cannot be resolved") -let build_node_kind ~is_folded_base lval kinstr = +let build_node_kind ~is_folded_base gstmt lval = match lval with | Var vi, offset -> (* Build a scalar node even if kinstr is dead *) Scalar (vi, Cil.typeOfLval lval, offset) | Mem _, _ -> - let cells_seq = enumerate_cells ~is_folded_base lval kinstr in + let cells_seq = enumerate_cells ~is_folded_base gstmt lval in match cells_seq () with | Seq.Cons (node_kind, seq) when Seq.is_empty seq -> node_kind - | _ -> Scattered (lval, kinstr) - -let default_node_locality callstack = - match callstack with - | [] -> - (* The empty callstack can be used for global lvalues *) - { loc_file="" ; loc_callstack=[] } - | (kf,_kinstr) :: _ -> - let loc_file = get_loc_filename (Kernel_function.get_location kf) in - { loc_file ; loc_callstack=callstack } - -let build_node_locality callstack node_kind = - match Node_kind.get_base node_kind with - | None -> default_node_locality callstack - | Some vi -> - match Kernel_function.find_defining_kf vi with - | Some kf -> - let callstack = - try - Callstack.pop_downto kf callstack - with Failure _ -> - Callstack.init kf (* TODO: complete callstack *) - in - default_node_locality callstack - | None -> - { loc_file = get_loc_filename vi.vdecl ; loc_callstack = [] } + | _ -> + match gstmt with + | Local (stmt ,_) -> Scattered (lval, stmt) + | Global _vi -> Error "Global initialization address cannot be resolved" + + +let build_node_locality gstmt node_kind = + let make_local callstack = + match callstack with + | [] -> assert false + | (kf,_kinstr) :: _ -> + let loc_file = get_loc_filename (Kernel_function.get_location kf) in + { loc_file ; loc_callstack=callstack } + in + let make_global vi = + { loc_file=get_loc_filename vi.vdecl; loc_callstack=[] } + in + match gstmt with + | Local (_, callstack) -> + begin match node_kind with + | Scalar (vi,_,_) | Composite (vi) -> + begin match Kernel_function.find_defining_kf vi with + | Some kf -> + let callstack = + try + Callstack.pop_downto kf callstack + with Failure _ -> + Callstack.init kf (* TODO: complete callstack *) + in + make_local callstack + | None -> make_global vi + end + | Scattered _ | Unknown _ | Alarm _ | AbsoluteMemory | String _ | Const _ + | Error _ -> + make_local callstack + end + | Global vi -> + make_global vi let find_compatible_callstacks stmt callstack = let kf = Kernel_function.find_englobing_kf stmt in @@ -264,196 +284,242 @@ let find_compatible_callstacks stmt callstack = (* --- Graph building --- *) -let add_or_update_node context callstack node_kind = - let node_locality = build_node_locality callstack node_kind in - Context.add_node context ~node_kind ~node_locality +let add_or_update_node ~context gstmt node_kind = + let node_locality = build_node_locality gstmt node_kind in + let node = Context.add_node context ~node_kind ~node_locality in + begin match node_kind with (* Some nodes don't have read or write deps *) + | Alarm _ -> + node.node_reads_computation <- Done + | Unknown _ | Const _ | String _ -> + node.node_writes_computation <- Done + | Error _ -> + node.node_reads_computation <- Done; + node.node_writes_computation <- Done + | _ -> () + end; + node -let build_node context callstack lval kinstr = +let build_node ~context gstmt lval = let is_folded_base = Context.is_folded context in - let node_kind = build_node_kind ~is_folded_base lval kinstr in - add_or_update_node context callstack node_kind + let node_kind = build_node_kind ~is_folded_base gstmt lval in + add_or_update_node ~context gstmt node_kind -let build_var context callstack varinfo = +let build_var ~context gstmt varinfo = let lval = Var varinfo, NoOffset in - build_node context callstack lval Kglobal + build_node ~context gstmt lval -let build_lval context callstack kinstr lval = - let node = build_node context callstack lval kinstr in - update_node_values ~lval:(Some lval) node (Eval.after_kinstr kinstr); +let build_lval ~context gstmt lval = + let node = build_node ~context gstmt lval in + update_node_values context ~lval:(Some lval) node (Eval.after_gstmt gstmt); node -let build_const context callstack exp = - add_or_update_node context callstack (Const exp) +let build_const ~context gstmt exp = + add_or_update_node ~context gstmt (Const exp) -let build_alarm context callstack stmt alarm = +let build_alarm ~context (stmt,_ as locstack) alarm = let node_kind = Alarm (stmt,alarm) in - let node_locality = build_node_locality callstack node_kind in + let node_locality = build_node_locality (Local locstack) node_kind in Context.add_node context ~node_kind ~node_locality (* --- Writes --- *) +let compatible_writes callstack = function + | Studia.Writes.CallIndirect _ -> None (* Ignore indirect writes *) + | Assign _ | CallDirect _ | GlobalInit _ as w -> Some w + | FormalInit (vi, _callsites) as w -> + match Callstack.pop callstack with + | Some (kf,stmt,_callstack) -> + (* keep the only callsite compatible with the current callstack *) + Some (Studia.Writes.FormalInit (vi, [(kf,[stmt])])) + | None -> Some w + +(* returns true if the callsite (kf,stmt) *) + type deps_builder = unit Seq.t let build_node_writes context node = - let graph = Context.get_graph context - and is_folded_base = Context.is_folded context in + let is_folded_base = Context.is_folded context in - let rec build_write_deps callstack kinstr lval : deps_builder = - let add_deps = function - | { skind=Instr instr } as stmt -> + let rec build_write_deps ~callstack zone : deps_builder = + let add_deps origin = + match origin with + | Studia.Writes.CallIndirect _ -> + Seq.empty (* Ignore indirect writes *) + + | Assign stmt | CallDirect stmt -> + let instr = match stmt.skind with + | Instr instr -> instr + | _ -> assert false (* Studia invariant *) + in (* Update the values at the light of new discovered write *) - update_node_values node (Eval.after stmt); + update_node_values context node (Eval.after stmt); (* Add dependencies for each callstack *) List.to_seq (find_compatible_callstacks stmt callstack) |> - Seq.flat_map (fun cs -> build_instr_deps cs stmt instr) - | _ -> assert false (* Studia invariant *) + Seq.flat_map + (fun cs -> build_instr_deps ~callstack:cs ~origin stmt instr) + + | GlobalInit (vi, initinfo) as origin -> + let init = match initinfo.init with + | None -> SingleInit (Cil.zero ~loc:vi.vdecl) + | Some init -> init + in + build_init_deps ~origin (Global vi) vi init + + | FormalInit (vi, callsites) as origin -> + let kf = Option.get (Kernel_function.find_defining_kf vi) in + let pos = Kernel_function.get_formal_position vi kf in + let add_deps stmt = + match stmt.skind with + | Instr + (Call (_,_,args,_) | + (Local_init (_, ConsInit (_, args, _), _))) -> + let exp = List.nth args pos in + let callstack = + match Callstack.pop callstack with + | Some (_kf,_stmt,callstack') -> callstack' + | None -> Callstack.init kf + in + build_exp_deps ~origin (Local (stmt, callstack)) Data exp + | _ -> + assert false (* Callsites can only be Call or ConsInit *) + in + (* Evaluate the parameter values at the start of its defining function *) + update_node_values context node (Eval.at_start_of kf); + let callsites = List.concat_map snd callsites in + Seq.flat_map add_deps (List.to_seq callsites) in - let writes = Eval.writes kinstr lval in - let args_seq, call_stmts = build_arg_deps callstack in - let compare = Cil_datatype.Stmt_Id.compare in - node.node_writes_stmts <- List.sort_uniq compare (writes @ call_stmts); - Seq.append args_seq (Seq.flat_map add_deps (List.to_seq writes)) - - and build_alarm_deps callstack stmt alarm : deps_builder = - build_lvals_deps callstack stmt Data (EnumLvals.in_alarm alarm) - - and build_instr_deps callstack stmt instr : deps_builder = + let writes = Eval.writes zone in + let writes = List.filter_map (compatible_writes callstack) writes in + Context.set_node_writes context node writes; + Seq.flat_map add_deps (List.to_seq writes) + + and build_alarm_deps ~callstack stmt alarm : deps_builder = + let lvals = EnumLvals.in_alarm alarm in + let origin = Studia.Writes.Assign stmt in + let gstmt = Local (stmt, callstack) in + build_lvals_deps ~origin gstmt Data lvals + + and build_instr_deps ~origin ~callstack stmt instr : deps_builder = + let gstmt = Local (stmt, callstack) in (* Add dependencies found in the instruction *) match instr with | Set (_, exp, _) -> - build_exp_deps callstack stmt Data exp + build_exp_deps ~origin gstmt Data exp | Call (_, callee, args, _) -> - build_call_deps callstack stmt callee args + build_call_deps ~callstack ~origin stmt callee args | Local_init (dest, ConsInit (f, args, k), loc) -> let as_func _dest callee args _loc = - build_call_deps callstack stmt callee args + build_call_deps ~callstack ~origin stmt callee args in Cil.treat_constructor_as_func as_func dest f args k loc | Local_init (vi, AssignInit init, _) -> - let lvals = EnumLvals.in_init vi init in - let exp = - match init with - | CompoundInit _ -> None (* Do not generate nodes for Compounds for now *) - | SingleInit exp -> Some exp - in - build_lvals_deps callstack stmt Data ?exp lvals + build_init_deps ~origin gstmt vi init | Asm _ | Skip _ | Code_annot _ -> Seq.empty (* Cases not returned by Studia *) - and build_arg_deps callstack : deps_builder * stmt list = - match Node_kind.get_base node.node_kind with - (* TODO refine formal dependency computation for non-scalar formals *) - | Some vi when vi.vformal -> - let kf = Option.get (Kernel_function.find_defining_kf vi) in - let pos = Kernel_function.get_formal_position vi kf in - let callsites = - match Callstack.pop callstack with - | Some (kf',stmt,callstack) -> - assert (Kernel_function.equal kf' kf); - [(stmt,callstack)] - | None -> - let callsites = Kernel_function.find_syntactic_callsites kf in - List.map (fun (kf,stmt) -> (stmt,Callstack.init kf)) callsites - and add_deps (stmt,callstack) : unit Seq.t = - match stmt.skind with - | Instr - (Call (_,_,args,_) | - (Local_init (_, ConsInit (_, args, _), _))) -> - let exp = List.nth args pos in - build_exp_deps callstack stmt Data exp - | _ -> - assert false (* Callsites can only be Call or ConsInit *) - in - (* Evaluate the parameter values at the start of its defining function *) - update_node_values node (Eval.at_start_of kf); - Seq.flat_map add_deps (List.to_seq callsites), List.map fst callsites - | _ -> Seq.empty, [] - - and build_return_deps callstack stmt args kf : deps_builder = + and build_return_deps ~callstack call_stmt args kf : deps_builder = match Kernel_function.find_return kf with | {skind = Return (Some {enode = Lval lval_res},_)} as return_stmt -> - let callstack = Callstack.push (kf,stmt) callstack in - build_lval_deps callstack return_stmt Data lval_res + let callstack = Callstack.push (kf,call_stmt) callstack in + let origin = Studia.Writes.Assign return_stmt in + let gstmt = Local (return_stmt, callstack) in + build_lval_deps ~origin gstmt Data lval_res | {skind = Return (None, _)} -> Seq.empty (* return void *) | _ -> assert false (* Cil invariant *) | exception Kernel_function.No_Statement -> (* the function is only a prototype *) (* TODO: read assigns instead *) + let origin = Studia.Writes.Assign call_stmt in + let gstmt = Local (call_stmt, callstack) in List.to_seq args |> - Seq.flat_map (build_exp_deps callstack stmt Data) + Seq.flat_map (build_exp_deps ~origin gstmt Data) - and build_call_deps callstack stmt callee args : deps_builder = + and build_call_deps ~origin ~callstack stmt callee args : deps_builder = + let gstmt = Local (stmt, callstack) in let callee_deps = match callee.enode with | Lval (Var _vi, _offset) -> Seq.empty | Lval (Mem exp, _offset) -> - build_exp_deps callstack stmt Callee exp + build_exp_deps ~origin gstmt Callee exp | _ -> Self.warning "Cannot compute all callee dependencies for %a" Cil_printer.pp_stmt stmt; Seq.empty and return_deps = List.to_seq (Eval.to_kf_list (Kstmt stmt) callee) |> - Seq.flat_map (build_return_deps callstack stmt args) + Seq.flat_map (build_return_deps ~callstack stmt args) in Seq.append callee_deps return_deps - and build_exp_deps callstack stmt kind exp : deps_builder = + and build_init_deps ~origin gstmt vi init : deps_builder = + let lvals = EnumLvals.in_init vi init in + let exp = + match init with + | CompoundInit _ -> None (* Do not generate nodes for Compounds for now *) + | SingleInit exp -> Some exp + in + build_lvals_deps ~origin gstmt Data ?exp lvals + + and build_exp_deps ~origin gstmt kind exp : deps_builder = let lvals = EnumLvals.in_exp exp in - build_lvals_deps callstack stmt kind ~exp lvals + build_lvals_deps ~origin gstmt kind ~exp lvals - and build_lvals_deps callstack stmt kind ?exp lvals : deps_builder = + and build_lvals_deps ~origin gstmt kind ?exp lvals : deps_builder = if lvals <> [] then List.to_seq lvals |> - Seq.flat_map (build_lval_deps callstack stmt kind) + Seq.flat_map (build_lval_deps ~origin gstmt kind) else - Option.fold exp ~none:Seq.empty - ~some:(build_const_deps callstack stmt kind) + Option.to_seq exp |> + Seq.flat_map (build_const_deps ~origin gstmt kind) - and build_lval_deps callstack stmt kind lval : deps_builder = - let kinstr = Kstmt stmt in - let dst = build_lval context callstack kinstr lval in - Seq.return (Graph.create_dependency graph kinstr dst kind node) + and build_lval_deps ~origin gstmt kind lval : deps_builder = + let dst = build_lval ~context gstmt lval in + Seq.return (Context.add_dep context ~origin ~kind dst node) - and build_const_deps callstack stmt kind exp : deps_builder = - let kinstr = Kstmt stmt in - let dst = build_const context callstack exp in - Seq.return (Graph.create_dependency graph kinstr dst kind node) + and build_const_deps ~origin gstmt kind exp : deps_builder = + let dst = build_const ~context gstmt exp in + Seq.return (Context.add_dep context ~origin ~kind dst node) - and build_scattered_deps callstack kinstr lval : deps_builder = + and build_scattered_deps ~callstack stmt lval : deps_builder = + let gstmt = Local (stmt,callstack) in let add_cell node_kind = - let node' = add_or_update_node context callstack node_kind in - update_node_values node (Eval.after_kinstr kinstr); - Graph.create_dependency graph kinstr node' Composition node + let dst = add_or_update_node ~context gstmt node_kind in + update_node_values context node (Eval.after stmt); + let origin = Studia.Writes.Assign stmt in + Context.add_dep context ~origin ~kind:Composition dst node in - enumerate_cells ~is_folded_base lval kinstr |> Seq.map add_cell + enumerate_cells ~is_folded_base gstmt lval |> Seq.map add_cell in let callstack = node.node_locality.loc_callstack in match node.node_kind with - | Scalar (vi,_typ,offset) -> - build_write_deps callstack Kglobal (Cil_types.Var vi, offset) + | Scalar (vi, _typ, offset) -> + let zone = Eval.to_zone (Global vi) (Cil_types.Var vi, offset) in + build_write_deps ~callstack zone | Composite (vi) -> - build_write_deps callstack Kglobal (Cil_types.Var vi, Cil_types.NoOffset) - | Scattered (lval,kinstr) -> - build_scattered_deps callstack kinstr lval - | Alarm (stmt,alarm) -> - build_alarm_deps callstack stmt alarm + let zone = Locations. zone_of_varinfo vi in + build_write_deps ~callstack zone + | Scattered (lval, stmt) -> + build_scattered_deps ~callstack stmt lval + | Alarm (stmt, alarm) -> + build_alarm_deps ~callstack stmt alarm | Unknown _ | AbsoluteMemory | String _ | Const _ | Error _ -> Seq.empty (* --- Reads --- *) -let build_node_reads context node = - let graph = Context.get_graph context in +let compatible_reads = function + | Studia.Reads.Indirect _ -> None + | Direct stmt -> Some stmt - let rec build_reads_deps callstack kinstr lval : deps_builder = +let build_node_reads context node = + let rec build_reads_deps callstack zone : deps_builder = let add_deps stmt = - let zone = Some (Eval.to_zone kinstr lval) in List.to_seq (find_compatible_callstacks stmt callstack) |> - Seq.flat_map (fun cs -> build_stmt_deps cs zone stmt) + Seq.flat_map (fun cs -> build_stmt_deps ~callstack:cs (Some zone) stmt) in - List.to_seq (Eval.reads kinstr lval) |> + Eval.reads zone |> List.to_seq |> + Seq.filter_map compatible_reads |> Seq.flat_map add_deps and exp_contains_read zone stmt exp = @@ -468,11 +534,7 @@ let build_node_reads context node = | Some zone' -> Eval.does_init_read_zone zone' stmt vi init - and build_kinstr_deps callstack zone = function - | Kglobal -> Seq.empty (* Do nothing *) - | Kstmt stmt -> build_stmt_deps callstack zone stmt - - and build_stmt_deps callstack zone stmt = + and build_stmt_deps ~callstack zone stmt = match stmt.skind with | Instr instr -> build_instr_deps callstack zone stmt instr | Return (Some exp,_) @@ -483,7 +545,7 @@ let build_node_reads context node = and build_instr_deps callstack zone stmt = function | Set (lval, exp, _) when exp_contains_read zone stmt exp -> - build_lval_deps callstack stmt lval + build_lval_deps ~callstack stmt lval | Local_init (dest, ConsInit (f, args, k), loc) -> let as_func _dest callee args _loc = build_call_deps callstack zone stmt callee args @@ -491,7 +553,7 @@ let build_node_reads context node = Cil.treat_constructor_as_func as_func dest f args k loc | Local_init (vi, AssignInit init, _) when init_contains_read zone stmt vi init -> - build_var_deps callstack stmt vi + build_var_deps ~callstack stmt vi | Call (_, callee, args, _) -> build_call_deps callstack zone stmt callee args | _ -> Seq.empty @@ -510,9 +572,9 @@ let build_node_reads context node = match stmt.skind with | Instr (Call (None,_,_,_)) -> Seq.empty | Instr (Call (Some lval,_,_,_)) -> - build_lval_deps callstack stmt lval + build_lval_deps ~callstack stmt lval | Instr (Local_init (vi,_,_)) -> - build_var_deps callstack stmt vi + build_var_deps ~callstack stmt vi | _ -> assert false (* Callsites can only be Call or ConsInit *) in @@ -533,26 +595,30 @@ let build_node_reads context node = and build_arg_dep callstack stmt zone (arg,formal) = if exp_contains_read zone stmt arg - then build_var_deps callstack stmt formal + then build_var_deps ~callstack stmt formal else Seq.empty - and build_lval_deps callstack stmt lval = - let kinstr = Kstmt stmt in - let src = build_lval context callstack kinstr lval in - Seq.return (Graph.create_dependency graph kinstr node Data src) + and build_lval_deps ~callstack stmt lval = + let gstmt = Local (stmt, callstack) in + let src = build_lval ~context gstmt lval in + let origin = Studia.Writes.Assign stmt in + Seq.return (Context.add_dep context ~origin ~kind:Data node src) - and build_var_deps callstack stmt vi = - build_lval_deps callstack stmt (Cil.var vi) + and build_var_deps ~callstack stmt vi = + build_lval_deps ~callstack stmt (Cil.var vi) in let callstack = node.node_locality.loc_callstack in match node.node_kind with | Scalar (vi,_typ,offset) -> - build_reads_deps callstack Kglobal (Cil_types.Var vi, offset) + (* Offset should be constant and no evaluation should be required *) + let zone = Eval.to_zone (Global vi) (Cil_types.Var vi, offset) in + build_reads_deps callstack zone | Composite (vi) -> - build_reads_deps callstack Kglobal (Cil_types.Var vi, Cil_types.NoOffset) - | Scattered (_lval,kinstr) -> - build_kinstr_deps callstack None kinstr + let zone = Locations. zone_of_varinfo vi in + build_reads_deps callstack zone + | Scattered (_lval,stmt) -> + build_stmt_deps ~callstack None stmt | Alarm _ | Unknown _ | AbsoluteMemory | Const _ | String _ | Error _ -> Seq.empty @@ -594,8 +660,7 @@ let explore_backward ~depth context root = | Partial builder -> builder | NotDone -> build_node_writes context n in - n.node_writes_computation <- advance_computation context deps_builder; - Context.update_diff context n + n.node_writes_computation <- advance_computation context deps_builder end in bfs ~depth ~iter_succ explore_node root @@ -610,8 +675,7 @@ let explore_forward ~depth context root = | Partial builder -> builder | NotDone -> build_node_reads context n in - n.node_reads_computation <- advance_computation context deps_builder; - Context.update_diff context n + n.node_reads_computation <- advance_computation context deps_builder end in bfs ~depth ~iter_succ explore_node root @@ -623,22 +687,23 @@ let complete context root = Context.add_root context root; root -let add_var context varinfo = - let callstack = [] in - let node = build_var context callstack varinfo in +let add_var context vi = + let gstmt = match Kernel_function.find_defining_kf vi with + | Some kf -> Local (Kernel_function.find_first_stmt kf , Callstack.init kf) + | None -> Global vi + in + let node = build_var ~context gstmt vi in complete context node -let add_lval context kinstr lval = - let callstack = match kinstr with - | Kglobal -> [] - | Kstmt stmt -> Callstack.init (Kernel_function.find_englobing_kf stmt) - in - let node = build_lval context callstack kinstr lval in +let add_lval context stmt lval = + let callstack = Callstack.init (Kernel_function.find_englobing_kf stmt) in + let gstmt = Local (stmt, callstack) in + let node = build_lval ~context gstmt lval in complete context node let add_alarm context stmt alarm = let callstack = Callstack.init (Kernel_function.find_englobing_kf stmt) in - let node = build_alarm context callstack stmt alarm in + let node = build_alarm ~context (stmt, callstack) alarm in complete context node let add_annotation context stmt annot = @@ -647,7 +712,7 @@ let add_annotation context stmt annot = let add_instr context stmt = function | Set (lval, _, _) - | Call (Some lval, _, _, _) -> Some (add_lval context (Kstmt stmt) lval) + | Call (Some lval, _, _, _) -> Some (add_lval context stmt lval) | Local_init (vi, _, _) -> Some (add_var context vi) | Code_annot (annot, _) -> add_annotation context stmt annot | _ -> None (* Do nothing for any other instruction *) @@ -663,9 +728,9 @@ let add_property context = function | _ -> None (* Do nothing fo any other property *) let add_localizable context = function - | Printer_tag.PLval (_kf, kinstr, lval) -> Some (add_lval context kinstr lval) + | Printer_tag.PIP prop -> add_property context prop + | PLval (_kf, Kstmt stmt, lval) -> Some (add_lval context stmt lval) | PVDecl (_kf, _kinstr, varinfo) -> Some (add_var context varinfo) - | PIP (prop) -> add_property context prop | PStmt (_kf, stmt) | PStmtStart (_kf, stmt) -> add_stmt context stmt | _ -> None (* Do nothing for any other localizable *) @@ -674,12 +739,10 @@ let add_localizable context = function let remove_dependencies context node = (* Remove incomming edges *) - Graph.remove_dependencies (Context.get_graph context) node; - (* Dependencies are not there anymore *) + Context.remove_node_deps context node; + (* Reset the writes computation status *) node.node_writes_computation <- NotDone; - node.node_writes_stmts <- []; - (* Notify node update *) - Context.update_diff context node + Context.set_node_writes context node [] let remove_disconnected context = let roots = Context.get_roots context in diff --git a/src/plugins/dive/build.mli b/src/plugins/dive/build.mli index 22893c9a394472dfdda40cef86572a230169ed6f..f73a88ab2a29cede25733371e5cee8377a6f0ec7 100644 --- a/src/plugins/dive/build.mli +++ b/src/plugins/dive/build.mli @@ -24,7 +24,7 @@ open Cil_types open Dive_types open Context -val add_lval : t -> kinstr -> lval -> node +val add_lval : t -> stmt -> lval -> node val add_var : t -> varinfo -> node val add_alarm : t -> stmt -> Alarms.alarm -> node val add_annotation : t -> stmt -> code_annotation -> node option diff --git a/src/plugins/dive/context.ml b/src/plugins/dive/context.ml index b0a3dd3e4a74954a32c9a76e997e0cb1cefa7091..c3482a199e7dbfc7ba101f2fd1d346ec6389dfae 100644 --- a/src/plugins/dive/context.ml +++ b/src/plugins/dive/context.ml @@ -24,8 +24,6 @@ open Dive_types module Graph = Dive_graph -let dkey = Self.register_category "context" - module NodeRef = Datatype.Pair_with_collections (Node_kind) (Callstack) @@ -36,6 +34,8 @@ module NodeTable = FCHashtbl.Make (NodeRef) module NodeSet = Graph.Node.Set module BaseSet = Cil_datatype.Varinfo.Set +type element = Node of node | Edge of (node * dependency * node) + type t = { mutable graph: Graph.t; mutable vertex_table: node Index.t; (* node_key -> node *) @@ -44,14 +44,17 @@ type t = { mutable hidden_bases: BaseSet.t; mutable max_dep_fetch_count: int; mutable roots: NodeSet.t; - mutable graph_diff: graph_diff; + mutable update_hook : element -> unit; + mutable remove_hook : element -> unit; + mutable clear_hook : unit -> unit; } (* --- initialization --- *) +let no_hook = fun _ -> () + let create () = - Eva.Analysis.compute (); { graph = Graph.create (); vertex_table = Index.create 13; @@ -60,7 +63,9 @@ let create () = hidden_bases = BaseSet.empty; max_dep_fetch_count = 10; roots = NodeSet.empty; - graph_diff = { last_root = None ; added_nodes=[] ; removed_nodes=[] }; + update_hook = no_hook; + remove_hook = no_hook; + clear_hook = no_hook; } let clear context = @@ -69,7 +74,22 @@ let clear context = context.node_table <- NodeTable.create 13; context.max_dep_fetch_count <- 10; context.roots <- NodeSet.empty; - context.graph_diff <- { last_root = None ; added_nodes=[] ; removed_nodes=[] } + context.clear_hook () + + +(* Hooks *) + +let set_update_hook context f = + context.update_hook <- f + +let set_remove_hook context f = + context.remove_hook <- f + +let set_clear_hook context f = + context.clear_hook <- f + +let notify_node_update context node = + context.update_hook (Node node) (* --- Accessors --- *) @@ -84,36 +104,6 @@ let get_max_dep_fetch_count context = context.max_dep_fetch_count -(* --- State --- *) - -let is_node_updated context node = - let is_node n = Graph.Node.equal node n in - List.exists is_node context.graph_diff.removed_nodes || - List.exists is_node context.graph_diff.added_nodes - -let update_diff context node = - if not (is_node_updated context node) then - context.graph_diff <- { - context.graph_diff with - added_nodes = node :: context.graph_diff.added_nodes; - } - -let take_last_diff context = - let pp_node fmt n = Format.pp_print_int fmt n.node_key in - let pp_node_list = Pretty_utils.pp_list ~sep:",@, " pp_node in - let diff = context.graph_diff in - Self.debug ~dkey "root: %a,@, added: %a,@, subbed: %a" - (Pretty_utils.pp_opt pp_node) diff.last_root - pp_node_list diff.added_nodes - pp_node_list diff.removed_nodes; - context.graph_diff <- { - last_root = None ; - added_nodes=[] ; - removed_nodes=[] - }; - diff - - (* --- Roots --- *) let get_roots context = @@ -123,15 +113,11 @@ let update_roots context new_roots = let old_roots = context.roots in context.roots <- new_roots; let unset n = - if not (NodeSet.mem n new_roots) then begin - n.node_is_root <- false; - update_diff context n - end + n.node_is_root <- false; + context.update_hook (Node n); and set n = - if not (NodeSet.mem n old_roots) then begin - n.node_is_root <- true; - update_diff context n - end + n.node_is_root <- true; + context.update_hook (Node n); in NodeSet.iter unset old_roots; NodeSet.iter set new_roots @@ -180,7 +166,7 @@ let add_node context ~node_kind ~node_locality = let node = Graph.create_node context.graph ~node_kind ~node_locality in node.node_hidden <- is_hidden context node.node_kind; Index.add context.vertex_table node.node_key node; - update_diff context node; + context.update_hook (Node node); node in NodeTable.memo context.node_table node_ref add_new @@ -190,12 +176,28 @@ let remove_node context node = let graph = context.graph in Graph.iter_succ (fun n -> n.node_writes_computation <- NotDone) graph node; Graph.iter_pred (fun n -> n.node_reads_computation <- NotDone) graph node; + Graph.iter_succ_e (fun e -> context.remove_hook (Edge e)) graph node; + Graph.iter_pred_e (fun e -> context.remove_hook (Edge e)) graph node; Graph.remove_node context.graph node; Index.remove context.vertex_table node.node_key; NodeTable.remove context.node_table node_ref; - let is_not_node n = not (Graph.Node.equal node n) in - context.graph_diff <- { - context.graph_diff with - added_nodes = List.filter is_not_node context.graph_diff.added_nodes; - removed_nodes = node :: context.graph_diff.removed_nodes; - } + context.remove_hook (Node node) + +let add_dep context ~origin ~kind src dest = + let edge = Graph.create_dependency context.graph ~origin ~kind src dest in + context.update_hook (Edge edge) + +let remove_dep context edge = + Graph.remove_dependency context.graph edge; + context.remove_hook (Edge edge) + +let remove_node_deps context node = + Graph.iter_pred_e (remove_dep context) context.graph node + +let update_node_values context node ~typ ~cvalue ~taint = + Graph.update_node_values node ~typ ~cvalue ~taint; + notify_node_update context node + +let set_node_writes context node writes = + node.node_writes <- List.sort_uniq Studia.Writes.compare writes; + notify_node_update context node diff --git a/src/plugins/dive/context.mli b/src/plugins/dive/context.mli index ecc6139bf78ce55e79db800c9313d3131af99c2c..d440e8b54a6c6c545b6fed757482a25d4043a727 100644 --- a/src/plugins/dive/context.mli +++ b/src/plugins/dive/context.mli @@ -22,20 +22,13 @@ open Dive_types -(* -module NodeRef : Datatype.S with type t = node_kind * callstack -module Index : Datatype.Hashtbl with type key = int -module NodeTable : Datatype.Hashtbl with type key = NodeRef.t -module NodeSet : Datatype.Set with type elt = node -module BaseSet : Datatype.Set with type elt = Cil_types.varinfo -module FunctionMap : Datatype.Map with type key = Cil_types.kernel_function -*) - type t +type element = Node of node | Edge of (node * dependency * node) + val create : unit -> t val clear : t -> unit (* reset to almost an empty context, - but keeps folded and hidden bases *) + but keeps folded and hidden bases, and hooks *) val get_graph : t -> Dive_graph.t val find_node : t -> int -> node @@ -56,6 +49,16 @@ val show : t -> Cil_types.varinfo -> unit val add_node : t -> node_kind:node_kind -> node_locality:node_locality -> node val remove_node : t -> node -> unit +val add_dep : t -> origin:origin -> kind:dependency_kind -> + node -> node -> unit +val remove_node_deps : t -> node -> unit + +val update_node_values : t -> node -> + typ:Cil_types.typ -> + cvalue:Locations.Location_Bytes.t -> taint:Eva.Results.taint option -> unit +val set_node_writes : t -> node -> origin list -> unit + +val set_update_hook : t -> (element -> unit) -> unit +val set_remove_hook : t -> (element -> unit) -> unit +val set_clear_hook : t -> (unit -> unit) -> unit -val update_diff : t -> node -> unit -val take_last_diff : t -> graph_diff diff --git a/src/plugins/dive/dive_graph.ml b/src/plugins/dive/dive_graph.ml index d950484cb2fe818cec169dac5b5cdfcef9563fe8..ef3c84076d6d3a39afe77c1c39c0786fc8602102 100644 --- a/src/plugins/dive/dive_graph.ml +++ b/src/plugins/dive/dive_graph.ml @@ -40,7 +40,7 @@ let new_node node_taint = None; node_writes_computation = NotDone; node_reads_computation = NotDone; - node_writes_stmts = []; + node_writes = []; } module Node = Datatype.Make_with_collections @@ -80,9 +80,9 @@ let create_node ~node_kind ~node_locality g = let remove_node = remove_vertex -let create_dependency g kinstr v1 dependency_kind v2 = +let create_dependency g ~origin ~kind v1 v2 = let same_kind (_,e,_) = - e.dependency_kind = dependency_kind + e.dependency_kind = kind in let matching_edge = try @@ -94,21 +94,19 @@ let create_dependency g kinstr v1 dependency_kind v2 = | None -> let e = { dependency_key = fresh_key (); - dependency_kind; + dependency_kind = kind; dependency_origins = [] } in add_edge_e g (v1,e,v2); e in - (* Add origins *) - match kinstr with - | Cil_types.Kglobal -> () - | Kstmt stmt -> - let add_uniq l x = - List.sort_uniq Cil_datatype.Stmt.compare (x :: l) - in - e.dependency_origins <- add_uniq e.dependency_origins stmt + (* Add origin *) + let add_uniq l x = + List.sort_uniq Studia.Writes.compare (x :: l) + in + e.dependency_origins <- add_uniq e.dependency_origins origin; + (v1,e,v2) let remove_dependency g edge = @@ -117,12 +115,6 @@ let remove_dependency g edge = let remove_dependencies g node = iter_pred_e (remove_dependency g) g node -let vertices g = - fold_vertex (fun n acc -> n ::acc) g [] - -let edges g = - fold_edges_e (fun d acc -> d ::acc) g [] - let update_node_values node ~typ ~cvalue ~taint = let join_taint t1 t2 = @@ -178,7 +170,7 @@ let bfs ?(iter_succ=iter_succ) ?(limit=max_int) g roots = Table.fold (fun n _ l -> n :: l) explored [] -let ouptput_to_dot out_channel g = +let output_to_dot out_channel g = let open Graph.Graphviz.DotAttributes in (* let g = add_dummy_nodes g in *) @@ -267,158 +259,3 @@ let ouptput_to_dot out_channel g = end) in Dot.output_graph out_channel g - -module JsonPrinter = -struct - let output_stmt stmt = - let kf = Kernel_function.find_englobing_kf stmt in - Server.Kernel_ast.Location.to_json (kf, PStmtStart (kf, stmt)) - - let output_kinstr = function - | Cil_types.Kglobal -> `String "global" - | Cil_types.Kstmt stmt -> `Int stmt.Cil_types.sid - - let output_callsite (kf,kinstr) = - `Assoc [ - ("fun", `String (Kernel_function.get_name kf)) ; - ("instr", output_kinstr kinstr) ; - ] - - let output_callstack cs = - `List (List.map output_callsite cs) - - let output_node_kind kind = - let s = match kind with - | Scalar _ -> "scalar" - | Composite _ -> "composite" - | Scattered _ -> "scattered" - | Unknown _ -> "unknown" - | Alarm _ -> "alarm" - | AbsoluteMemory -> "absolute" - | String _ -> "string" - | Const _ -> "const" - | Error _ -> "error" - in - `String s - - let output_node_locality { loc_file ; loc_callstack } = - let f1 = ("file", `String loc_file) in - let fields = match loc_callstack with - | [] -> [f1] - | cs -> [f1 ; ("callstack", output_callstack cs)] - in - `Assoc fields - - let output_range range = - match range with - | Empty -> `String "empty" - | Singleton -> `String "singleton" - | Normal range_grade -> `Int range_grade - | Wide -> `String "wide" - - let output_dep_kind kind = - let s = match kind with - | Callee -> "callee" - | Data -> "data" - | Address -> "addr" - | Control -> "ctrl" - | Composition -> "comp" - in - `String s - - let output_node_values values = - match values with - | None -> `Null - | Some cvalue when Cvalue.V.is_bottom cvalue -> `Null - | Some cvalue -> `String (Pretty_utils.to_string Cvalue.V.pretty cvalue) - - let output_computation = function - | Done -> `String "yes" - | Partial _ -> `String "partial" - | NotDone -> `String "no" - - let output_taint = function - | Eva.Results.Direct -> `String "direct" - | Indirect -> `String "indirect" - | Untainted -> `String "untainted" - - let output_node node = - let label = Pretty_utils.to_string Node_kind.pretty node.node_kind in - `Assoc ([ - ("id", `Int node.node_key) ; - ("label", `String label) ; - ("kind", output_node_kind node.node_kind) ; - ("locality", output_node_locality node.node_locality) ; - ("is_root", `Bool node.node_is_root) ; - ("backward_explored", output_computation node.node_writes_computation) ; - ("forward_explored", output_computation node.node_reads_computation) ; - ("writes", `List (List.map output_stmt node.node_writes_stmts)) ; - ("values", output_node_values node.node_values) ; - ("range", output_range node.node_range) ; - ] @ - begin match Node_kind.to_lval node.node_kind with - | None -> [] - | Some lval -> - let typ = Cil.typeOfLval lval in - let str = Pretty_utils.to_string Cil_printer.pp_typ typ in - [("type", `String str)] - end @ - begin match node.node_taint with - | None -> [] - | Some t -> [("taint", output_taint t)] - end) - - let output_dep (n1,dep,n2) = - `Assoc [ - ("id", `Int dep.dependency_key) ; - ("src", `Int n1.node_key) ; - ("dst", `Int n2.node_key) ; - ("kind", output_dep_kind dep.dependency_kind) ; - ("origins", `List (List.map output_stmt dep.dependency_origins)) ; - ] - - let output_graph g = - `Assoc [ - ("nodes", `List (List.map output_node (vertices g))) ; - ("deps", `List (List.map output_dep (edges g))) - ] - - let output_diff g diff = - let root = match diff.last_root with - | None -> `Null - | Some root -> `Int root.node_key - and added_nodes = List.map output_node diff.added_nodes - and added_deps = - let module Set = Set.Make (struct - type t = edge - let compare (_,d1,_) (_,d2,_) = d1.dependency_key - d2.dependency_key - end) - in - let collect_deps set node = - let set = fold_pred_e Set.add g node set in - let set = fold_succ_e Set.add g node set in - set - in - let set = List.fold_left collect_deps Set.empty diff.added_nodes in - List.map output_dep (Set.elements set) - and removed_nodes = - List.map (fun node -> `Int node.node_key) diff.removed_nodes - in - `Assoc [ - ("root", root) ; - ("add", `Assoc [ - ("nodes", `List added_nodes) ; - ("deps", `List added_deps) - ]) ; - ("sub", `List removed_nodes)] -end - -let ouptput_to_json out_channel g = - let json = JsonPrinter.output_graph g in - Yojson.Basic.to_channel out_channel json - -let to_json g = - JsonPrinter.output_graph g - -let diff_to_json g diff = - JsonPrinter.output_diff g diff diff --git a/src/plugins/dive/dive_graph.mli b/src/plugins/dive/dive_graph.mli index 987080b02037a73ce3471f257c7060174d075755..2f3e9635f8a96b2a498e8575272b8a9689125de9 100644 --- a/src/plugins/dive/dive_graph.mli +++ b/src/plugins/dive/dive_graph.mli @@ -42,8 +42,8 @@ val update_node_values : node -> typ:Cil_types.typ -> cvalue:Cvalue.V.t -> taint:Eva.Results.taint option -> unit -val create_dependency : t -> Cil_types.kinstr -> - node -> dependency_kind -> node -> unit +val create_dependency : t -> origin:origin -> kind:dependency_kind -> + node -> node -> node * dependency * node val remove_dependency : t -> node * dependency * node -> unit val remove_dependencies : t -> node -> unit @@ -52,8 +52,4 @@ val find_independant_nodes : t -> node list -> node list val bfs : ?iter_succ:((node -> unit) -> t -> node -> unit) -> ?limit:int -> t -> node list -> node list -val ouptput_to_dot : out_channel -> t -> unit -val ouptput_to_json : out_channel -> t -> unit - -val to_json : t -> Json.t -val diff_to_json : t -> graph_diff -> Json.t +val output_to_dot : out_channel -> t -> unit diff --git a/src/plugins/dive/dive_types.ml b/src/plugins/dive/dive_types.ml index c71f7f375cd6f901e8c23e25539249b2a41bbdac..b38f5e975a499d4cf08cf055547cbef0c3e34d7d 100644 --- a/src/plugins/dive/dive_types.ml +++ b/src/plugins/dive/dive_types.ml @@ -23,8 +23,8 @@ type node_kind = | Scalar of Cil_types.varinfo * Cil_types.typ * Cil_types.offset | Composite of Cil_types.varinfo - | Scattered of Cil_types.lval * Cil_types.kinstr - | Unknown of Cil_types.lval * Cil_types.kinstr + | Scattered of Cil_types.lval * Cil_types.stmt + | Unknown of Cil_types.lval * Cil_types.stmt | Alarm of Cil_types.stmt * Alarms.alarm | AbsoluteMemory | String of int * Base.cstring @@ -46,6 +46,8 @@ type node_range = type computation = NotDone | Partial of (unit Seq.t) | Done +type origin = Studia.Writes.t + type node = { node_key : int; node_kind : node_kind; @@ -57,7 +59,7 @@ type node = { mutable node_taint : Eva.Results.taint option; mutable node_writes_computation : computation; mutable node_reads_computation : computation; - mutable node_writes_stmts : Cil_types.stmt list; + mutable node_writes : origin list; } type dependency_kind = Callee | Data | Address | Control | Composition @@ -65,7 +67,7 @@ type dependency_kind = Callee | Data | Address | Control | Composition type dependency = { dependency_key : int; dependency_kind : dependency_kind; - mutable dependency_origins : Cil_types.stmt list; + mutable dependency_origins : origin list; } type graph_diff = { diff --git a/src/plugins/dive/main.ml b/src/plugins/dive/main.ml index 86d8e2d5393c6c7f224a152c1b775cc6b03b9b69..6c81b013f84c8a11d4aea07b9852af7cc1ca04f4 100644 --- a/src/plugins/dive/main.ml +++ b/src/plugins/dive/main.ml @@ -24,8 +24,8 @@ type format = Dot | Json let output format context filename = let output_function = match format with - | Dot -> Dive_graph.ouptput_to_dot - | Json -> Dive_graph.ouptput_to_json + | Dot -> Dive_graph.output_to_dot + | Json -> Server_interface.output_to_json in Self.result "output to %a" Filepath.Normalized.pretty filename; let out_channel = open_out (filename:>string) in @@ -35,6 +35,8 @@ let output format context filename = let main () = if not (Self.FromBases.is_empty () && Self.FromFunctionAlarms.is_empty ()) then begin + (* Make sure Eva is computed *) + Eva.Analysis.compute (); (* Create the initial graph *) let context = Context.create () in (* Handle parameters *) diff --git a/src/plugins/dive/node_kind.ml b/src/plugins/dive/node_kind.ml index 1d46ba6136ea6653d82e21a4d3f5fcc9ff9a3f7f..de501c05d61436230f0a301480d9dbf678f1a967 100644 --- a/src/plugins/dive/node_kind.ml +++ b/src/plugins/dive/node_kind.ml @@ -51,12 +51,12 @@ struct | Composite vi1, Composite vi2 -> Varinfo.compare vi1 vi2 | Composite _, _ -> 1 | _, Composite _ -> -1 - | Scattered (lv1,ki1), Scattered (lv2,ki2) -> - LvalStructEq.compare lv1 lv2 <?> (Kinstr.compare, ki1, ki2) + | Scattered (lv1,stmt1), Scattered (lv2,stmt2) -> + LvalStructEq.compare lv1 lv2 <?> (Stmt.compare, stmt1, stmt2) | Scattered _, _ -> 1 | _, Scattered _ -> -1 - | Unknown (lv1,ki1), Unknown (lv2,ki2) -> - LvalStructEq.compare lv1 lv2 <?> (Kinstr.compare, ki1, ki2) + | Unknown (lv1,stmt1), Unknown (lv2,stmt2) -> + LvalStructEq.compare lv1 lv2 <?> (Stmt.compare, stmt1, stmt2) | Unknown _, _ -> 1 | _, Unknown _ -> -1 | Alarm (stmt1, alarm1), Alarm (stmt2, alarm2) -> @@ -82,10 +82,10 @@ struct | Scalar (vi1, _, offset1), Scalar (vi2, _, offset2) -> Varinfo.equal vi1 vi2 && OffsetStructEq.equal offset1 offset2 | Composite vi1, Composite vi2 -> Varinfo.equal vi1 vi2 - | Scattered (lv1, ki1), Scattered (lv2, ki2) -> - LvalStructEq.equal lv1 lv2 && Kinstr.equal ki1 ki2 - | Unknown (lv1, ki1), Unknown (lv2, ki2) -> - LvalStructEq.equal lv1 lv2 && Kinstr.equal ki1 ki2 + | Scattered (lv1, stmt1), Scattered (lv2, stmt2) -> + LvalStructEq.equal lv1 lv2 && Stmt.equal stmt1 stmt2 + | Unknown (lv1, stmt1), Unknown (lv2, stmt2) -> + LvalStructEq.equal lv1 lv2 && Stmt.equal stmt1 stmt2 | Alarm (stmt1, alarm1), Alarm (stmt2, alarm2) -> Stmt.equal stmt1 stmt2 && Alarms.equal alarm1 alarm2 | AbsoluteMemory, AbsoluteMemory -> true @@ -99,10 +99,10 @@ struct | Scalar (vi, _, offset) -> Hashtbl.hash (1, Varinfo.hash vi, OffsetStructEq.hash offset) | Composite vi -> Hashtbl.hash (2, Varinfo.hash vi) - | Scattered (lv, ki) -> - Hashtbl.hash (3, LvalStructEq.hash lv, Kinstr.hash ki) - | Unknown (lv, ki) -> - Hashtbl.hash (4, LvalStructEq.hash lv, Kinstr.hash ki) + | Scattered (lv, stmt) -> + Hashtbl.hash (3, LvalStructEq.hash lv, Stmt.hash stmt) + | Unknown (lv, stmt) -> + Hashtbl.hash (4, LvalStructEq.hash lv, Stmt.hash stmt) | Alarm (stmt, alarm) -> Hashtbl.hash (5, Stmt.hash stmt, Alarms.hash alarm) | AbsoluteMemory -> 6 diff --git a/src/plugins/dive/self.ml b/src/plugins/dive/self.ml index 4e3bb2c1eef4774d191c2084ee7107b65cf29c20..df6cbfc9216ce23512ee8496d27abe6913b1116e 100644 --- a/src/plugins/dive/self.ml +++ b/src/plugins/dive/self.ml @@ -75,9 +75,9 @@ struct with Not_found -> raise (Cannot_build ("no function '" ^ function_name ^ "'")) in - try Globals.Vars.find_from_astinfo variable_name (VLocal kf) + try Globals.Vars.find_from_astinfo variable_name (Whole_function kf) with Not_found -> - try Globals.Vars.find_from_astinfo variable_name (VFormal kf) + try Globals.Vars.find_from_astinfo variable_name (Formal kf) with Not_found -> raise (Cannot_build ("no variable '" ^ variable_name ^ "' in function " ^ function_name)) diff --git a/src/plugins/dive/server_interface.ml b/src/plugins/dive/server_interface.ml index dab161a0c2940d6df6015dad2930651fbee98386..e3fcfb5515fe51d96dd70148975d4b7677f555a4 100644 --- a/src/plugins/dive/server_interface.ml +++ b/src/plugins/dive/server_interface.ml @@ -25,225 +25,417 @@ open Data open Dive_types let package = Package.package ~plugin:"dive" ~title:"Dive Services" () +let declare name ?(descr = name) = + Data.declare ~package ~name ~descr:(Markdown.plain descr) +module Enum (X: sig type t end) = +struct + include Enum + let dictionary: X.t dictionary = Enum.dictionary () + let tag name descr = Enum.tag ~name ~descr:(Markdown.plain descr) dictionary + let publish lookup name descr = + set_lookup dictionary lookup; + Request.dictionary ~package ~name ~descr:(Markdown.plain descr) dictionary +end -(* -------------------------------------------------------------------------- *) -(* --- State handling --- *) -(* -------------------------------------------------------------------------- *) - -(* TODO: project state *) -let get_context = - let context = ref None in - fun () -> - match !context with - | Some c -> c - | None -> - if Eva.Analysis.is_computed () then - let c = Context.create () in - context := Some c; - c - else - Server.Data.failure "Eva analysis not computed" - - -let global_window = ref { - perception = { backward = Some 2 ; forward = Some 1 }; - horizon = { backward = None ; forward = None }; - } +module Record () = +struct + include Record + type record + let record : record Record.signature = Record.signature () + let field name ?(descr = name) = + Record.field record ~name ~descr:(Markdown.plain descr) + let option name ?(descr = name) = + Record.option record ~name ~descr:(Markdown.plain descr) + let publish ?descr name = + let descr = Option.map Markdown.plain descr in + Record.publish record ~package ~name ?descr +end (* -------------------------------------------------------------------------- *) (* --- Data types --- *) (* -------------------------------------------------------------------------- *) -module Range : Data.S with type t = int option range = -struct - type t = int option range - let name = "range" - let descr = Markdown.plain "Parametrization of the exploration range." - let sign : t Record.signature = Record.signature () +let stmt_to_location stmt = + let kf = Kernel_function.find_englobing_kf stmt in + (kf, Printer_tag.PStmtStart (kf, stmt)) + +let origin_to_locations = function + | Studia.Writes.Assign s + | CallDirect s -> [stmt_to_location s] + | CallIndirect _s -> [] + | GlobalInit (_vi, _init) -> [] + | FormalInit (_vi, callsites) -> + List.concat_map (fun (_,l) -> List.map stmt_to_location l) callsites - module Fields = - struct - let backward = Record.option sign - ~name:"backward" - ~descr:(Markdown.plain "range for the write dependencies") - (module (Jint)) - let forward = Record.option sign - ~name:"forward" - ~descr:(Markdown.plain "range for the read dependencies") - (module (Jint)) - end +module Range : Data.S with type t = int option range = +struct + include Record () - module Record = (val Record.publish ~package ~name ~descr sign) + let backward = + option "backward" ~descr:"range for the write dependencies" jint + let forward = + option "forward" ~descr:"range for the read dependencies" jint - let jtype = Record.jtype + let descr = "Parametrization of the exploration range." + include (val publish "range" ~descr) + type t = int option range - let to_json r = - Record.default |> - Record.set Fields.backward r.backward |> - Record.set Fields.forward r.forward |> - Record.to_json + let to_json r= + default |> + set backward r.backward |> + set forward r.forward |> + to_json let of_json js = - let r = Record.of_json js in - { - backward = Record.get Fields.backward r; - forward = Record.get Fields.forward r; - } + let r = of_json js in + { backward = get backward r; forward = get forward r; } end module Window : Data.S with type t = window = struct - type t = window - let name = "explorationWindow" - let descr = Markdown.plain "Global parametrization of the exploration." - let sign : t Record.signature = Record.signature () - - module Fields = - struct - let perception = Record.field sign - ~name:"perception" - ~descr:(Markdown.plain "how far dive will explore from root nodes ; \ - must be a finite range") - (module Range) + include Record () - let horizon = Record.field sign - ~name:"horizon" - ~descr:(Markdown.plain "range beyond which the nodes must be hidden") - (module Range) - end + let perception = + let descr = "how far dive will explore from root nodes ; \ + must be a finite range" in + field "perception" ~descr (module Range) - module Record = (val Record.publish ~package ~name ~descr sign) + let horizon = + let descr = "range beyond which the nodes must be hidden" in + field "horizon" ~descr (module Range) - let jtype = Record.jtype + let descr = "Global parametrization of the exploration." + include (val publish "explorationWindow" ~descr) + type t = window let to_json w = - Record.default |> - Record.set Fields.perception w.perception |> - Record.set Fields.horizon w.horizon |> - Record.to_json + default |> + set perception w.perception |> + set horizon w.horizon |> + to_json let of_json js = - let r = Record.of_json js in - { - perception = Record.get Fields.perception r; - horizon = Record.get Fields.horizon r; - } + let r = of_json js in + { perception = get perception r; horizon = get horizon r; } end module NodeId = struct - type t = node - let name = "nodeId" - let descr = Markdown.plain "A node identifier in the graph" - - let jtype = Data.declare ~package ~name ~descr Data.Jint.jtype - - let _to_json node = - `Int node.node_key - - let of_json json = - let node_key = Data.Jint.of_json json in - try - Context.find_node (get_context ()) node_key - with Not_found -> - Data.failure "no node '%d' in the current graph" node_key + include Data.Jint + let jtype = declare "nodeId" ~descr:"A node identifier in the graph" jtype end module Callsite = struct - let name = "callsite" - let descr = Markdown.plain "A callsite" - let jtype = Data.declare ~package ~name ~descr (Jrecord [ + type t = Cil_types.kernel_function * Cil_types.kinstr + let jtype = declare "callsite" (Jrecord [ "fun", Jstring; - "instr", Junion [ Jnumber ; Jstring ]; + "instr", Junion [ Jnumber ; Jtag "global" ]; ]) + + let output_kinstr = function + | Cil_types.Kglobal -> `String "global" + | Cil_types.Kstmt stmt -> `Int stmt.sid + + let to_json (kf, kinstr) = + `Assoc [ + ("fun", `String (Kernel_function.get_name kf)) ; + ("instr", output_kinstr kinstr) ; + ] + + let of_json _ = Data.failure "Callsite.of_json not implemented" end module Callstack = struct - let name = "callstack" - let descr = Markdown.plain "The callstack context for a node" - let jtype = Data.declare ~package ~name ~descr (Jarray Callsite.jtype) + include Data.Jlist (Callsite) + let descr = "The callstack context for a node" + let jtype = declare "callstack" ~descr jtype end module NodeLocality = struct - let name = "nodeLocality" - let descr = Markdown.plain "The description of a node locality" - let jtype = Data.declare ~package ~name ~descr (Jrecord [ - "file", Jstring; - "callstack", Joption (Callstack.jtype) - ]) + include Record () + + let file = field "file" jstring + let callstack = option "callstack" (module Callstack) + + let descr = "The description of a node locality" + include (val publish "nodeLocality" ~descr) + type t = node_locality + + let to_json t = + let to_option = function [] -> None | l -> Some l in + default |> + set file t.loc_file |> + set callstack (to_option t.loc_callstack) |> + to_json + + let of_json js = + let r = of_json js in + { loc_file = get file r ; + loc_callstack = Option.value ~default:[] (get callstack r) } +end + +module NodeKind = struct + include Enum (struct type t = node_kind end) + + let scalar = tag "scalar" "a single memory cell" + let composite = tag "composite" "a memory bloc containing cells" + let scattered = tag "scattered" "a set of memory locations designated by \ + an lvalue" + let unknown = tag "unknown" "an unresolved memory location" + let alarm = tag "alarm" "an alarm emitted by Frama-C" + let absolute = tag "absolute" "a memory location designated by a range \ + of adresses" + let string = tag "string" "a string literal" + let error = tag "error" "a placeholder node when an error prevented \ + the generation process" + let const = tag "const" "a numeric constant literal" + + let lookup = function + | Scalar _ -> scalar + | Composite _ -> composite + | Scattered _ -> scattered + | Unknown _ -> unknown + | Alarm _ -> alarm + | AbsoluteMemory -> absolute + | String _ -> string + | Const _ -> const + | Error _ -> error + + include (val publish lookup "nodeKind" "The nature of a node") +end + +module Taint = struct + include Enum (struct type t = Eva.Results.taint end) + + let untainted = tag "untainted" "not tainted by anything" + let indirect = tag "indirect" "tainted by control" + let direct = tag "direct" "tainted by data" + + let lookup = function + | Eva.Results.Direct -> direct + | Indirect -> indirect + | Untainted -> untainted + + include (val publish lookup "taint" "Taint of a memory location") +end + +module Computation = struct + include Enum (struct type t = computation end) + + let yes = tag "yes" "all dependencies have been computed" + let partial = tag "partial" "some dependencies have been explored" + let no = tag "no" "dependencies have not been computed" + + let lookup = function + | Done -> yes + | Partial _ -> partial + | NotDone -> no + + let descr = "The computation state of a node read or write dependencies" + include (val publish lookup "exploration" descr) +end + +module NodeSpecialRange = struct + include Enum (struct type t = node_range end) + + let empty = tag "empty" "no value ever computed for this node" + let singleton = tag "singleton" "this node can only have one value" + let wide = tag "wide" "this node can take almost all values of its type" + + let lookup = function + | Empty -> empty + | Singleton -> singleton + | Wide -> wide + | Normal _ -> raise Not_found + + let descr = "A qualitative description of the range of values \ + that this node can take." + + include (val publish lookup "nodeSpecialRange" descr) +end + +module NodeRange = struct + type t = node_range + let descr = "A qualitative or quantitative description of the range of \ + values that this node can take." + let jtype = declare "nodeRange" ~descr + (Junion [ Jnumber ; NodeSpecialRange.jtype ]) + + let to_json = function + | Normal range_grade -> `Int range_grade + | range -> NodeSpecialRange.to_json range + + let of_json _ = Data.failure "NodeRange.of_json not implemented" end module Node = struct - let name = "node" - let descr = Markdown.plain "A graph node" - let jtype = Data.declare ~package ~name ~descr (Jrecord [ - "id", NodeId.jtype; - "label", Jstring; - "kind", Jstring; - "locality", NodeLocality.jtype; - "is_root", Jboolean; - "backward_explored", Jstring; - "forward_explored", Jstring; - "writes", Jarray Kernel_ast.Location.jtype; - "values", Joption Jstring; - "range", Junion [ Jnumber ; Jstring ]; - "type", Joption Jstring; - "taint", Joption (Junion [ - Jtag "direct"; Jtag "indirect"; Jtag "untainted"]) - ]) + include Record () + + let id = field "id" (module NodeId) + let label = field "label" jstring + let nkind = field "nkind" (module NodeKind) + let locality = field "locality" (module NodeLocality) + let is_root = field "is_root" jbool + let backward_explored = field "backward_explored" (module Computation) + let forward_explored = field "forward_explored" (module Computation) + let writes = field "writes" (module Jlist (Kernel_ast.Location)) + let values = field "values" (joption jstring) + let range = field "range" (module NodeRange) + let typ = option "type" jstring + let taint = option "taint" (module Taint) + + include (val publish "node") + + let node_type node = + match Node_kind.to_lval node.node_kind with + | None -> None + | Some lval -> + let typ = Cil.typeOfLval lval in + Some (Pretty_utils.to_string Cil_printer.pp_typ typ) + + let to_json node = + default |> + set id node.node_key |> + set label (Pretty_utils.to_string Node_kind.pretty node.node_kind) |> + set nkind node.node_kind |> + set locality node.node_locality |> + set is_root node.node_is_root |> + set backward_explored node.node_writes_computation |> + set forward_explored node.node_reads_computation |> + set writes (List.concat_map origin_to_locations node.node_writes) |> + set values + (Option.map (Pretty_utils.to_string Cvalue.V.pretty) node.node_values) |> + set range node.node_range |> + set typ (node_type node) |> + set taint node.node_taint |> + to_json end module Dependency = struct - let name = "dependency" - let descr = Markdown.plain "The dependency between two nodes" - let jtype = Data.declare ~package ~name ~descr (Jrecord [ - "id", Jnumber ; - "src", NodeId.jtype ; - "dst", NodeId.jtype ; - "kind", Jstring ; - "origins", Jarray Kernel_ast.Location.jtype - ]) + include Record () + + let id = field "id" jint + let src = field "src" (module NodeId) + let dst = field "dst" (module NodeId) + let dkind = field "dkind" jstring + let origins = field "origins" (module Jlist (Kernel_ast.Location)) + + include (val publish "dependency" ~descr:"The dependency between two nodes") + + let dep_kind = function + | Callee -> "callee" + | Data -> "data" + | Address -> "addr" + | Control -> "ctrl" + | Composition -> "comp" + + let to_json (n1, dep, n2) = + default |> + set id dep.dependency_key |> + set src n1.node_key |> + set dst n2.node_key |> + set dkind (dep_kind dep.dependency_kind) |> + set origins (List.concat_map origin_to_locations dep.dependency_origins) |> + to_json end -module Graph = +module Element = struct - type t = Dive_graph.t - let name = "graphData" - let descr = Markdown.plain "The whole graph being built" - let jtype = Data.declare ~package ~name ~descr (Jrecord [ - "nodes", Jarray Node.jtype; - "deps", Jarray Dependency.jtype - ]) + type t = Context.element = Node of node | Edge of (node * dependency * node) + let descr = "A graph element, either a node or a dependency" + let jtype = declare "element" ~descr (Junion [Node.jtype ; Dependency.jtype]) - let to_json = Dive_graph.to_json + let to_json = function + | Node v -> Node.to_json v + | Edge edge -> Dependency.to_json edge end -module GraphDiff = +(* -------------------------------------------------------------------------- *) +(* --- State handling --- *) +(* -------------------------------------------------------------------------- *) + +let global_window = ref { + perception = { backward = Some 2 ; forward = Some 1 }; + horizon = { backward = None ; forward = None }; + } + +let get_context = (* TODO: projectify ? *) + let context = Context.create () in + fun () -> + if Eva.Analysis.is_computed () then + context + else + Server.Data.failure "Eva analysis not computed" + +let vertices g = Dive_graph.fold_vertex (fun n acc -> n ::acc) g [] +let edges g = Dive_graph.fold_edges_e (fun d acc -> d ::acc) g [] + +let output_graph g = + `Assoc [ + ("nodes", `List (List.map Node.to_json (vertices g))) ; + ("deps", `List (List.map Dependency.to_json (edges g))) + ] + +let output_to_json out_channel g = + let json = output_graph g in + Yojson.Basic.to_channel out_channel json + +module Graph = struct - type t = Dive_graph.t * graph_diff - let name = "diffData" - let descr = Markdown.plain "Graph differences from the last action." - let jtype = Data.declare ~package ~name ~descr (Jrecord [ - "root", Joption NodeId.jtype; - "add", Jrecord [ - "nodes", Jarray Node.jtype; - "deps", Jarray Dependency.jtype - ]; - "sub", Jarray NodeId.jtype - ]) + let name = "graph" + let model = States.model () + let descr = Markdown.plain "The graph being built as a set of vertices and \ + edges" + + let key = function + | Element.Node v -> Format.sprintf "n%d" v.node_key + | Edge (_,dep,_) -> Format.sprintf "d%d" dep.dependency_key + + let () = States.column model ~name:"element" + ~descr:(Markdown.plain "a graph element") + ~data:(module Element) + ~get:(fun el -> el) + + + let iter f = + let context = get_context () in + let graph = Context.get_graph context in + Dive_graph.iter_vertex (fun v -> f (Element.Node v)) graph; + Dive_graph.iter_edges_e (fun e -> f (Element.Edge e)) graph + + let _array = + let hook f = + fun g -> f (get_context ()) g + in + States.register_array ~package ~name ~descr ~key ~iter model + ~add_update_hook:(hook Context.set_update_hook) + ~add_remove_hook:(hook Context.set_remove_hook) + ~add_reload_hook:(hook Context.set_clear_hook) +end + - let to_json = fun (g,d) -> Dive_graph.diff_to_json g d +module NodeId' = +struct + type t = node + let jtype = NodeId.jtype + let to_json node = NodeId.to_json node.node_key + let of_json json = + let node_key = Data.Jint.of_json json in + try + Context.find_node (get_context ()) node_key + with Not_found -> + Data.failure "no node '%d' in the current graph" node_key end @@ -251,26 +443,19 @@ end (* --- Actions --- *) (* -------------------------------------------------------------------------- *) -let result context last_root = - let diff = Context.take_last_diff context in - Context.get_graph context, { diff with last_root } - -let finalize' context node_opt = - begin match node_opt with - | None -> () - | Some node -> - let may_explore f = - Option.iter (fun depth -> f ~depth context node) - in - may_explore Build.explore_backward !global_window.perception.backward; - may_explore Build.explore_forward !global_window.perception.forward; - let horizon = !global_window.horizon in - if Option.is_some horizon.forward || - Option.is_some horizon.backward - then - Build.reduce_to_horizon context horizon node - end; - result context node_opt +let finalize' context = function + | None -> () + | Some node -> + let may_explore f = + Option.iter (fun depth -> f ~depth context node) + in + may_explore Build.explore_backward !global_window.perception.backward; + may_explore Build.explore_forward !global_window.perception.forward; + let horizon = !global_window.horizon in + if Option.is_some horizon.forward || + Option.is_some horizon.backward + then + Build.reduce_to_horizon context horizon node let finalize context node = finalize' context (Some node) @@ -281,12 +466,6 @@ let () = Request.register ~package ~input:(module Window) ~output:(module Data.Junit) (fun window -> global_window := window) -let () = Request.register ~package - ~kind:`GET ~name:"graph" - ~descr:(Markdown.plain "Retrieve the whole graph") - ~input:(module Data.Junit) ~output:(module Graph) - (fun () -> Context.get_graph (get_context ())) - let () = Request.register ~package ~kind:`EXEC ~name:"clear" ~descr:(Markdown.plain "Erase the graph and start over with an empty one") @@ -296,16 +475,18 @@ let () = Request.register ~package let () = Request.register ~package ~kind:`EXEC ~name:"add" ~descr:(Markdown.plain "Add a node to the graph") - ~input:(module Kernel_ast.Marker) ~output:(module GraphDiff) + ~input:(module Kernel_ast.Marker) ~output:(module Joption (NodeId')) begin fun loc -> let context = get_context () in - finalize' context (Build.add_localizable context loc) + let node = Build.add_localizable context loc in + finalize' context node; + node end let () = Request.register ~package ~kind:`EXEC ~name:"explore" ~descr:(Markdown.plain "Explore the graph starting from an existing vertex") - ~input:(module NodeId) ~output:(module GraphDiff) + ~input:(module NodeId') ~output:(module Data.Junit) begin fun node -> let context = get_context () in Build.show context node; @@ -315,7 +496,7 @@ let () = Request.register ~package let () = Request.register ~package ~kind:`EXEC ~name:"show" ~descr:(Markdown.plain "Show the dependencies of an existing vertex") - ~input:(module NodeId) ~output:(module GraphDiff) + ~input:(module NodeId') ~output:(module Data.Junit) begin fun node -> let context = get_context () in Build.show context node; @@ -326,7 +507,7 @@ let () = Request.register ~package let () = Request.register ~package ~kind:`EXEC ~name:"hide" ~descr:(Markdown.plain "Hide the dependencies of an existing vertex") - ~input:(module NodeId) ~output:(module GraphDiff) + ~input:(module NodeId') ~output:(module Data.Junit) begin fun node -> let context = get_context () in Build.hide context node; diff --git a/src/plugins/dive/server_interface.mli b/src/plugins/dive/server_interface.mli index bd656c9049e55b9db813ea3a69c9d0538ce4a763..d8adab7ed6a4aef38c4fa25a4bfcfdf3b0811aad 100644 --- a/src/plugins/dive/server_interface.mli +++ b/src/plugins/dive/server_interface.mli @@ -21,3 +21,5 @@ (**************************************************************************) (* Dive API for the server. Nothing is exported. *) + +val output_to_json: out_channel -> Dive_graph.t -> unit diff --git a/src/plugins/dive/tests/dive/oracle/assigned_param.dot b/src/plugins/dive/tests/dive/oracle/assigned_param.dot index a1190d2d94fd0e19e93369c4f7543bcf51d966d6..dbf37f6f407a6e3967e6f8f52940fa21910a2279 100644 --- a/src/plugins/dive/tests/dive/oracle/assigned_param.dot +++ b/src/plugins/dive/tests/dive/oracle/assigned_param.dot @@ -3,21 +3,21 @@ digraph G { style="filled,bold", ]; cp3 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp5 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp5 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp7 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp7 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; cp9 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - subgraph cluster_cs_1 { label=<main>; cp9;cp5;cp2; - subgraph cluster_cs_2 { label=<f>; cp7;cp3; + subgraph cluster_cs_1 { label=<main>; cp9;cp7;cp2; + subgraph cluster_cs_2 { label=<f>; cp5;cp3; }; }; cp3 -> cp2; cp5 -> cp3; cp7 -> cp3; - cp9 -> cp7; + cp9 -> cp5; } \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/callstack_global.dot b/src/plugins/dive/tests/dive/oracle/callstack_global.dot index d2245d10a588309fb482b7056f5153ce5016c37c..927402ef746431e2a2fddfc9e44d18404d0fcf87 100644 --- a/src/plugins/dive/tests/dive/oracle/callstack_global.dot +++ b/src/plugins/dive/tests/dive/oracle/callstack_global.dot @@ -13,14 +13,15 @@ digraph G { style="filled", ]; cp15 [label=<x>, shape=box, fillcolor="#EEFFEE", color="#004400", style="filled", ]; - cp17 [label=<x2>, shape=box, fillcolor="#AACCFF", color="#88AAFF", - style="filled", ]; + cp17 [label=<0>, shape=ellipse, ]; cp19 [label=<x1>, shape=box, fillcolor="#AACCFF", color="#88AAFF", style="filled", ]; - cp21 [label=<39>, shape=ellipse, ]; + cp21 [label=<x2>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + style="filled", ]; cp23 [label=<3>, shape=ellipse, ]; + cp25 [label=<39>, shape=ellipse, ]; - subgraph cluster_cs_1 { label=<main>; cp23;cp21;cp19;cp17;cp5;cp3;cp2; + subgraph cluster_cs_1 { label=<main>; cp25;cp23;cp21;cp19;cp5;cp3;cp2; subgraph cluster_cs_2 { label=<f>; cp7; }; subgraph cluster_cs_3 { label=<f>; cp9; @@ -28,7 +29,7 @@ digraph G { }; subgraph cluster_cs_4 { label=<f>; cp15; }; - subgraph cluster_file_1 { label=<callstack_global.i>; cp11; + subgraph cluster_file_1 { label=<callstack_global.i>; cp17;cp11; }; cp3 -> cp2; @@ -39,9 +40,10 @@ digraph G { cp11 -> cp9; cp11 -> cp11; cp15 -> cp11; - cp17 -> cp15; + cp17 -> cp11; cp19 -> cp15; - cp21 -> cp17; + cp21 -> cp15; cp23 -> cp19; + cp25 -> cp21; } \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot b/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot index 1944fac8cbf2e0aeb6d60f86d28a5cb43919f25e..f343686a117e0a25a97402d5b40f0ebad3efc64f 100644 --- a/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot +++ b/src/plugins/dive/tests/dive/oracle/callstack_strategy.dot @@ -5,15 +5,15 @@ digraph G { style="filled", ]; cp5 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp7 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp7 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp9 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp9 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; cp11 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp13 [label=<a>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp13 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp15 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp15 [label=<a>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; cp18 [label=<x>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; @@ -22,13 +22,13 @@ digraph G { subgraph cluster_cs_4 { label=<f>; cp11; }; }; - subgraph cluster_cs_2 { label=<i>; cp7; - }; - subgraph cluster_cs_3 { label=<h>; cp18;cp9; - subgraph cluster_cs_6 { label=<f>; cp15; + subgraph cluster_cs_2 { label=<h>; cp18;cp7; + subgraph cluster_cs_5 { label=<f>; cp13; }; }; - subgraph cluster_cs_5 { label=<main>; cp13; + subgraph cluster_cs_3 { label=<i>; cp9; + }; + subgraph cluster_cs_6 { label=<main>; cp15; }; cp3 -> cp2; @@ -38,8 +38,8 @@ digraph G { cp9 -> cp3; cp11 -> cp5; cp13 -> cp7; - cp13 -> cp18; cp15 -> cp9; - cp18 -> cp15; + cp15 -> cp18; + cp18 -> cp13; } \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/global.dot b/src/plugins/dive/tests/dive/oracle/global.dot index 36c6ca1aa9f8d8457b593fa6eccfe780127a22bc..2659479de44b35d430becb1153d31d1a0c3dde6d 100644 --- a/src/plugins/dive/tests/dive/oracle/global.dot +++ b/src/plugins/dive/tests/dive/oracle/global.dot @@ -7,15 +7,17 @@ digraph G { style="filled", ]; cp7 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; + cp9 [label=<0>, shape=ellipse, ]; subgraph cluster_cs_1 { label=<main>; cp7;cp5;cp2; }; - subgraph cluster_file_1 { label=<global.i>; cp3; + subgraph cluster_file_1 { label=<global.i>; cp9;cp3; }; cp3 -> cp2; cp5 -> cp2; cp5 -> cp7; cp7 -> cp3; + cp9 -> cp3; } \ No newline at end of file diff --git a/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot b/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot index 1978773631238f75819acf83686dc50b242d2366..c1212e05cefdb363f882f5cb34a1b977b4c942a1 100644 --- a/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot +++ b/src/plugins/dive/tests/dive/oracle/unfocused_callers.dot @@ -12,11 +12,11 @@ digraph G { subgraph cluster_cs_1 { label=<g>; cp2; }; - subgraph cluster_cs_2 { label=<f3>; cp3; + subgraph cluster_cs_2 { label=<f1>; cp3; }; subgraph cluster_cs_3 { label=<f2>; cp5; }; - subgraph cluster_cs_4 { label=<f1>; cp7; + subgraph cluster_cs_4 { label=<f3>; cp7; }; subgraph cluster_cs_5 { label=<main>; cp9; }; diff --git a/src/plugins/dive/tests/dive/oracle/various.dot b/src/plugins/dive/tests/dive/oracle/various.dot index d661acee21a6b81d2dc2e4e1243d9adafee1eee7..0a9076386dcb14e7caaaf483c9ecafa96355fd46 100644 --- a/src/plugins/dive/tests/dive/oracle/various.dot +++ b/src/plugins/dive/tests/dive/oracle/various.dot @@ -1,69 +1,71 @@ digraph G { cp2 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled,bold", ]; - cp3 [label=<x>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + cp3 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp5 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp5 [label=<x>, shape=box, fillcolor="#AACCFF", color="#88AAFF", style="filled", ]; - cp8 [label=<g>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + cp9 [label=<g>, shape=box, fillcolor="#AACCFF", color="#88AAFF", style="filled", ]; - cp11 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp11 [label=<0>, shape=ellipse, ]; + cp13 [label=<z>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled,bold", ]; - cp12 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp14 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp14 [label=<w>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp16 [label=<w>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp16 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp18 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp18 [label=<tmp_0>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp20 [label=<tmp_0>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp21 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp22 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp23 [label=<pf>, shape=box, fillcolor="#AACCFF", color="#88AAFF", + cp25 [label=<pf>, shape=box, fillcolor="#AACCFF", color="#88AAFF", style="filled", ]; - cp25 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp27 [label=<x2>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp28 [label=<& f>, shape=ellipse, ]; - cp31 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", + cp30 [label=<& f>, shape=ellipse, ]; + cp32 [label=<y>, shape=box, fillcolor="#FFBBBB", color="#FF0000", style="filled", ]; - cp34 [label=<is_nan_or_infinite: \is_finite((float)\mul_double((double)y, (double)2.0))>, + cp36 [label=<is_nan_or_infinite: \is_finite((float)\mul_double((double)y, (double)2.0))>, fillcolor="#FF0000", color="#FF0000", shape=doubleoctagon, style="filled,bold,bold", ]; - cp36 [label=<is_nan_or_infinite: \is_finite(\add_float(y, w))>, + cp38 [label=<is_nan_or_infinite: \is_finite(\add_float(y, w))>, fillcolor="#FF0000", color="#FF0000", shape=doubleoctagon, style="filled,bold,bold", ]; - subgraph cluster_cs_1 { label=<f>; cp34;cp5;cp2; + subgraph cluster_cs_1 { label=<f>; cp36;cp3;cp2; }; - subgraph cluster_cs_2 { label=<main>; cp36;cp28;cp23;cp18;cp14;cp12;cp11;cp3; - subgraph cluster_cs_3 { label=<f>; cp21;cp16; + subgraph cluster_cs_2 { label=<main>; cp38;cp30;cp25;cp20;cp16;cp14;cp13;cp5; + subgraph cluster_cs_3 { label=<f>; cp22;cp18; }; - subgraph cluster_cs_4 { label=<f>; cp31;cp25; + subgraph cluster_cs_4 { label=<f>; cp32;cp27; }; }; - subgraph cluster_file_1 { label=<various.i>; cp8; + subgraph cluster_file_1 { label=<various.i>; cp11;cp9; }; - cp2 -> cp5; + cp2 -> cp3; cp3 -> cp2; - cp3 -> cp3; - cp3 -> cp16; - cp3 -> cp25; + cp3 -> cp36; cp5 -> cp2; - cp5 -> cp34; - cp8 -> cp3; - cp12 -> cp11; - cp12 -> cp36; - cp14 -> cp11; - cp14 -> cp36; - cp16 -> cp12; - cp16 -> cp21; + cp5 -> cp5; + cp5 -> cp18; + cp5 -> cp27; + cp9 -> cp5; + cp11 -> cp9; + cp14 -> cp13; + cp14 -> cp38; + cp16 -> cp13; + cp16 -> cp38; cp18 -> cp14; - cp21 -> cp16; - cp23 -> cp18 [color="#00FF00", ]; - cp25 -> cp18; - cp25 -> cp31; - cp28 -> cp23; - cp31 -> cp25; + cp18 -> cp22; + cp20 -> cp16; + cp22 -> cp18; + cp25 -> cp20 [color="#00FF00", ]; + cp27 -> cp20; + cp27 -> cp32; + cp30 -> cp25; + cp32 -> cp27; } \ No newline at end of file diff --git a/src/plugins/e-acsl/doc/Changelog b/src/plugins/e-acsl/doc/Changelog index 4fb3fdb40ff2b7ba4d3a53fb6f57c3c264d80642..8d365c6d4a829724b44bdaac91bb6c491d01fb05 100644 --- a/src/plugins/e-acsl/doc/Changelog +++ b/src/plugins/e-acsl/doc/Changelog @@ -21,20 +21,24 @@ # configure configure ############################################################################### -############################ +############################################################################### Plugin E-ACSL <next-release> -############################ +############################################################################### + +############################################################################### +Plugin E-ACSL 27.0 (Cobalt) +############################################################################### -! e-acsl-gcc [2023-02-08] arguments to options -e/--cpp-flags now overload the default values set by e-acsl-gcc instead of being ignored. -######################### +############################################################################### Plugin E-ACSL 26.1 (Iron) -######################### +############################################################################### -######################### +############################################################################### Plugin E-ACSL 26.0 (Iron) -######################### +############################################################################### -* E-ACSL [2022-11-08] Fix clashing name when a function with contract and a logic function have the same name (frama-c/eacsl#204). @@ -48,9 +52,9 @@ Plugin E-ACSL 26.0 (Iron) -* E-ACSL [2022-17-06] Fix wrong cast from pointer to integer (frama-c/frama-c#1119). -############################## +############################################################################### Plugin E-ACSL 25.0 (Manganese) -############################## +############################################################################### -* E-ACSL [2022-23-05] Fix crash for quantifications over enum types (frama-c/e-acsl#199). @@ -79,9 +83,9 @@ Plugin E-ACSL 25.0 (Manganese) -* E-ACSL [2021-11-03] Now the same Frama-C options are used when parsing the user sources and the E-ACSL's RTL. -############################# +############################################################################### Plugin E-ACSL 24.0 (Chromium) -############################# +############################################################################### -* E-ACSL [2021-11-24] Fix code generation of properties proven invalid with a previous analysis (frama-c/e-acsl#166). @@ -116,9 +120,9 @@ Plugin E-ACSL 24.0 (Chromium) range indices (frama-c/e-acsl#148). -* E-ACSL [2021-06-04] Do not translate contracts of E-ACSL built-ins. -############################# +############################################################################### Plugin E-ACSL 23.1 (Vanadium) -############################# +############################################################################### -* E-ACSL [2021-07-19] Fix crash occurring when two or more successive logic coercions were done in a term (frama-c/e-acsl#172). @@ -129,9 +133,9 @@ Plugin E-ACSL 23.1 (Vanadium) -* E-ACSL [2021-07-13] Fix crash when encountering a GMP value in a loop variant (frama-c/e-acsl#169). -############################# +############################################################################### Plugin E-ACSL 23.0 (Vanadium) -############################# +############################################################################### -* E-ACSL [2021-05-25] Restore behavior of option -e-acsl-no-valid broken since Titanium (included). @@ -169,9 +173,9 @@ Plugin E-ACSL 23.0 (Vanadium) - E-ACSL [2020-11-17] Update e-acsl-gcc.sh so that the library dlmalloc can be compiled and used from sources. -############################# +############################################################################### Plugin E-ACSL 22.0 (Titanium) -############################# +############################################################################### -* E-ACSL [2020-11-16] Fix soundness bug when checking initialization of a chunk of heap memory block. @@ -208,9 +212,9 @@ Plugin E-ACSL 22.0 (Titanium) -* E-ACSL [2020-06-18] Fix support of VLA memory tracking (frama-c/e-acsl#119). -############################# +############################################################################### Plugin E-ACSL 21.0 (Scandium) -############################# +############################################################################### -* E-ACSL [2020-06-10] Fix ##13: bug when mixing integers and floats in annotations while -e-acsl-gmp-only is activated. @@ -232,18 +236,18 @@ Plugin E-ACSL 21.0 (Scandium) arrays that may lead to incorrect generated code. -* E-ACSL [2019-12-04] Fix bug with compiler built-ins. -############################ +############################################################################### Plugin E-ACSL 20.0 (Calcium) -############################ +############################################################################### - E-ACSL [2019-08-28] Support of rational numbers and operations. -! E-ACSL [2019-08-28] Deactivate the unsound support of real numbers (that are not rationals). They were previously unsoundly converted to floating point numbers. -############################## +############################################################################### Plugin E-ACSL 19.0 (Potassium) -############################## +############################################################################### - E-ACSL [2019-04-29] Support for logic functions and predicates without labels. @@ -263,9 +267,9 @@ Plugin E-ACSL 19.0 (Potassium) - E-ACSL [2018-11-15] Predicates with empty quantifications directly generate \true or \false instead of nested loops. -########################## +############################################################################### Plugin E-ACSL 18.0 (Argon) -########################## +############################################################################### -* E-ACSL [2018-11-13] Fix typing bug in quantifications when the guards of the quantifier variable cannot be represented into @@ -283,9 +287,9 @@ Plugin E-ACSL 18.0 (Argon) - E-ACSL [2018-09-18] Support for ranges in memory builtins (\valid, \initialized, etc). -###################################### +############################################################################### Plugin E-ACSL 17.0 (Chlorine-20180501) -###################################### +############################################################################### - E-ACSL [2018-03-30] Support for let binding. - E-ACSL [2018-02-21] New option -e-acsl-replace-libc-functions to @@ -312,9 +316,9 @@ Plugin E-ACSL 17.0 (Chlorine-20180501) -* E-ACSL [2017-11-27] Restore behavior of option -e-acsl-valid broken since Phosphorus (included). -#################################### +############################################################################### Plugin E-ACSL 16.0 (Sulfur-20171101) -#################################### +############################################################################### -* E-ACSL [2017-10-25] Fix bug #2303 about unnamed formals in annotated functions. @@ -331,9 +335,9 @@ Plugin E-ACSL 16.0 (Sulfur-20171101) e-acsl-gcc.sh allowing to change the default sizes of the respective shadow spaces. -######################################## +############################################################################### Plugin E-ACSL 15.0 (Phosphorus-20170501) -######################################## +############################################################################### - runtime [2017-03-29] The (much more efficient) shadow memory model is now used by default. @@ -359,9 +363,9 @@ Plugin E-ACSL 15.0 (Phosphorus-20170501) operations in a few cases: the generated code might have overflowed. -#################################### +############################################################################### Plugin E-ACSL 0.8 (Silicon-20161101) -#################################### +############################################################################### -* e-acsl-gcc [2016-11-07] Added --rte-select feature to e-acsl-gcc.sh. -* e-acsl-gcc [2016-08-02] Added --rt-debug feature to e-acsl-gcc.sh. @@ -397,9 +401,9 @@ Plugin E-ACSL 0.8 (Silicon-20161101) initialization of tracked memory blocks in the E-ACSL memory model library. -###################################### +############################################################################### Plugin E-ACSL 0.6 (Magnesium_20151002) -###################################### +############################################################################### -* e-acsl-gcc [2016-01-22] Add an e-acsl-gcc.sh option allowing to skip compilation of original sources. @@ -413,9 +417,9 @@ Plugin E-ACSL 0.6 (Magnesium_20151002) -* runtime [2015-11-06] Fix a crash occuring when using a recent libc while GMP headers provided by E-ACSL are used. -################################### +############################################################################### Plugin E-ACSL 0.5 (Sodium_20150201) -################################### +############################################################################### - E-ACSL [2015-06-01] Support of \freeable. Thus illegal calls to free (e.g. double free) are detected. @@ -431,9 +435,9 @@ o E-ACSL [2014-12-17] Export a minimal API for other plug-ins. -* E-ACSL [2014-10-27] Add a missing cast when translating an integral type used in a floating point/real context in an annotation. -################################### +############################################################################### Plugin E-ACSL 0.4.1 (Neon_20140301) -################################### +############################################################################### -* E-ACSL [2014-08-05] Fix bug #1838 about memset. -* E-ACSL [2014-08-05] Fix bug #1818 about initialization of globals. @@ -458,9 +462,9 @@ Plugin E-ACSL 0.4.1 (Neon_20140301) generates incorrect code. -* E-ACSL [2014-03-17] Fix bug #1700 about non-ISO empty struct. -################################# +############################################################################### Plugin E-ACSL 0.4 (Neon_20140301) -################################# +############################################################################### -* E-ACSL [2014-01-28] Fix bug #1634 occuring in presence of static addresses. @@ -468,9 +472,9 @@ Plugin E-ACSL 0.4 (Neon_20140301) of aliasing. -* E-ACSL [2013-09-25] Some loop invariants were tagged as "assertions". -##################################### +############################################################################### Plugin E-ACSL 0.3 (Fluorine_20130601) -##################################### +############################################################################### - E-ACSL [2013-09-18] More precise message for unsupported contract clauses. @@ -488,9 +492,9 @@ Plugin E-ACSL 0.3 (Fluorine_20130601) generated project. -* E-ACSL [2013-05-30] Fix -e-acsl-debug n, with n >= 2. -##################################### +############################################################################### Plugin E-ACSL 0.2 (Fluorine_20130401) -##################################### +############################################################################### - E-ACSL [2013-01-09] New option -e-acsl-valid. By default, valid annotation are not translated anymore. @@ -527,10 +531,10 @@ Plugin E-ACSL 0.2 (Fluorine_20130401) - E-ACSL [2012-01-20] Use GMP arithmetics only when required (i.e. mostly never in practice). -##################################### +############################################################################### Plugin E-ACSL 0.1 (Nitrogen_20111001) -##################################### +############################################################################### - E-ACSL [2012-01-06] First public release. -################################### +############################################################################### diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c index 75bafb53733678a481528b1b45fc83a1dbf9a974..05ad2ab4d9630b9fc40e315b154e7f330e769fae 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c +++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcat.c @@ -648,7 +648,7 @@ pid_t __gen_e_acsl_fork(void) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "fork"; - __gen_e_acsl_assert_data.line = 846; + __gen_e_acsl_assert_data.line = 853; __gen_e_acsl_assert_data.name = "result_ok_child_or_error"; __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c index fa8adbe47e652c0494feefb8b30464727abafc11..b8a1cf816d1ff12b4a9d05f038ce82a244df2b9e 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c +++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcmp.c @@ -213,7 +213,7 @@ pid_t __gen_e_acsl_fork(void) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "fork"; - __gen_e_acsl_assert_data.line = 846; + __gen_e_acsl_assert_data.line = 853; __gen_e_acsl_assert_data.name = "result_ok_child_or_error"; __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c index 4269e70a49c9e9183678c6bea3bfc8c98ce6cd4d..a82b19ca899af10ef56efa8cd421b733dc5a0352 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c +++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strcpy.c @@ -627,7 +627,7 @@ pid_t __gen_e_acsl_fork(void) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "fork"; - __gen_e_acsl_assert_data.line = 846; + __gen_e_acsl_assert_data.line = 853; __gen_e_acsl_assert_data.name = "result_ok_child_or_error"; __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); diff --git a/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c b/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c index b78f217fe8da244eedb82d0922e1e356a3d8086a..2fc62ec2c840513dda53a243873a8c22eccbcdcb 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c +++ b/src/plugins/e-acsl/tests/builtin/oracle/gen_strlen.c @@ -187,7 +187,7 @@ pid_t __gen_e_acsl_fork(void) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "fork"; - __gen_e_acsl_assert_data.line = 846; + __gen_e_acsl_assert_data.line = 853; __gen_e_acsl_assert_data.name = "result_ok_child_or_error"; __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle index 79b6833073302250ad8fe4a1057ac2df85d67e12..3d4daab9ad5c01bd59d126de081bce4a0d624ff8 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle +++ b/src/plugins/e-acsl/tests/builtin/oracle/strcat.res.oracle @@ -8,7 +8,7 @@ [e-acsl] Warning: annotating undefined function `fork': the generated program may miss memory instrumentation if there are memory-related annotations. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: @@ -25,9 +25,9 @@ is not yet supported. Ignoring annotation. [e-acsl] translation done in project "e-acsl". -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:846: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:853: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:847: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:854: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle index 23aaebecb39a3031654d59684ee79c701659ffab..f0f2dd6bac7d240b1951d30131abcc48f249fc1b 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle +++ b/src/plugins/e-acsl/tests/builtin/oracle/strcmp.res.oracle @@ -49,7 +49,7 @@ [e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle index 4d60df21bef6e71b55d35f9d70e3f0a80081b3b3..ef798a2e8602f3a65f86a373bfa895fbab1a7e81 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle +++ b/src/plugins/e-acsl/tests/builtin/oracle/strcpy.res.oracle @@ -44,7 +44,7 @@ [e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: diff --git a/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle b/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle index 08078ac2fc031bffaaa0258a46f0b6d74806cc7f..1d60323480135dccc0464552181b36d335b2ba1f 100644 --- a/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle +++ b/src/plugins/e-acsl/tests/builtin/oracle/strlen.res.oracle @@ -47,7 +47,7 @@ [e-acsl] FRAMAC_SHARE/libc/__fc_string_axiomatic.h:278: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c b/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c index ab5af04d3e66f2fa394eb2e386923b28d33192b0..fae60f07a4bcf944b858ecc1f37eab71b82be061 100644 --- a/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c +++ b/src/plugins/e-acsl/tests/concurrency/oracle/gen_parallel_threads.c @@ -750,7 +750,7 @@ int __gen_e_acsl_usleep(useconds_t usec) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "usleep"; - __gen_e_acsl_assert_data.line = 1145; + __gen_e_acsl_assert_data.line = 1152; __gen_e_acsl_assert_data.name = "result_ok_or_error"; __e_acsl_assert(__gen_e_acsl_or,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); @@ -1717,7 +1717,7 @@ void __e_acsl_globals_init(void) __e_acsl_full_init((void *)(& perror)); __e_acsl_store_block((void *)(& __fc_p_tmpnam),8UL); __e_acsl_full_init((void *)(& __fc_p_tmpnam)); - __e_acsl_store_block((void *)(__fc_tmpnam),2048UL); + __e_acsl_store_block((void *)(__fc_tmpnam),20UL); __e_acsl_full_init((void *)(& __fc_tmpnam)); __e_acsl_store_block((void *)(& __fc_p_fopen),8UL); __e_acsl_full_init((void *)(& __fc_p_fopen)); diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c index 77907fea3c8271b68ac82049c7141bb1bdc41627..c1b193f256bdb4dfd424e2e088cc6a97a9929acf 100644 --- a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c +++ b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_debug.c @@ -432,7 +432,7 @@ int __gen_e_acsl_usleep(useconds_t usec) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "usleep"; - __gen_e_acsl_assert_data.line = 1145; + __gen_e_acsl_assert_data.line = 1152; __gen_e_acsl_assert_data.name = "result_ok_or_error"; __e_acsl_assert(__gen_e_acsl_or,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); @@ -1399,7 +1399,7 @@ void __e_acsl_globals_init(void) __e_acsl_full_init((void *)(& perror)); __e_acsl_store_block((void *)(& __fc_p_tmpnam),8UL); __e_acsl_full_init((void *)(& __fc_p_tmpnam)); - __e_acsl_store_block((void *)(__fc_tmpnam),2048UL); + __e_acsl_store_block((void *)(__fc_tmpnam),20UL); __e_acsl_full_init((void *)(& __fc_tmpnam)); __e_acsl_store_block((void *)(& __fc_p_fopen),8UL); __e_acsl_full_init((void *)(& __fc_p_fopen)); diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c index 5228bebf9ee603886848d3b89dbabe3cd84cc4f5..3113cefa8b2f90ffb5b527648584b9295619fe39 100644 --- a/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c +++ b/src/plugins/e-acsl/tests/concurrency/oracle/gen_threads_safe_locations.c @@ -492,7 +492,7 @@ void __e_acsl_globals_init(void) __e_acsl_full_init((void *)(& thread_start)); __e_acsl_store_block((void *)(& __fc_p_tmpnam),8UL); __e_acsl_full_init((void *)(& __fc_p_tmpnam)); - __e_acsl_store_block((void *)(__fc_tmpnam),2048UL); + __e_acsl_store_block((void *)(__fc_tmpnam),20UL); __e_acsl_full_init((void *)(& __fc_tmpnam)); __e_acsl_store_block((void *)(& __fc_p_fopen),8UL); __e_acsl_full_init((void *)(& __fc_p_fopen)); diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle b/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle index 2c771c66bd1bdcf46f73936f65aea84f732108ff..26bee74a6dea8e54ad16b3b067774451af038ea4 100644 --- a/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle +++ b/src/plugins/e-acsl/tests/concurrency/oracle/parallel_threads.res.oracle @@ -35,7 +35,7 @@ [e-acsl] Warning: annotating undefined function `usleep': the generated program may miss memory instrumentation if there are memory-related annotations. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:1142: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:1149: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/stdlib.h:505: Warning: @@ -169,6 +169,6 @@ [eva:alarm] FRAMAC_SHARE/libc/pthread.h:316: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1145: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1152: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. diff --git a/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle b/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle index 2c771c66bd1bdcf46f73936f65aea84f732108ff..26bee74a6dea8e54ad16b3b067774451af038ea4 100644 --- a/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle +++ b/src/plugins/e-acsl/tests/concurrency/oracle/threads_debug.res.oracle @@ -35,7 +35,7 @@ [e-acsl] Warning: annotating undefined function `usleep': the generated program may miss memory instrumentation if there are memory-related annotations. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:1142: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:1149: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/stdlib.h:505: Warning: @@ -169,6 +169,6 @@ [eva:alarm] FRAMAC_SHARE/libc/pthread.h:316: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1145: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:1152: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. diff --git a/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c b/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c index 4204fcd3ed9ba4bacc3a12bcddb6007ff628a85e..b189489a114c9c540fb33df1cc23919b2f7c0454 100644 --- a/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c +++ b/src/plugins/e-acsl/tests/constructs/oracle/gen_printed_data.c @@ -21,16 +21,16 @@ enum EBool { EBOOL_MAX = (_Bool)1 }; enum EChar { - ECHAR_MIN = (char)(-128), + ECHAR_MIN = (char)(-127 - 1), ECHAR_MAX = (char)127 }; enum ESChar { - ESCHAR_MIN = (signed char)(-128), + ESCHAR_MIN = (signed char)(-127 - 1), ESCHAR_MAX = (signed char)127 }; enum EUChar { EUCHAR_MIN = (unsigned char)0, - EUCHAR_MAX = (unsigned char)255 + EUCHAR_MAX = (unsigned char)255U }; enum EInt { EINT_MIN = -2147483647 - 1, @@ -41,12 +41,12 @@ enum EUInt { EUINT_MAX = 4294967295U }; enum EShort { - ESHORT_MIN = (short)(-32768), + ESHORT_MIN = (short)(-32767 - 1), ESHORT_MAX = (short)32767 }; enum EUShort { EUSHORT_MIN = (unsigned short)0, - EUSHORT_MAX = (unsigned short)65535 + EUSHORT_MAX = (unsigned short)65535U }; enum ELong { ELONG_MIN = -9223372036854775807L - 1L, @@ -164,7 +164,7 @@ int main(void) __e_acsl_assert_clean(& __gen_e_acsl_assert_data_3); } /*@ assert \let x = int_schar; \true; */ ; - unsigned char int_uchar = (unsigned char)255; + unsigned char int_uchar = (unsigned char)255U; __e_acsl_store_block((void *)(& int_uchar),1UL); __e_acsl_full_init((void *)(& int_uchar)); { @@ -244,7 +244,7 @@ int main(void) __e_acsl_assert_clean(& __gen_e_acsl_assert_data_7); } /*@ assert \let x = int_short; \true; */ ; - unsigned short int_ushort = (unsigned short)65535; + unsigned short int_ushort = (unsigned short)65535U; __e_acsl_store_block((void *)(& int_ushort),2UL); __e_acsl_full_init((void *)(& int_ushort)); { @@ -423,8 +423,7 @@ int main(void) } /*@ assert \let x = real_double; \true; */ ; /*@ assert - Eva: is_nan_or_infinite: - \is_finite((long double)0x1.fffffffffffffffep+16383L); + Eva: is_nan_or_infinite: \is_finite(0x1.fffffffffffffffep+16383L); */ long double real_ldouble = 0x1.fffffffffffffffep+16383L; __e_acsl_store_block((void *)(& real_ldouble),16UL); diff --git a/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle b/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle index 2bc5c16105b06b1f77eafeb26a46b63d4e260432..f9589246d101d590ef5796c6a6b6ca0e6620532d 100644 --- a/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle +++ b/src/plugins/e-acsl/tests/constructs/oracle/printed_data.res.oracle @@ -21,7 +21,7 @@ cannot parse floating-point constant, returning imprecise result [eva:alarm] printed_data.c:101: Warning: non-finite long double value. - assert \is_finite((long double)0x1.fffffffffffffffep+16383L); + assert \is_finite(0x1.fffffffffffffffep+16383L); [eva:alarm] printed_data.c:102: Warning: non-finite long double value. assert \is_finite(real_ldouble); [eva:alarm] printed_data.c:102: Warning: diff --git a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle index 658935448b79860faf628778090446a16a2f2b6e..618817f8cf34a55412723b544aee62e28e882b65 100644 --- a/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle +++ b/src/plugins/e-acsl/tests/format/oracle/fprintf.res.oracle @@ -14,7 +14,7 @@ [e-acsl] Warning: annotating undefined function `fork': the generated program may miss memory instrumentation if there are memory-related annotations. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: @@ -42,10 +42,10 @@ is not yet supported. Ignoring annotation. [e-acsl] translation done in project "e-acsl". -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:846: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:853: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:847: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:854: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. [kernel:annot:missing-spec] fprintf.c:22: Warning: diff --git a/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c b/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c index 437ed75a82541931cfc0f3a34996233d94d3bdf3..bb0d77edd343e52a469b3adcad7fc8a484a33197 100644 --- a/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c +++ b/src/plugins/e-acsl/tests/format/oracle/gen_fprintf.c @@ -126,7 +126,7 @@ pid_t __gen_e_acsl_fork(void) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "fork"; - __gen_e_acsl_assert_data.line = 846; + __gen_e_acsl_assert_data.line = 853; __gen_e_acsl_assert_data.name = "result_ok_child_or_error"; __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); diff --git a/src/plugins/e-acsl/tests/format/oracle/gen_printf.c b/src/plugins/e-acsl/tests/format/oracle/gen_printf.c index 7526a0f39b5452827752d424283bb425a0e4179c..0dd82c4b10993096f678d8ba7c2d3fe5fee2e9d0 100644 --- a/src/plugins/e-acsl/tests/format/oracle/gen_printf.c +++ b/src/plugins/e-acsl/tests/format/oracle/gen_printf.c @@ -1019,7 +1019,7 @@ pid_t __gen_e_acsl_fork(void) __gen_e_acsl_assert_data.pred_txt = "\\result == 0 || \\result > 0 || \\result == -1"; __gen_e_acsl_assert_data.file = "FRAMAC_SHARE/libc/unistd.h"; __gen_e_acsl_assert_data.fct = "fork"; - __gen_e_acsl_assert_data.line = 846; + __gen_e_acsl_assert_data.line = 853; __gen_e_acsl_assert_data.name = "result_ok_child_or_error"; __e_acsl_assert(__gen_e_acsl_or_2,& __gen_e_acsl_assert_data); __e_acsl_assert_clean(& __gen_e_acsl_assert_data); diff --git a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle index 1eaec8a8f39741aa8937f21524340247e6280696..02fda025503b0601a9443c74d7d377448cb04c66 100644 --- a/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle +++ b/src/plugins/e-acsl/tests/format/oracle/printf.res.oracle @@ -81,7 +81,7 @@ E-ACSL construct `logic functions or predicates performing read accesses' is not yet supported. Ignoring annotation. -[e-acsl] FRAMAC_SHARE/libc/unistd.h:843: Warning: +[e-acsl] FRAMAC_SHARE/libc/unistd.h:850: Warning: E-ACSL construct `assigns clause in behavior' is not yet supported. Ignoring annotation. [e-acsl] FRAMAC_SHARE/libc/sys/wait.h:82: Warning: @@ -105,10 +105,10 @@ is not yet supported. Ignoring annotation. [e-acsl] translation done in project "e-acsl". -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:846: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:853: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. -[eva:alarm] FRAMAC_SHARE/libc/unistd.h:847: Warning: +[eva:alarm] FRAMAC_SHARE/libc/unistd.h:854: Warning: function __e_acsl_assert_register_int: precondition data->values == \null || \valid(data->values) got status unknown. [kernel:annot:missing-spec] printf.c:190: Warning: diff --git a/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c b/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c index 8810b1add07155c58bb699ce351a65cbd6c8928c..354f67ce51f263016bbd315a37cb77ec93aab093 100644 --- a/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c +++ b/src/plugins/e-acsl/tests/temporal/oracle/gen_t_fun_lib.c @@ -31,7 +31,7 @@ int main(void) char *c = (char *)__gen_e_acsl_literal_string; __e_acsl_temporal_reset_parameters(); __e_acsl_temporal_reset_return(); - char *p = malloc((size_t)256); + char *p = malloc((size_t)4096); __e_acsl_temporal_store_nblock((void *)(& p),(void *)*(& p)); __e_acsl_store_block((void *)(& p),8UL); __e_acsl_full_init((void *)(& p)); @@ -42,7 +42,7 @@ int main(void) __e_acsl_full_init((void *)(& q)); __e_acsl_temporal_reset_parameters(); __e_acsl_temporal_reset_return(); - q = (char *)malloc((size_t)256); + q = (char *)malloc((size_t)4096); __e_acsl_temporal_store_nblock((void *)(& q),(void *)*(& q)); { int __gen_e_acsl_initialized; diff --git a/src/plugins/e-acsl/tests/test_config_dev b/src/plugins/e-acsl/tests/test_config_dev index e98e5eb62f93de601cb5e0f75f480a7b5df64a4f..ee637413caa074f7a35b7f7d482396ca83d8158f 100644 --- a/src/plugins/e-acsl/tests/test_config_dev +++ b/src/plugins/e-acsl/tests/test_config_dev @@ -7,6 +7,9 @@ MACRO: ROOT_EACSL_GCC_MISC_OPTS -q -X --no-assert-print-data COMMENT: Default options for the frama-c invocation MACRO: ROOT_EACSL_GCC_FC_EXTRA -verbose 0 +COMMENT: Currently compilation assumes an x86_64 architecture +ENABLED_IF: (= %{architecture} x86_64) + PLUGIN: e-acsl eva,scope,variadic rtegen COMMENT: The dependency to the plugin share directory has not to be explicited diff --git a/src/plugins/eva/api/general_requests.ml b/src/plugins/eva/api/general_requests.ml index 3c75a9020251e3775500b6531321d49bcabcdb8f..d3085ad822cb528b62bcffc5a61cea4ea055f09c 100644 --- a/src/plugins/eva/api/general_requests.ml +++ b/src/plugins/eva/api/general_requests.ml @@ -39,7 +39,8 @@ module ComputationState = struct Package.(Junion [ Jtag "not_computed" ; Jtag "computing" ; - Jtag "computed"]) + Jtag "computed" ; + Jtag "aborted" ]) let to_json = function | Analysis.NotComputed -> `String "not_computed" | Computing -> `String "computing" @@ -47,7 +48,7 @@ module ComputationState = struct | Aborted -> `String "aborted" end -let _computation_signal = +let computation_signal = States.register_value ~package ~name:"computationState" ~descr:(Markdown.plain "The current computation state of the analysis.") @@ -84,8 +85,31 @@ let () = Request.register ~package ~kind:`GET ~name:"getCallers" ~descr:(Markdown.plain "Get the list of call site of a function") ~input:(module Kernel_ast.Function) ~output:(module Data.Jlist (CallSite)) + ~signals:[computation_signal] callers +let eval_callee stmt lval = + let expr = Eva_utils.lval_to_exp lval in + Results.(before stmt |> eval_callee expr |> default []) + +let callees = function + | Printer_tag.PLval (_kf, Kstmt stmt, (Mem _, NoOffset as lval)) + when Cil.(isFunctionType (typeOfLval lval)) -> + eval_callee stmt lval + | Printer_tag.PLval (_kf, Kstmt stmt, lval) + when Cil.(isFunPtrType (Cil.typeOfLval lval)) -> + eval_callee stmt (Mem (Eva_utils.lval_to_exp lval), NoOffset) + | _ -> [] + +let () = Request.register ~package + ~kind:`GET ~name:"getCallees" + ~descr:(Markdown.plain + "Return the functions pointed to by a function pointer") + ~input:(module Kernel_ast.Marker) + ~output:(module Data.Jlist (Kernel_ast.Function)) + ~signals:[computation_signal] + callees + (* ----- Functions ---------------------------------------------------------- *) module Functions = @@ -177,37 +201,95 @@ let () = Request.register ~package statements in a function") ~input:(module Kernel_ast.Function) ~output:(module DeadCode) + ~signals:[computation_signal] dead_code (* ----- Register Eva values information ------------------------------------ *) -let term_lval_to_lval tlval = - try Logic_to_c.term_lval_to_lval tlval +type evaluation_point = + | Initial + | Pre of kernel_function + | Stmt of kernel_function * stmt + +let post kf = + if Analysis.use_spec_instead_of_definition kf + then raise Not_found + else + try Stmt (kf, Kernel_function.find_return kf) + with Kernel_function.No_Statement -> raise Not_found + +let request_at = function + | Initial -> Results.at_start + | Stmt (_, stmt) -> Results.before stmt + | Pre kf -> Results.at_start_of kf + +let property_evaluation_point = function + | Property.IPCodeAnnot { ica_kf = kf; ica_stmt = stmt } + | IPPropertyInstance { ii_kf = kf; ii_stmt = stmt } -> Stmt (kf, stmt) + | IPPredicate {ip_kf; ip_kind = PKEnsures (_, Normal)} -> post ip_kf + | IPPredicate { ip_kf = kf; + ip_kind = PKRequires _ | PKAssumes _ | PKTerminates } + | IPAssigns {ias_kf = kf} | IPFrom {if_kf = kf} -> + Pre kf + | IPPredicate _ | IPComplete _ | IPDisjoint _ | IPDecrease _ + | IPAxiomatic _ | IPLemma _ | IPTypeInvariant _ | IPGlobalInvariant _ + | IPOther _ | IPAllocation _ | IPReachable _ | IPExtended _ | IPBehavior _ -> + raise Not_found + +let marker_evaluation_point = function + | Printer_tag.PGlobal _ -> Initial + | PStmt (kf, stmt) | PStmtStart (kf, stmt) -> Stmt (kf, stmt) + | PVDecl (kf, kinstr, v) when not (v.vformal || v.vglob) -> + begin + (* Only evaluate declaration of local variable if it is initialized. *) + match kf, kinstr with + | Some kf, Kstmt ({skind = Instr (Local_init _)} as s) -> Stmt (kf, s) + | _ -> raise Not_found + end + | PLval (kf, ki, _) | PExp (kf, ki, _) | PVDecl (kf, ki, _) -> + begin + match kf, ki with + | Some kf, Kstmt stmt -> Stmt (kf, stmt) + | Some kf, Kglobal -> Pre kf + | None, Kglobal -> Initial + | None, Kstmt _ -> assert false + end + | PTermLval (_, _, prop, _) | PIP prop -> property_evaluation_point prop + | PType _ -> raise Not_found + +let term_lval_to_lval kf tlval = + try + let result = Option.bind kf Eva_utils.find_return_var in + Logic_to_c.term_lval_to_lval ?result tlval with Logic_to_c.No_conversion -> raise Not_found let print_value fmt loc = let is_scalar = Cil.isScalarType in - let kinstr, eval = + let evaluation_point = marker_evaluation_point loc in + let request = request_at evaluation_point in + let eval = match loc with - | Printer_tag.PLval (_kf, ki, lval) when is_scalar (Cil.typeOfLval lval) -> - ki, Results.eval_lval lval - | Printer_tag.PExp (_kf, ki, expr) when is_scalar (Cil.typeOf expr) -> - ki, Results.eval_exp expr - | PVDecl (_kf, ki, vi) when is_scalar vi.vtype -> - ki, Results.eval_var vi - | PTermLval (_kf, ki, _ip, tlval) -> - let lval = term_lval_to_lval tlval in - ki, Results.eval_lval lval + | Printer_tag.PLval (_, _, lval) when is_scalar (Cil.typeOfLval lval) -> + Results.eval_lval lval + | Printer_tag.PExp (_, _, expr) when is_scalar (Cil.typeOf expr) -> + Results.eval_exp expr + | PVDecl (_, _, vi) when is_scalar vi.vtype -> + Results.eval_var vi + | PTermLval (kf, _, _ip, tlval) -> + let lval = term_lval_to_lval kf tlval in + if is_scalar (Cil.typeOfLval lval) + then Results.eval_lval lval + else raise Not_found | _ -> raise Not_found in let pretty = Cvalue.V_Or_Uninitialized.pretty in let eval_cvalue at = Results.(eval at |> as_cvalue_or_uninitialized) in - let before = eval_cvalue (Results.before_kinstr kinstr) in - match kinstr with - | Kglobal -> pretty fmt before - | Kstmt stmt -> + let before = eval_cvalue request in + match evaluation_point with + | Initial | Pre _ -> pretty fmt before + | Stmt (_, stmt) -> let after = eval_cvalue (Results.after stmt) in if Cvalue.V_Or_Uninitialized.equal before after then pretty fmt before @@ -241,8 +323,8 @@ module EvaTaints = struct | PLval (_, Kstmt stmt, lval) -> Some (expr_of_lval lval, stmt) | PExp (_, Kstmt stmt, expr) -> Some (expr, stmt) | PVDecl (_, Kstmt stmt, vi) -> Some (expr_of_lval (Var vi, NoOffset), stmt) - | PTermLval (_, Kstmt stmt, _, tlval) -> - Some (term_lval_to_lval tlval |> expr_of_lval, stmt) + | PTermLval (kf, Kstmt stmt, _, tlval) -> + Some (term_lval_to_lval kf tlval |> expr_of_lval, stmt) | _ -> None let of_marker marker = @@ -394,6 +476,7 @@ module LvalueTaints = struct ~descr:(Markdown.plain "Get the tainted lvalues of a given function") ~input:(module (Kernel_ast.Fundec)) ~output:(module (Data.Jlist (Status))) + ~signals:[computation_signal] get_tainted_lvals end @@ -749,4 +832,7 @@ let () = Request.register ~package ~input:(module Data.Jpair (Kernel_ast.Marker) (Data.Jbool)) ~output:(module Data.Jlist (Data.Jtriple (Data.Jstring) (Data.Jstring) (Data.Jstring))) + ~signals:[computation_signal] get_states + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/eva/api/general_requests.mli b/src/plugins/eva/api/general_requests.mli index 6472763b7e5187d8703feffb06c7581d7b81282f..7e98550daa190962d7250a23df777bc81c9d9d7a 100644 --- a/src/plugins/eva/api/general_requests.mli +++ b/src/plugins/eva/api/general_requests.mli @@ -21,3 +21,18 @@ (**************************************************************************) (** General Eva requests registered in the server. *) + +open Cil_types + +type evaluation_point = + | Initial + | Pre of kernel_function + | Stmt of kernel_function * stmt + +(* Returns the evaluation point of a marker. + @raise Not_found if the marker cannot be evaluated. *) +val marker_evaluation_point: Printer_tag.localizable -> evaluation_point + +(* Converts an ACSL lval into a C lval. + @raise Not_found if the conversion fails. *) +val term_lval_to_lval: kernel_function option -> term_lval -> lval diff --git a/src/plugins/eva/api/values_request.ml b/src/plugins/eva/api/values_request.ml index c672982553d0d692ed28822bfcb09146bd3d04bc..1e109a39629a2e95115db3b403be1112542972ba 100644 --- a/src/plugins/eva/api/values_request.ml +++ b/src/plugins/eva/api/values_request.ml @@ -42,9 +42,12 @@ let package = ~title:"Eva Values" () -type probe = - | Pexpr of exp * stmt - | Plval of lval * stmt +type term = Pexpr of exp | Plval of lval | Ppred of predicate +type evaluation_point = General_requests.evaluation_point = + Initial | Pre of kernel_function | Stmt of kernel_function * stmt + +(* A term and the program point where it should be evaluated. *) +type probe = term * evaluation_point type callstack = Value_types.callstack type truth = Abstract_interp.truth @@ -81,32 +84,53 @@ let () = Analysis.register_computation_hook ~on:Computed (* --- Marker Utilities --- *) (* -------------------------------------------------------------------------- *) -let next_steps s = - match s.skind with - | If (cond, _, _, _) -> [ `Then cond ; `Else cond ] - | Instr (Set _ | Call _ | Local_init _) -> [ `After ] - | Instr (Asm _ | Code_annot _) - | Switch _ | Loop _ | Block _ | UnspecifiedSequence _ - | TryCatch _ | TryFinally _ | TryExcept _ - | Instr (Skip _) | Return _ | Break _ | Continue _ | Goto _ | Throw _ -> [] - -let probe_stmt s = - match s.skind with - | Instr (Set(lv,_,_)) -> Some (Plval (lv,s)) - | Instr (Call(Some lr,_,_,_)) -> Some (Plval (lr,s)) - | Instr (Local_init(v,_,_)) -> Some (Plval ((Var v,NoOffset), s)) - | Return (Some e,_) | If(e,_,_,_) | Switch(e,_,_,_) -> Some (Pexpr (e,s)) - | _ -> None +let next_steps = function + | Initial | Pre _ -> [] + | Stmt (_, stmt) -> + match stmt.skind with + | If (cond, _, _, _) -> [ `Then cond ; `Else cond ] + | Instr (Set _ | Call _ | Local_init _) -> [ `After ] + | Instr (Asm _ | Code_annot _) + | Switch _ | Loop _ | Block _ | UnspecifiedSequence _ + | TryCatch _ | TryFinally _ | TryExcept _ + | Instr (Skip _) | Return _ | Break _ | Continue _ | Goto _ | Throw _ -> [] + +let probe_stmt stmt = + match stmt.skind with + | Instr (Set (lv, _, _)) + | Instr (Call (Some lv, _, _, _)) -> Plval lv + | Instr (Local_init (v, _, _)) -> Plval (Var v, NoOffset) + | Return (Some e, _) | If (e, _, _, _) | Switch (e, _, _, _) -> Pexpr e + | _ -> raise Not_found + +let probe_code_annot = function + | AAssert (_, p) | AInvariant (_, true, p) -> Ppred p.tp_statement + | _ -> raise Not_found + +let probe_property = function + | Property.IPCodeAnnot ica -> probe_code_annot ica.ica_ca.annot_content + | IPPropertyInstance { ii_pred = Some pred } + | IPPredicate {ip_pred = pred} -> + Ppred (Logic_const.pred_of_id_pred pred) + | _ -> raise Not_found + +let probe_marker = function + | Printer_tag.PLval (_, _, lval) + when Cil.(isFunctionType (typeOfLval lval)) -> raise Not_found + | PVDecl (_, _, vi) when Cil.isFunctionType vi.vtype -> raise Not_found + | PLval (_, _, l) -> Plval l + | PExp (_, _, e) -> Pexpr e + | PStmt (_, s) | PStmtStart (_, s) -> probe_stmt s + | PVDecl (_, _, v) -> Plval (Var v, NoOffset) + | PTermLval (kf, _, _, tlval) -> + Plval (General_requests.term_lval_to_lval kf tlval) + | PIP property -> probe_property property + | _ -> raise Not_found let probe marker = - let open Printer_tag in - match marker with - | PLval (_, _, (Var vi, NoOffset)) when Cil.isFunctionType vi.vtype -> None - | PLval(_,Kstmt s,l) -> Some (Plval (l,s)) - | PExp(_,Kstmt s,e) -> Some (Pexpr (e,s)) - | PStmt(_,s) | PStmtStart(_,s) -> probe_stmt s - | PVDecl(_,Kstmt s,v) -> Some (Plval ((Var v,NoOffset),s)) - | _ -> None + try Some (probe_marker marker, + General_requests.marker_evaluation_point marker) + with Not_found -> None (* -------------------------------------------------------------------------- *) (* --- Stmt Ranking --- *) @@ -329,7 +353,8 @@ let filter_variables bases = (* -------------------------------------------------------------------------- *) module type EvaProxy = sig - val callstacks : stmt -> callstack list + val kf_callstacks : kernel_function -> callstack list + val stmt_callstacks : stmt -> callstack list val evaluate : probe -> callstack option -> evaluations end @@ -346,58 +371,77 @@ module Proxy(A : Analysis.S) : EvaProxy = struct let default = fun _ -> Cvalue.V.top in Option.value ~default (A.Val.get Main_values.CVal.key) - let callstacks stmt = - match A.get_stmt_state_by_callstack ~after:false stmt with + let callstacks get_state_by_callstack elt = + match get_state_by_callstack elt with | `Top | `Bottom -> [] - | `Value states -> CSmap.fold_sorted (fun cs _ wcs -> cs :: wcs) states [] + | `Value states -> CSmap.fold (fun cs _ acc -> cs :: acc) states [] + + let kf_callstacks = callstacks A.get_initial_state_by_callstack + let stmt_callstacks = callstacks (A.get_stmt_state_by_callstack ~after:false) - let dstate ~after stmt = function - | None -> (A.get_stmt_state ~after stmt :> dstate) + let get_state get_consolidated get_by_callstack arg = function + | None -> get_consolidated arg | Some cs -> - match A.get_stmt_state_by_callstack ~selection:[cs] ~after stmt with + match get_by_callstack ?selection:(Some [cs]) arg with | (`Top | `Bottom) as res -> res | `Value cmap -> try `Value (CSmap.find cmap cs) with Not_found -> `Bottom + let get_stmt_state ~after = + get_state (A.get_stmt_state ~after) (A.get_stmt_state_by_callstack ~after) + + let get_initial_state = + get_state A.get_initial_state A.get_initial_state_by_callstack + + let domain_state callstack = function + | Initial -> A.get_global_state () + | Pre kf -> get_initial_state kf callstack + | Stmt (_, stmt) -> get_stmt_state ~after:false stmt callstack + (* --- Converts an evaluation [result] into an exported [value]. ---------- *) (* Result of an evaluation: a generic value for scalar types, or an offsetmap for struct and arrays. *) type result = - | Value of A.Val.t + | Value of A.Val.t Eval.flagged_value | Offsetmap of offsetmap + | Status of truth let pp_result typ fmt = function - | Value v -> A.Val.pretty fmt v + | Value v -> (Eval.Flagged_Value.pretty (A.Val.pretty_typ (Some typ))) fmt v | Offsetmap offsm -> pp_offsetmap typ fmt offsm + | Status truth -> Alarmset.Status.pretty fmt truth let get_pointed_bases = function - | Value v -> get_bases (get_cvalue v) + | Value v -> get_bases (Bottom.fold ~bottom:Cvalue.V.bottom get_cvalue v.v) | Offsetmap offsm -> get_pointed_bases offsm + | Status _ -> Base.Hptset.empty - let get_pointed_markers stmt result = + let get_pointed_markers eval_point result = let bases = get_pointed_bases result in let vars = filter_variables bases in - let kf = - try Some (Kernel_function.find_englobing_kf stmt) - with Not_found -> None + let kf, kinstr = + match eval_point with + | Initial -> None, Kglobal + | Pre kf -> Some kf, Kglobal + | Stmt (kf, stmt) -> Some kf, Kstmt stmt in let to_marker vi = let text = Pretty_utils.to_string Printer.pp_varinfo vi in - let marker = Printer_tag.PLval (kf, Kstmt stmt, Cil.var vi) in + let marker = Printer_tag.PLval (kf, kinstr, Cil.var vi) in text, marker in List.map to_marker vars (* Creates an exported [value] from an evaluation result. *) - let make_value typ stmt (result, alarms) = + let make_value typ eval_point (result, alarms) = let descr = Format.asprintf "@[<hov 2>%a@]" Alarms.pretty in let f alarm status acc = (status, descr alarm) :: acc in let alarms = Alarmset.fold f [] alarms |> List.rev in let pretty_eval = Bottom.pretty (pp_result typ) in let value = Pretty_utils.to_string pretty_eval result in - let pointed_markers = get_pointed_markers stmt in + let pointed_markers = get_pointed_markers eval_point in let pointed_vars = Bottom.fold ~bottom:[] pointed_markers result in { value; alarms; pointed_vars } @@ -417,13 +461,25 @@ module Proxy(A : Analysis.S) : EvaProxy = struct let eval_lval lval state = match Cil.(unrollType (typeOfLval lval)) with | TInt _ | TEnum _ | TPtr _ | TFloat _ -> - A.copy_lvalue state lval >>=. fun value -> - value.v >>-: fun v -> Value v + A.copy_lvalue state lval >>=: fun value -> Value value | _ -> lval_to_offsetmap lval state >>=: fun offsm -> Offsetmap offsm let eval_expr expr state = - A.eval_expr state expr >>=: fun value -> Value value + A.eval_expr state expr >>=: fun value -> + Value { v = `Value value; initialized = true; escaping = false } + + let eval_pred eval_point predicate state = + let result = + match eval_point with + | Initial | Pre _ -> None + | Stmt (kf, _) -> Eva_utils.find_return_var kf + in + let env = + Abstract_domain.{ states = (function _ -> A.Dom.top) ; result } + in + let truth = A.Dom.evaluate_predicate env state predicate in + `Value (Status truth), Alarmset.none (* --- Evaluates all steps (before/after the statement). ------------------ *) @@ -434,32 +490,34 @@ module Proxy(A : Analysis.S) : EvaProxy = struct let else_state = (A.assume_cond stmt state cond false :> dstate) in Cond (eval then_state, eval else_state) | Instr (Set _ | Call _ | Local_init _) -> - let after_state = dstate ~after:true stmt callstack in + let after_state = get_stmt_state ~after:true stmt callstack in After (eval after_state) | _ -> Nothing - let eval_steps typ eval stmt callstack = + let eval_steps typ eval eval_point callstack = let default value = { value; alarms = []; pointed_vars = []; } in let eval = function | `Bottom -> default "Unreachable" | `Top -> default "No information" - | `Value state -> make_value typ stmt (eval state) + | `Value state -> make_value typ eval_point (eval state) in - let before = dstate ~after:false stmt callstack in + let before = domain_state callstack eval_point in let here = eval before in let next = - match before with - | `Bottom | `Top -> Nothing - | `Value state -> do_next eval state stmt callstack + match before, eval_point with + | `Value state, Stmt (_, stmt) -> do_next eval state stmt callstack + | _ -> Nothing in { here; next; } - let evaluate p callstack = - match p with - | Plval (lval, stmt) -> - eval_steps (Cil.typeOfLval lval) (eval_lval lval) stmt callstack - | Pexpr (expr, stmt) -> - eval_steps (Cil.typeOf expr) (eval_expr expr) stmt callstack + let evaluate (term, eval_point) callstack = + match term with + | Plval lval -> + eval_steps (Cil.typeOfLval lval) (eval_lval lval) eval_point callstack + | Pexpr expr -> + eval_steps (Cil.typeOf expr) (eval_expr expr) eval_point callstack + | Ppred pred -> + eval_steps Cil.intType (eval_pred eval_point pred) eval_point callstack end let proxy = @@ -481,11 +539,14 @@ let () = ~output:(module Jlist(Jcallstack)) begin fun markers -> let module A : EvaProxy = (val proxy ()) in - let add stmt = List.fold_right CSet.add (A.callstacks stmt) in let gather_callstacks cset marker = - match probe marker with - | Some (Pexpr (_, stmt) | Plval (_, stmt)) -> add stmt cset - | None -> cset + let list = + match probe marker with + | Some (_, Stmt (_, stmt)) -> A.stmt_callstacks stmt + | Some (_, Pre kf) -> A.kf_callstacks kf + | Some (_, Initial) | None -> [] + in + List.fold_left (fun set elt -> CSet.add elt set) cset list in let cset = List.fold_left gather_callstacks CSet.empty markers in Ranking.sort (CSet.elements cset) @@ -528,6 +589,11 @@ let () = (* --- Request getProbeInfo --- *) (* -------------------------------------------------------------------------- *) +let is_reachable = function + | Stmt (_, stmt) -> Results.is_reachable stmt + | Pre kf -> Results.is_called kf + | Initial -> Results.is_reachable_kinstr Kglobal + let () = let getProbeInfo = Request.signature ~input:(module Jmarker) () in let set_evaluable = Request.result getProbeInfo @@ -539,9 +605,6 @@ let () = and set_stmt = Request.result_opt getProbeInfo ~name:"stmt" ~descr:(Md.plain "Probe statement") (module Jstmt) - and set_rank = Request.result getProbeInfo - ~name:"rank" ~descr:(Md.plain "Probe statement rank") - ~default:0 (module Jint) and set_effects = Request.result getProbeInfo ~name:"effects" ~descr:(Md.plain "Effectfull statement") ~default:false (module Jbool) @@ -549,27 +612,30 @@ let () = ~name:"condition" ~descr:(Md.plain "Conditional statement") ~default:false (module Jbool) in - let set_probe rq pp p s = + let set_probe rq pp p eval_point = let computed = Analysis.is_computed () in - let reachable = Results.is_reachable s in + let reachable = is_reachable eval_point in set_evaluable rq (computed && reachable); - set_code rq (Some (Pretty_utils.to_string pp p)) ; - set_stmt rq (Some s) ; - set_rank rq (Ranking.stmt s) ; + set_code rq (Some (Pretty_utils.to_string pp p)); + set_stmt rq (match eval_point with Stmt (_, s) -> Some s | _ -> None); let on_steps = function | `Here -> () | `Then _ | `Else _ -> set_condition rq true | `After -> set_effects rq true - in List.iter on_steps (next_steps s) + in + List.iter on_steps (next_steps eval_point) in Request.register_sig ~package getProbeInfo ~kind:`GET ~name:"getProbeInfo" ~descr:(Md.plain "Probe informations") begin fun rq marker -> match probe marker with - | Some (Plval (l, s)) -> set_probe rq Printer.pp_lval l s - | Some (Pexpr (e, s)) -> set_probe rq Printer.pp_exp e s | None -> set_evaluable rq false + | Some (term, eval_point) -> + match term with + | Plval l -> set_probe rq Printer.pp_lval l eval_point + | Pexpr e -> set_probe rq Printer.pp_exp e eval_point + | Ppred p -> set_probe rq Printer.pp_predicate p eval_point end (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/eva/domains/cvalue/builtins.ml b/src/plugins/eva/domains/cvalue/builtins.ml index 2f497c83aec2232083a53a68a6bc222679f164e7..feb925ad393094dc7e98d1d4112efe7de8af2af3 100644 --- a/src/plugins/eva/domains/cvalue/builtins.ml +++ b/src/plugins/eva/domains/cvalue/builtins.ml @@ -165,9 +165,10 @@ let prepare_builtin kf (name, builtin, cacheable, expected_typ) = Self.warning ~source ~once:true ~wkey:Self.wkey_builtins_override "The builtin %s will not be used for function %a of incompatible type.@ \ - (got: %a)." + (got: %a. Machdep is %s)." name Kernel_function.pretty kf Printer.pp_typ (Kernel_function.get_type kf) + Cil.theMachine.theMachine.machdep_name else match find_builtin_specification kf with | None -> diff --git a/src/plugins/eva/domains/hcexprs.ml b/src/plugins/eva/domains/hcexprs.ml index 170011b36caf1961bba12169a7ed64e705736cb8..c9a1d48b3bff48020d873f1a3880afec570b8506 100644 --- a/src/plugins/eva/domains/hcexprs.ml +++ b/src/plugins/eva/domains/hcexprs.ml @@ -135,6 +135,10 @@ module HCE = struct | E _ -> false | LV _ -> true + let type_of h = match get h with + | E e -> Cil.typeOf e + | LV lv -> Cil.typeOfLval lv + let replace kind ~late ~heir h = match get h with | E e -> let e = E.replace kind ~late ~heir e in diff --git a/src/plugins/eva/domains/hcexprs.mli b/src/plugins/eva/domains/hcexprs.mli index e39664b4827f696f413c28c62522db515732cbce..5d346bdf9de93bb74d7a49d098f6779b0033bd4f 100644 --- a/src/plugins/eva/domains/hcexprs.mli +++ b/src/plugins/eva/domains/hcexprs.mli @@ -55,7 +55,7 @@ module HCE: sig val to_exp: t -> exp val to_lval: t -> lval option val is_lval: t -> bool - + val type_of: t -> typ (** Replaces all occurrences of the lvalue [late] by the expression [heir]. @raise NonExchangeable if the replacement is not feasible. *) diff --git a/src/plugins/eva/domains/octagons.ml b/src/plugins/eva/domains/octagons.ml index add6bba4fb5a8308fb2702a59dcef0b1caabd941..00adb0b62fdff9fa42f670690688e674271b7a16 100644 --- a/src/plugins/eva/domains/octagons.ml +++ b/src/plugins/eva/domains/octagons.ml @@ -52,76 +52,117 @@ type kind = Integer | Float let typ_kind typ = match Cil.unrollType typ with - | TInt _ | TEnum _ -> Integer + | TInt _ | TEnum _ | TPtr _ -> Integer | TFloat _ -> Float | _ -> assert false +type dependencies = Eva_utils.deps = { + data: Locations.Zone.t; + indirect: Locations.Zone.t; +} + +type evaluator = Cil_types.exp -> Cvalue.V.t or_top + (* Abstract interface for the variables used by the octagons. *) module type Variable = sig include Datatype.S_with_collections - (* Creates a variable from a varinfo. Should be extended to support more - lvalues. *) - val make: varinfo -> t + (* Creates a variable from a lvalue. *) + val make_lval: lval -> t val make_int: varinfo -> t - (* Returns all variables that may have been created for a varinfo. *) - val get_all: varinfo -> t list + val make_startof: varinfo -> t val kind: t -> kind (* The kind of the variable: integer or float. *) val lval: t -> lval option (* The CIL lval corresponding to the variable. *) - val base: t -> Base.t (* Base of the variable. *) val id: t -> int (* Unique id, needed to use variables as hptmap keys. *) + val deps: eval_loc:(Cil_types.lval -> Precise_locs.precise_location) -> + t -> dependencies end (* Variables of the octagons. Should be extended later to also include symbolic lvalues. *) module Variable : Variable = struct + module HCE = Hcexprs.HCE + type var = | Var of varinfo | Int of varinfo + | StartOf of varinfo + | Lval of HCE.t + + type tt = var * int + + (* The use of [HCE.id] makes this id non-deterministic. This can have an + impact when printing the domain state, as the order between variables + depends on this id. Option -deterministic circumvents this issue. *) + let make_id = function + | Var vi -> 4 * vi.vid + | Int vi -> 4 * vi.vid + 1 + | StartOf vi -> 4 * vi.vid + 2 + | Lval lval -> 4 * HCE.id lval + 3 - let id = function - | Var vi -> 2 * vi.vid - | Int vi -> 2 * vi.vid + 1 + let id (_var, id) = id module Datatype_Input = struct include Datatype.Undefined - type t = var + type t = tt let name = "Eva.Octagons.Variable" let structural_descr = Structural_descr.t_abstract - let reprs = [ Var (List.hd Cil_datatype.Varinfo.reprs) ] - - let compare x y = - match x, y with - | Var x, Var y - | Int x, Int y -> Cil_datatype.Varinfo.compare x y - | Var _, Int _ -> -1 - | Int _, Var _ -> 1 - - let equal x y = compare x y = 0 + let reprs = [ Var (List.hd Cil_datatype.Varinfo.reprs), 0 ] + let compare x y = id y - id x + let equal = Datatype.from_compare let hash = id let rehash = Datatype.identity - let pretty fmt = function - | Var vi -> Printer.pp_varinfo fmt vi + let pretty fmt (var, _id) = + match var with + | Var vi | StartOf vi -> Printer.pp_varinfo fmt vi | Int vi -> Format.fprintf fmt "(integer)%a" Printer.pp_varinfo vi + | Lval lval -> HCE.pretty fmt lval + end include Datatype.Make_with_collections (Datatype_Input) - let make vi = Var vi - let make_int vi = Int vi - let get_all vi = [ Var vi; Int vi ] - let kind = function + let make var = var, make_id var + + let make_lval = function + | Cil_types.Var vi, NoOffset -> make (Var vi) + | lval -> make (Lval (HCE.of_lval lval)) + + let make_int vi = make (Int vi) + let make_startof vi = make (StartOf vi) + + let kind (var, _) = + match var with | Var vi -> typ_kind vi.vtype - | Int _ -> Integer + | Int _ | StartOf _ -> Integer + | Lval lval -> typ_kind (HCE.type_of lval) - let lval = function + let lval (var, _) = + match var with | Var vi -> Some (Cil_types.Var vi, NoOffset) - | Int _ -> None - - let base = function Var vi | Int vi -> Base.of_varinfo vi + | Lval lval -> HCE.to_lval lval + | Int _ | StartOf _ -> None + + let deps ~eval_loc (var, _) = + match var with + | Var vi | Int vi -> + { + data = Locations.zone_of_varinfo vi; + indirect = Locations.Zone.bottom; + } + | StartOf _ -> + { data = Locations.Zone.bottom ; indirect = Locations.Zone.bottom } + | Lval lval -> + Eva_utils.deps_of_lval eval_loc (Option.get (HCE.to_lval lval)) end +module VarSet = + Hptset.Make + (Variable) + (struct let v = [ [ ] ] end) + (struct let l = [ Ast.self ] 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. *) @@ -147,12 +188,19 @@ module Pair = struct let fst t = fst (get t) let kind t = Variable.kind (fst t) + let variable_list t = + let (v1,v2) = get t in [v1 ; v2] end (* Kind of relation between two variables X and Y: X+Y or X-Y. *) type operation = Add | Sub +let operation_of_binop = function + | PlusA | PlusPI -> Add + | MinusA | MinusPI | MinusPP -> Sub + | _ -> assert false + (* Extended arithmetic operations over Ival.t. *) module Arith = struct open Ival @@ -188,6 +236,7 @@ module Arith = struct let sub = int_or_float_operation Ival.sub_int Fval.sub let add = int_or_float_operation Ival.add_int Fval.add + let mul_integer = Ival.scale let apply = function | Add -> add @@ -218,6 +267,13 @@ let _pretty_octagon fmt octagon = Variable.pretty x op Variable.pretty y (Unicode.inset_string ()) Ival.pretty octagon.value +(* An environment associates a term v ± c, where v is a variable and + c an integer limited to an interval, to some well chosen expressions. A + request to the environment may return a new or an existing variable. + The abstract domain chooses which expressions are worth being represented + by a variable; the environment may return [None] otherwise. *) +type environment = Cil_types.exp -> (Variable.t * Ival.t) option + (* Transforms Cil expressions into mathematical octagons. Use Ival.t to evaluate expressions. *) module Rewriting = struct @@ -253,32 +309,46 @@ module Rewriting = struct where X is a variable and coeff an interval. *) type var_coeff = { var: Variable.t; sign: bool; coeff: Ival.t; } + let _pretty_var_coeff fmt var_coeff = + Format.fprintf fmt "%s%a - %a" + (if var_coeff.sign then "" else "-") + Variable.pretty var_coeff.var + Ival.pretty var_coeff.coeff + (* Negates a simplified form. *) let neg { var; sign; coeff } = { var; 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 + let (let*) x f = match x with | `Top -> [] - | `Value ival -> f ival + | `Value x -> f x + + let project_ival x = + match x with + | `Top -> `Top + | `Value x -> + try + `Value (Cvalue.V.project_ival x) + with Cvalue.V.Not_based_on_null -> `Top (* 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 apply_binop f (eval : evaluator) typ e1 op e2 = let kind = typ_kind (Cil.typeOf e1) in - let result = Arith.apply op kind v1 v2 in - if may_overflow typ result - then [] - else f kind v1 v2 + let v1 = eval e1 in + let v2 = eval e2 in + if Cil.isPointerType typ + then f kind v1 v2 + else + let* v1' = project_ival v1 in + let* v2' = project_ival v2 in + let result = Arith.apply op kind v1' v2' in + if may_overflow typ result + then [] + else f kind 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 @@ -289,60 +359,63 @@ module Rewriting = struct 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 - let var = Variable.make varinfo in - [ { var; 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 } + let rec rewrite (eval : evaluator) (env : environment) expr = + match env expr with + | Some (var, ival) -> [ { var; sign = true; coeff = Ival.neg_int ival } ] + | None -> + match expr.enode with + | UnOp (Neg, e, typ) -> + let* v = project_ival (eval e) in + if may_overflow typ (Arith.neg v) + then [] else List.map neg (rewrite eval env e) + + | BinOp (PlusA | MinusA | PlusPI | MinusPI as binop, e1, e2, typ) -> + let op = operation_of_binop binop in + let rewrite_binop kind v1 v2 = + let left_linearized = + let* v2 = project_ival v2 in + let inverse_op = if op = Add then Arith.sub else Arith.add in + try + let v2 = + if Cil.isPointerType typ + then + let scale = Cil.(bytesSizeOf (typeOf_pointed typ)) in + Arith.mul_integer (Integer.of_int scale) v2 + else v2 + in + let add_v2 var = + { var with coeff = inverse_op kind var.coeff v2 } + in + List.map add_v2 (rewrite eval env e1) + with Cil.SizeOfError _ -> [] + and right_linearized = + let* v1 = project_ival v1 in + let add_v1 var = + let var = if op = Sub then neg var else var in + { var with coeff = Arith.sub kind var.coeff v1 } + in + List.map add_v1 (rewrite eval env e2) + in + left_linearized @ right_linearized 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, { enode = Lval (Var vi, NoOffset) }) - when Cil.isIntegralType typ - && Cil.isFloatingType vi.vtype - && not (Cil.typeHasQualifier "volatile" vi.vtype) - && not (is_singleton (evaluate expr)) -> - let var = Variable.make_int vi in - [ { var; sign = true; coeff = Ival.zero } ] + apply_binop rewrite_binop eval typ e1 op e2 + | CastE (typ, e) -> + if Cil.(isIntegralType typ && isIntegralType (typeOf e)) then + let* v = project_ival (eval e) in + if may_overflow ~cast:true typ v then [] else rewrite eval env e + else if Cil.(isPointerType typ && isPointerType (typeOf e)) then + rewrite eval env e + else + [] - | CastE (typ, e) -> - if Cil.(isIntegralType typ && isIntegralType (typeOf e)) then - evaluate e >> fun v -> - if may_overflow ~cast:true typ v then [] else rewrite evaluate e - else [] - - | _ -> [] + | _ -> [] (* Rewrites the operation [e1 ± e2] into equivalent octagons ±(X±Y-value). *) - let rewrite_binop evaluate e1 binop e2 = + let rewrite_binop (eval : evaluator) (env : environment) e1 binop e2 = let kind = typ_kind (Cil.typeOf e1) in - let vars1 = rewrite evaluate e1 in - let vars2 = rewrite evaluate e2 in + let vars1 = rewrite eval env e1 in + let vars2 = rewrite eval env e2 in let vars2 = if binop = Sub then List.map neg vars2 else vars2 in let aux acc var1 var2 = if Variable.equal var1.var var2.var @@ -373,10 +446,10 @@ module Rewriting = struct (* Transforms the constraint [expr] ∈ [ival] into a list of octagonal constraints. *) - let make_octagons evaluate expr ival = + let make_octagons evaluate env expr ival = let make_octagons_from_binop kind e1 op e2 ival = (* equivalent octagonal forms ±(X±Y-v) for [e1 op e2]. *) - let rewritings = rewrite_binop evaluate e1 op e2 in + let rewritings = rewrite_binop evaluate env 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 @@ -386,13 +459,13 @@ module Rewriting = struct 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 + | BinOp (PlusA | MinusA | PlusPI | MinusPI | MinusPP as binop, e1, e2, typ) -> + let op = operation_of_binop binop 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) + if not (Cil.isIntegralOrPointerType typ) || (Ival.contains_zero ival && Ival.contains_non_zero ival) then [] else @@ -429,7 +502,7 @@ module Rewriting = struct (* 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_through_octagons (eval : evaluator) evaluate_octagon env expr = let evaluate_octagon acc (sign, octagon) = match evaluate_octagon octagon with | None -> acc @@ -444,12 +517,14 @@ module Rewriting = struct 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 octagons = rewrite_binop eval env e1 op e2 in let ival = evaluate_octagons octagons in if Ival.(equal top ival) then default else let kind = typ_kind (Cil.typeOf e1) in let ival2 = - match evaluate_expr e1, evaluate_expr e2 with + match + project_ival (eval e1), project_ival (eval e2) + with | `Value v1, `Value v2 -> Arith.apply op kind v1 v2 | _, _ -> Ival.top in @@ -458,12 +533,12 @@ module Rewriting = struct 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) -> + when Cil.isIntegralOrPointerType (Cil.typeOf e1) -> let comp = Eva_utils.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 octagons = rewrite_binop eval env 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) @@ -670,29 +745,29 @@ module Relations = struct module Dependencies = struct let l = [ Ast.self ] end include Hptmap.Make (Variable) - (struct include Variable.Set let pretty_debug = pretty end) + (struct include VarSet let pretty_debug = pretty end) (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 + let r = VarSet.inter x y in + if VarSet.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 + let decide _pair x y = VarSet.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 -> Variable.Set.empty + with Not_found -> VarSet.empty in - let updated = Variable.Set.add y related in + let updated = VarSet.add y related in add x updated t (* Marks x and y as mutually related. *) @@ -701,7 +776,7 @@ module Relations = struct relate_aux y x (relate_aux x y t) let add variable set t = - if Variable.Set.is_empty set + if VarSet.is_empty set then remove variable t else add variable set t end @@ -759,6 +834,315 @@ module Intervals = struct inter ~cache ~symmetric:false ~idempotent:true ~decide end + +(* -------------------------------------------------------------------------- *) +(* Dependencies *) +(* -------------------------------------------------------------------------- *) + +module VariableToDeps = +struct + module Deps = + struct + include Function_Froms.Deps + let pretty_debug = pretty_precise + end + + let cache_prefix = "Eva.Octagons.VariableToDeps" + + include Hptmap.Make (Variable) (Deps) (Hptmap.Comp_unused) + (struct let v = [[]] end) (struct let l = [Ast.self] end) + + let is_included: t -> t -> bool = + let cache_name = cache_prefix ^ ".is_included" in + let decide_fst _b _v1 = true in + let decide_snd _b _v2 = false in + let decide_both _ v1 v2 = Deps.is_included v1 v2 in + let decide_fast s t = if s == t then PTrue else PUnknown in + binary_predicate + (Hptmap_sig.PersistentCache cache_name) UniversalPredicate + ~decide_fast ~decide_fst ~decide_snd ~decide_both + + let narrow: t -> t -> t = + let cache_name = cache_prefix ^ ".narrow" in + let cache = Hptmap_sig.PersistentCache cache_name in + let symmetric = true in + let idempotent = true in + let decide _ v1 v2 = Deps.narrow v1 v2 in + join ~cache ~symmetric ~idempotent ~decide + + let join: t -> t -> t = + let cache_name = cache_prefix ^ ".join" in + let cache = Hptmap_sig.PersistentCache cache_name in + let symmetric = true in + let idempotent = true in + let decide _ v1 v2 = Some (Deps.join v1 v2) in + inter ~cache ~symmetric ~idempotent ~decide + + let find_opt (v: Variable.t) (m: t) = + try Some (find v m) with Not_found -> None + + (* Return the subtrees of the left map whose keys are not in the right map. *) + let only_in_left = + let cache_name = cache_prefix ^ ".only_in_left" in + let cache = Hptmap_sig.PersistentCache cache_name in + let symmetric = false in + let idempotent = false in + let decide_both _ _ _ = None in + let decide_left = Neutral in + let decide_right = Absorbing in + merge ~cache ~symmetric ~idempotent ~decide_both ~decide_left ~decide_right + + let all_but_diff = + let cache_name = cache_prefix ^ ".all_but_diff" in + let cache = Hptmap_sig.PersistentCache cache_name in + let decide_both _ d1 d2 = if Deps.equal d1 d2 then Some d1 else None in + merge ~cache ~symmetric:true ~idempotent:true + ~decide_left:Neutral ~decide_right:Neutral ~decide_both +end + +module BaseToVariables = struct + module VSet = VarSet + + (* [BaseToVariables] represents a map from bases to each symbolic variable + used in the domain state that depends on this base. + These variables are split into two (non necessary disjoint) sets: + - direct dependency: variables whose value depends on the base; + - indirect dependency: variables whose location depends on the base. *) + module VSetPair = + struct + include Datatype.Pair + (VSet) (* Directly dependent variables *) + (VSet) (* Indirectly dependent variables *) + let pretty_debug = pretty + let inter (s1,t1) (s2,t2) = VSet.inter s1 s2, VSet.inter t1 t2 + let union (s1,t1) (s2,t2) = VSet.union s1 s2, VSet.union t1 t2 + let is_empty (s, t) = VSet.is_empty s && VSet.is_empty t + end + + include Hptmap.Make (Base.Base) (VSetPair) (Hptmap.Comp_unused) + (struct let v = [[]] end) (struct let l = [Ast.self] end) + + let cache_prefix = "Eva.Octagons.BaseToVariables" + + let _narrow = + let cache_name = cache_prefix ^ ".narrow" in + let cache = Hptmap_sig.PersistentCache cache_name in + let symmetric = true in + let idempotent = true in + let decide _ v1 v2 = + let inter = VSetPair.inter v1 v2 in + if VSetPair.is_empty inter then None else Some inter + in + inter ~cache ~symmetric ~idempotent ~decide + + let join = + let cache_name = cache_prefix ^ ".join" in + let cache = Hptmap_sig.PersistentCache cache_name in + let symmetric = true in + let idempotent = true in + let decide _ v1 v2 = VSetPair.union v1 v2 in + join ~cache ~symmetric ~idempotent ~decide + + let find b m = + try find b m + with Not_found -> VSet.empty, VSet.empty + + let add_direct v = + replace (function + | None -> Some (VSet.singleton v, VSet.empty) + | Some (direct, indirect) -> Some (VSet.add v direct, indirect)) + + let add_indirect v = + replace (function + | None -> Some (VSet.empty, VSet.singleton v) + | Some (direct, indirect) -> Some (direct, VSet.add v indirect)) + + let add_deps var deps map = + Locations.Zone.fold_bases (add_direct var) deps.data map |> + Locations.Zone.fold_bases (add_indirect var) deps.indirect + + let remove_direct v = + replace (function + | None -> None + | Some (direct, indirect) -> + let direct = VSet.remove v direct in + if VSet.is_empty direct && VSet.is_empty indirect + then None + else Some (direct, indirect)) + + let remove_indirect v = + replace (function + | None -> None + | Some (direct, indirect) -> + let indirect = VSet.remove v indirect in + if VSet.is_empty direct && VSet.is_empty indirect + then None + else Some (direct, indirect)) + + let remove_deps var deps map = + Locations.Zone.fold_bases (remove_direct var) deps.data map |> + Locations.Zone.fold_bases (remove_indirect var) deps.indirect + + let all_variables m = + fold (fun _b (dv, iv) acc -> VSet.(union (union dv iv) acc)) m VSet.empty +end + +module Deps = struct + module VSet = VarSet + + include Datatype.Pair (VariableToDeps) (BaseToVariables) + + (* [hash] and [compare] do not need to consider the [BaseToVariables] part as + it can be fully deduced from VariableToDeps's one *) + let hash (m, _i: t) = + VariableToDeps.hash m + + let compare (m1, _i1: t) (m2, _i2: t) = + VariableToDeps.compare m1 m2 + + let empty = VariableToDeps.empty, BaseToVariables.empty + + let intersects_base (_m, i: t) base = + let data, indirect = BaseToVariables.find base i in + VSet.union data indirect |> VSet.elements + + let intersects_var (d: t) (vi: Cil_types.varinfo) = + intersects_base d (Base.of_varinfo vi) + + let intersects_zone (m, i: t) zone = + let filter ~direct zone v = + try + let deps = VariableToDeps.find v m in + let v_zone = if direct then deps.data else deps.indirect in + Locations.Zone.intersects v_zone zone + with Not_found -> false + in + let get_at_base b intervals (data_acc, indirect_acc) = + let data, indirect = BaseToVariables.find b i in + let zone = Locations.Zone.inject b intervals in + VSet.union data_acc (VSet.filter (filter ~direct:true zone) data), + VSet.union indirect_acc (VSet.filter (filter ~direct:false zone) indirect) + in + let data, indirect = + Locations.Zone.fold_topset_ok get_at_base zone (VSet.empty, VSet.empty) + in + VSet.union data indirect |> VSet.elements + + (* Does [deps] contains at least the bases from [previous_deps]? *) + let are_bases_increasing previous_deps deps = + let get_bases = Locations.Zone.get_bases in + let is_increasing previous_zone zone = + Base.SetLattice.is_included (get_bases previous_zone) (get_bases zone) + in + is_increasing previous_deps.data deps.data && + is_increasing previous_deps.indirect deps.indirect + + (* Exact but slower [add]: in the resulting maps (m, i), [i] is exactly the + inverse of the map [m]. *) + let _exact_add var deps (m, i: t): t = + let add_to (m, i) = + VariableToDeps.add var deps m, + BaseToVariables.add_deps var deps i + in + match VariableToDeps.find_opt var m with + | Some previous_deps when Function_Froms.Deps.equal previous_deps deps -> + m, i + | Some previous_deps when not (are_bases_increasing previous_deps deps) -> + (* If [var] already exists in the state and had bigger dependencies (a + dependency can disappear by reduction), remove the previous deps + from the inverse map to ensure consistency between both maps. *) + add_to (m, BaseToVariables.remove_deps var previous_deps i) + | _ -> add_to (m, i) + + (* Faster but approximating [add]: in the resulting maps (m, i), [i] may + contain variables that do not appear in [m]. *) + let add var deps (m, i: t): t = + match VariableToDeps.find_opt var m with + | Some d when Function_Froms.Deps.equal d deps -> m, i + | _ -> + VariableToDeps.add var deps m, + BaseToVariables.add_deps var deps i + + let remove (var: Variable.t) ((m, i): t): t option = + match VariableToDeps.find_opt var m with + | None -> None (* The variable was not registered *) + | Some deps -> + Some (VariableToDeps.remove var m, + BaseToVariables.remove_deps var deps i) + + let filter (bases: Base.Hptset.t) (m, i : t): VSet.t * t = + let i_inter, i_diff = BaseToVariables.partition_with_shape bases i in + let removed_vars = BaseToVariables.all_variables i_diff in + let m = VariableToDeps.diff_with_shape removed_vars m in + let filter (s1, s2) = + VSet.diff s1 removed_vars, VSet.diff s2 removed_vars + in + let i = BaseToVariables.map filter i_inter in + removed_vars, (m, i) + + let get_var_bases (m, _: t) (var: Variable.t) = + try + let deps = VariableToDeps.find var m in + let zone = Locations.Zone.join deps.data deps.indirect in + Locations.Zone.get_bases zone + with Not_found -> Base.SetLattice.empty + + (* Exact but slower [join]: in the resulting maps (m, i), [i] is exactly the + inverse of the map [m]. *) + let _exact_join (m1, i1: t) (m2, i2: t) = + let m1_only = VariableToDeps.only_in_left m1 m2 + and m2_only = VariableToDeps.only_in_left m2 m1 in + let i1 = VariableToDeps.fold BaseToVariables.remove_deps m1_only i1 + and i2 = VariableToDeps.fold BaseToVariables.remove_deps m2_only i2 in + VariableToDeps.join m1 m2, BaseToVariables.join i1 i2 + + (* Exact but slower [narrow]: in the resulting maps (m, i), [i] is exactly the + inverse of the map [m]. *) + let _exact_narrow (m1, i1: t) (m2, i2: t) = + let all_but_diff = VariableToDeps.all_but_diff m1 m2 in + let m1 = VariableToDeps.only_in_left m1 all_but_diff + and m2 = VariableToDeps.only_in_left m2 all_but_diff in + let m_narrow = VariableToDeps.narrow m1 m2 + and m_join = VariableToDeps.join m1 m2 in + let m = VariableToDeps.narrow m_narrow all_but_diff in + let i = BaseToVariables.join i1 i2 in + let i = VariableToDeps.fold BaseToVariables.remove_deps m_join i in + let i = VariableToDeps.fold BaseToVariables.add_deps m_narrow i in + m, i + + (* Faster but approximating [join]: in the resulting maps (m, i), [i] may + contain variables that do not appear in [m]. *) + let join (m1, i1: t) (m2, i2: t) = + VariableToDeps.join m1 m2, BaseToVariables.join i1 i2 + + (* Faster but approximating [narrow]: in the resulting maps (m, i), [i] may + contain variables that do not appear in [m]. *) + let narrow (m1, i1: t) (m2, i2: t) = + VariableToDeps.narrow m1 m2, BaseToVariables.join i1 i2 + + let is_included (m1, _: t) (m2, _: t) = + VariableToDeps.is_included m1 m2 + + (* Check inverse dependencies. *) + let check (abort: ('a, Format.formatter, unit) format -> 'a) (m, i: t) = + let check_inverse var deps = + let check_base fst_or_snd base = + if not (VSet.mem var (fst_or_snd (BaseToVariables.find base i))) + then + abort "Missing inverse dependency %a of variable %a@" + Base.pretty base Variable.pretty var + in + let check_zone fst_or_snd zone = + let bases = Locations.Zone.get_bases zone in + Base.SetLattice.iter (check_base fst_or_snd) bases + in + check_zone fst deps.data; + check_zone snd deps.indirect; + in + VariableToDeps.iter check_inverse m +end + + (* -------------------------------------------------------------------------- *) (* Octagon states *) (* -------------------------------------------------------------------------- *) @@ -772,6 +1156,7 @@ module State = struct 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. *) + deps: Deps.t; } include Datatype.Make_with_collections @@ -785,26 +1170,31 @@ module State = struct [| Octagons.packed_descr; Intervals.packed_descr; Relations.packed_descr; - Zone.packed_descr |] + Zone.packed_descr; + Deps.packed_descr |] let reprs = [ { octagons = Octagons.top; intervals = Intervals.empty; relations = Relations.empty; - modified = Zone.bottom } ] + modified = Zone.bottom; + deps = Deps.empty; } ] 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 (<?>) c lcmp = + if c <> 0 then c else Lazy.force lcmp + in + Octagons.compare s1.octagons s2.octagons <?> + lazy (Intervals.compare s1.intervals s2.intervals) <?> + lazy (Zone.compare s1.modified s2.modified) <?> + lazy (Deps.compare s1.deps s2.deps) let equal = Datatype.from_compare let hash t = Hashtbl.hash (Octagons.hash t.octagons, Intervals.hash t.intervals, - Zone.hash t.modified) + Zone.hash t.modified, + Deps.hash t.deps) let pretty fmt { octagons } = Format.fprintf fmt "@[%a@]" Octagons.pretty octagons @@ -812,33 +1202,56 @@ module State = struct let log_category = Self.register_category "d-octagon" - let pretty_debug fmt { octagons; intervals; relations } = - Format.fprintf fmt "@[<v> Octagons: %a@; Intervals: %a@; Relations: %a@]" + let pretty_debug fmt { octagons; intervals; relations; deps } = + Format.fprintf fmt + "@[<v> Octagons: %a@; Intervals: %a@; Relations: %a@; Dependencies: %a@.]" Octagons.pretty octagons Intervals.pretty intervals Relations.pretty relations + Deps.pretty deps (* 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 -> + else fun name t -> + let abort format = + Format.kasprintf + (fun s -> + Self.fatal + "Incorrect octagon computed by function %s: %s@\n State: %a" + name s pretty_debug t) + format + in (* 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_relation x y = + try VarSet.mem x (Relations.find y t.relations) + && VarSet.mem y (Relations.find x t.relations) + with Not_found -> false + in + let check_relation x y = + if not (check_relation x y) + then + abort "missing relations between %a and %a" + Variable.pretty x Variable.pretty y + in + (* Checks that dependencies of [var] are correctly registered. *) + let check_deps var = + if not (VariableToDeps.mem var (fst t.deps)) + then abort "missing dependencies of variable %a" Variable.pretty var + in let check_octagon pair _ = let x, y = Pair.get pair in - try Variable.Set.mem x (Relations.find y t.relations) - && Variable.Set.mem y (Relations.find x t.relations) - with Not_found -> false + check_relation x y; check_deps x; check_deps y in - if Octagons.for_all check_octagon t.octagons - then t - else - Self.abort - "Incorrect octagon state computed by function %s:@ %a" - msg pretty_debug t + Octagons.iter check_octagon t.octagons; + Intervals.iter (fun var _ -> check_deps var) t.intervals; + (* Check consistency of the dependency maps. *) + Deps.check abort t.deps; + t (* Is an octagon no more precise than the intervals inferred for the related variables? If so, do not save the octagon in the domain. *) @@ -858,24 +1271,84 @@ module State = struct is_redundant intervals {variables; operation = Add; value = diamond.add} && is_redundant intervals {variables; operation = Sub; value = diamond.sub} + (* Evaluates offset to an interval using the evaluate function for indexes *) + let rec offset_to_coeff (eval : evaluator) base_type offset = + let open Lattice_bounds.Top.Operators in + match offset with + | Cil_types.NoOffset -> `Value (Ival.zero) + | Field (fi, sub) -> + let* sub_coeff = offset_to_coeff eval fi.ftype sub in + begin try + let byte_offset = Integer.of_int (fst (Cil.fieldBitsOffset fi) / 8) in + let coeff = Ival.add_singleton_int byte_offset sub_coeff in + `Value coeff + with Cil.SizeOfError _ -> `Top + end + | Index (exp, sub) -> + let elem_type = Cil.typeOf_array_elem base_type in + let* cvalue = eval exp in + let* index = + try + `Value (Cvalue.V.project_ival cvalue) + with Cvalue.V.Not_based_on_null -> `Top + in + let* sub_coeff = offset_to_coeff eval elem_type sub in + let+ elem_size = + try `Value (Cil.bytesSizeOf elem_type) + with Cil.SizeOfError _ -> `Top + in + Ival.(add_int (scale (Integer.of_int elem_size) index) sub_coeff) + + let mk_variable_builder (eval : evaluator) (_: t) = + let (let*) x f = Option.bind (Top.to_option x) f in + (* Is the interval computed for a variable a singleton? *) + let is_singleton = + Top.fold ~top:false Cvalue.V.cardinal_zero_or_one + in + fun exp -> + match exp.enode with + | Lval lval + when Cil.isIntegralOrPointerType (Cil.typeOfLval lval) + && not (Eval_typ.lval_contains_volatile lval) + && not (is_singleton (eval exp)) -> + Some (Variable.make_lval lval, Ival.zero) + + | CastE (typ, { enode = Lval (Var vi, NoOffset) }) + when Cil.isIntegralType typ + && Cil.isFloatingType vi.vtype + && not (Cil.typeHasQualifier "volatile" vi.vtype) + && not (is_singleton (eval exp)) -> + Some (Variable.make_int vi, Ival.zero) + + | StartOf (Var vi, offset) | AddrOf (Var vi, offset) -> + let var = Variable.make_startof vi in + let* coeff = offset_to_coeff eval vi.vtype offset in + Some (var, coeff) + + | _ -> None + + (* ------------------------------ Lattice --------------------------------- *) let top = { octagons = Octagons.top; intervals = Intervals.top; relations = Relations.empty; - modified = Zone.top; } + modified = Zone.top; + deps = Deps.empty } let empty () = { octagons = Octagons.top; intervals = Intervals.top; relations = Relations.empty; - modified = Zone.bottom; } + modified = Zone.bottom; + deps = Deps.empty } 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 + && Deps.is_included t1.deps t2.deps let join t1 t2 = let octagons = @@ -906,7 +1379,9 @@ module State = struct let state = { octagons; relations; intervals = Intervals.join t1.intervals t2.intervals; - modified = Zone.join t1.modified t2.modified; } + modified = Zone.join t1.modified t2.modified; + deps = Deps.join t1.deps t2.deps; + } in check "join" state @@ -943,7 +1418,8 @@ module State = struct let state = { octagons; relations; intervals = Intervals.widen t1.intervals t2.intervals; - modified = Zone.join t1.modified t2.modified; } + modified = Zone.join t1.modified t2.modified; + deps = Deps.join t1.deps t2.deps } in check "widen" state @@ -952,7 +1428,8 @@ module State = struct 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; } + let deps = Deps.narrow t1.deps t2.deps in + `Value { octagons; intervals; relations; modified; deps } (* -------------- Transitive closure when adding an octagon --------------- *) @@ -999,7 +1476,7 @@ module State = struct let saturate state x y rel1 = try let y_related = Relations.find y state.relations in - let y_related = Variable.Set.remove x y_related in + let y_related = VarSet.remove x y_related in let aux z state = state >>- fun state -> try @@ -1011,10 +1488,11 @@ module State = struct add_diamond state pair diamond with Not_found -> `Value state in - Variable.Set.fold aux y_related (`Value state) + VarSet.fold aux y_related (`Value state) with Not_found -> `Value state - let add_octagon state octagon = + (* Adds dependencies to the state only if [eval_deps] is not None. *) + let add_octagon eval_deps state octagon = if Ival.(equal top octagon.value) || is_redundant state.intervals octagon then `Value state else @@ -1034,32 +1512,45 @@ module State = struct 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 variable_list = Pair.variable_list octagon.variables in + let deps = + match eval_deps with + | None -> state.deps + | Some eval_deps -> + let add_var_deps deps v = + Deps.add v (eval_deps v) deps + in + List.fold_left add_var_deps state.deps variable_list + in + { state with octagons; relations; deps } - let add_diamond state variables diamond = - add_octagon state { variables; operation = Add; value = diamond.add } + let add_diamond eval_deps state variables diamond = + add_octagon eval_deps state { variables; operation = Add; value = diamond.add } >>- fun state -> - add_octagon state { variables; operation = Sub; value = diamond.sub } + add_octagon eval_deps state { variables; operation = Sub; value = diamond.sub } 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 = Variable.Set.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 = Variable.Set.fold remove_one relations state in - let relations = Relations.remove x state.relations in - { state with relations } - with Not_found -> state + match Deps.remove x state.deps with + | None -> state + | Some deps -> + let intervals = Intervals.remove x state.intervals in + let state = { state with intervals; deps } 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 = VarSet.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 = VarSet.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 @@ -1072,7 +1563,7 @@ module State = struct (y, diamond) :: acc with Not_found -> acc in - Variable.Set.fold aux related [] + VarSet.fold aux related [] with Not_found -> [] (* x' = ±x - delta *) @@ -1108,9 +1599,10 @@ module State = struct { state with octagons } with Not_found -> state in - Variable.Set.fold aux x_related state + VarSet.fold aux x_related state end + (* -------------------------------------------------------------------------- *) (* Octagon domain *) (* -------------------------------------------------------------------------- *) @@ -1126,17 +1618,42 @@ module Domain = struct let top_value = `Value (Cvalue.V.top, None), Alarmset.all - let extract_expr ~oracle _context 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 + (* Evaluator building. *) + + let evaluator_from_oracle oracle = fun expr -> + match fst (oracle expr) with + | `Bottom -> `Top (* should not happen *) + | `Value (Cvalue.V.Top _) -> `Top + | `Value cvalue -> `Value cvalue + + let evaluator_from_valuation valuation = + let eval_exp expr = + match valuation.Abstract_domain.find expr with + | `Top -> `Top + | `Value record -> + match record.Eval.value.v with + | `Bottom -> `Top (* TODO: why this keeps happening? *) + | `Value (Cvalue.V.Top _) -> `Top + | `Value cvalue -> `Value cvalue + in + let eval_loc lval = + match valuation.Abstract_domain.find_loc lval with + | `Top -> Precise_locs.loc_top + | `Value record -> record.loc + in + let eval_deps var = + Variable.deps ~eval_loc var in + eval_exp, eval_deps + + (* Domain functions *) + + let extract_expr ~oracle _context state expr = + let eval = evaluator_from_oracle oracle in let evaluate_octagon octagon = Octagons.evaluate octagon state.octagons in + let env = mk_variable_builder eval state in let ival, alarms = - Rewriting.evaluate_through_octagons evaluate_expr evaluate_octagon expr + Rewriting.evaluate_through_octagons eval evaluate_octagon env expr in if Ival.(equal ival top) then top_value @@ -1148,11 +1665,11 @@ module Domain = struct let reduce_further state expr value = match expr.enode with - | Lval (Var x, NoOffset) when Cil.isIntegralType x.vtype -> + | Lval lval when Cil.(isIntegralOrPointerType (typeOfLval lval)) -> begin try let x_ival = Cvalue.V.project_ival value in - let var = Variable.make x in + let var = Variable.make_lval lval in let kind = Variable.kind var in let octagons = State.related_octagons state var in let reduce acc (y, octagons) = @@ -1181,58 +1698,44 @@ module Domain = struct end | _ -> [] - - let kill_base base state = - try - let varinfo = Base.to_varinfo base in - let vars = Variable.get_all varinfo in - List.fold_left State.remove state vars - 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 + let vars = Deps.intersects_zone state.deps zone in + let state = List.fold_left State.remove state vars in { state with modified } - (* Evaluation function of expressions to ival, from a [valuation]. *) - let evaluation_function valuation = fun expr -> - match valuation.Abstract_domain.find 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 infer_octagons valuation expr ival state = + let eval_exp, eval_deps = evaluator_from_valuation valuation in + let env = mk_variable_builder eval_exp state in + let octagons = Rewriting.make_octagons eval_exp env expr ival in let add_octagon state octagon = - match State.add_octagon state octagon with + match State.add_octagon (Some eval_deps) state octagon with | `Bottom -> raise EBottom | `Value state -> state in List.fold_left add_octagon state octagons - let infer_interval expr ival state = + let infer_interval eval_deps expr ival state = if not infer_intervals then state else match expr.enode with - | Lval (Var varinfo, NoOffset) - when Cil.isIntegralType varinfo.vtype -> - let var = Variable.make varinfo in + | Lval lval when Cil.(isIntegralType (typeOfLval lval)) + && not (Eval_typ.lval_contains_volatile lval) -> + let var = Variable.make_lval lval in + let deps = Deps.add var (eval_deps var) state.deps in let intervals = Intervals.add var ival state.intervals in - { state with intervals } + { state with intervals; deps } | _ -> state let update valuation state = - let evaluate = evaluation_function valuation in + let _eval_exp, eval_deps = evaluator_from_valuation valuation in let aux expr record state = let value = record.Eval.value in match record.reductness, value.v, value.initialized, value.escaping with @@ -1240,8 +1743,8 @@ module Domain = struct begin try let ival = Cvalue.V.project_ival cvalue in - let state = infer_octagons evaluate expr ival state in - infer_interval expr ival state + let state = infer_octagons valuation expr ival state in + infer_interval eval_deps expr ival state with Cvalue.V.Not_based_on_null -> state end | _ -> state @@ -1249,7 +1752,7 @@ module Domain = struct try `Value (check "update" (valuation.Abstract_domain.fold aux state)) with EBottom -> `Bottom - let assign_interval variable assigned state = + let assign_interval eval_deps variable assigned state = if not infer_intervals then state else @@ -1260,17 +1763,27 @@ module Domain = struct try let ival = Cvalue.V.project_ival v in let intervals = Intervals.add variable ival state.intervals in - { state with intervals } + let deps = Deps.add variable (eval_deps variable) state.deps in + { state with intervals; deps } with Cvalue.V.Not_based_on_null -> state end | _ -> state - (* Assigns integer [varinfo] to [expr]. *) - let assign_variable varinfo expr assigned valuation state = - let evaluate = evaluation_function valuation in + (* Assigns [lvalue] to [expr]. *) + let assign_variable lvalue expr assigned valuation state = + let eval_exp, eval_deps = evaluator_from_valuation valuation in + let variable = Variable.make_lval lvalue in + (* Remove lvals refering to the variable *) + let lvalue_zone = (eval_deps variable).data in + let modified = Locations.Zone.join state.modified lvalue_zone in + let state = { state with modified } in + let vars = Deps.intersects_zone state.deps lvalue_zone in + let vars = List.filter (Fun.negate (Variable.equal variable)) vars in + let state = List.fold_left State.remove state vars in + (* Interpret inversible assignment if possible *) (* TODO: redundant with rewrite_binop below. *) - let vars = Rewriting.rewrite evaluate expr in - let variable = Variable.make varinfo in + let env = mk_variable_builder eval_exp state in + let vars = Rewriting.rewrite eval_exp env expr in let equal_varinfo v = Variable.equal variable v.Rewriting.var in let state = try @@ -1279,26 +1792,27 @@ module Domain = struct State.sub_delta ~inverse state variable var.Rewriting.coeff with Not_found -> State.remove state variable in - let state = assign_interval variable assigned state in - let enode = Lval (Var varinfo, NoOffset) in + let state = assign_interval eval_deps variable assigned state in + let enode = Lval lvalue 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 octagons = Rewriting.rewrite_binop eval_exp env left_expr Sub expr in let state = List.fold_left (fun acc (_sign, octagon) -> - acc >>- fun state -> State.add_octagon state octagon) + acc >>- fun state -> + State.add_octagon (Some eval_deps) 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 assign kinstr left_value expr assigned valuation state = + if kinstr <> Kglobal + && Cil.isIntegralOrPointerType left_value.ltyp + && not (Eval_typ.lval_contains_volatile left_value.lval) + then assign_variable left_value.lval expr assigned valuation state + else let written_loc = Precise_locs.imprecise_location left_value.lloc in let written_zone = Locations.(enumerate_valid_bits Write written_loc) @@ -1310,7 +1824,8 @@ module Domain = struct let start_recursive_call recursion state = let vars = List.map fst recursion.substitution @ recursion.withdrawal in - let vars = List.flatten (List.map Variable.get_all vars) in + let var_deps v = Deps.intersects_var state.deps v in + let vars = List.flatten (List.map var_deps vars) in List.fold_left State.remove state vars let start_call _stmt call recursion valuation state = @@ -1327,8 +1842,9 @@ module Domain = struct `Value (start_recursive_call recursion state) | None -> let assign_formal state { formal; concrete; avalue } = - if Cil.isIntegralType formal.vtype - then state >>- assign_variable formal concrete avalue valuation + let lval = (Var formal, NoOffset) in + if Cil.isIntegralOrPointerType formal.vtype + then state >>- assign_variable lval concrete avalue valuation else state in List.fold_left assign_formal (`Value state) call.arguments @@ -1348,7 +1864,8 @@ module Domain = struct let enter_scope _kind _varinfos state = state let leave_scope _kf varinfos state = - let vars = List.flatten (List.map Variable.get_all varinfos) in + let var_deps v = Deps.intersects_var state.deps v in + let vars = List.concat_map var_deps varinfos in let state = List.fold_left State.remove state vars in check "leave_scope" state @@ -1360,34 +1877,33 @@ module Domain = struct then Base.SetLattice.empty else let add_related_bases acc var = - let related = Relations.find var state.relations in - Variable.Set.fold - (fun var -> Base.Hptset.add (Variable.base var)) - related acc + try + let related = Relations.find var state.relations in + VarSet.elements related |> + List.map (Deps.get_var_bases state.deps) |> + List.fold_left Base.SetLattice.join acc + with Not_found -> acc in let aux base acc = - try - let varinfo = Base.to_varinfo base in - let variables = Variable.get_all varinfo in - List.fold_left add_related_bases acc variables - with Base.Not_a_C_variable | Not_found -> acc + let variables = Deps.intersects_base state.deps base in + List.fold_left add_related_bases acc variables in - let hptset = Base.Hptset.fold aux bases Base.Hptset.empty in - Base.SetLattice.inject hptset + Base.Hptset.fold aux bases Base.SetLattice.empty let filter _kind bases state = if intraprocedural () then state else - let mem_var var = Base.Hptset.mem (Variable.base var) bases in + let removed_vars, deps = Deps.filter bases state.deps in + let mem_var v = not (VarSet.mem v removed_vars) in let mem_pair pair = let x, y = Pair.get pair in mem_var x && mem_var y in let octagons = Octagons.filter mem_pair state.octagons in - let intervals = Intervals.filter mem_var state.intervals in - let relations = Relations.filter mem_var state.relations in - { state with octagons; intervals; relations; } + let intervals = Intervals.diff_with_shape removed_vars state.intervals in + let relations = Relations.diff_with_shape removed_vars state.relations in + { state with octagons; intervals; relations; deps } let interprocedural_reuse = let cache = Hptmap_sig.PersistentCache "Octagons.reuse" @@ -1399,6 +1915,8 @@ module Domain = struct and join_rel = Relations.union in fun kf ~current_input ~previous_output -> let current_input = kill previous_output.modified current_input in + let intervals = join_itv previous_output.intervals current_input.intervals + and deps = Deps.narrow previous_output.deps current_input.deps in (* We use [add_diamond] to add each relation from the previous output into the current input, in order to benefit from the (partial) saturation of octagons performed by this function. For a maximum @@ -1407,12 +1925,9 @@ module Domain = struct of the maps from the previous output and the current input. *) if saturate_octagons then - let intervals = - join_itv previous_output.intervals current_input.intervals - in - let state = { current_input with intervals } in + let state = { current_input with intervals; deps } in let add_diamond variables diamond acc = - match add_diamond acc variables diamond with + match add_diamond None acc variables diamond with | `Value state -> state | `Bottom -> Self.failure ~current:true ~once:true @@ -1425,9 +1940,9 @@ module Domain = struct Octagons.fold add_diamond previous_output.octagons state else { octagons = join_oct previous_output.octagons current_input.octagons; - intervals = join_itv previous_output.intervals current_input.intervals; relations = join_rel previous_output.relations current_input.relations; - modified = current_input.modified } + modified = current_input.modified; + intervals; deps; } let reuse kf _bases ~current_input ~previous_output = if intraprocedural () @@ -1435,9 +1950,6 @@ module Domain = struct else let t = interprocedural_reuse kf ~current_input ~previous_output in check "reuse result" t - - - end include Domain diff --git a/src/plugins/eva/engine/compute_functions.ml b/src/plugins/eva/engine/compute_functions.ml index cfb195799f725002717bd4354080abf90cfa08fd..5e913a57d2c6738e82bcb20c861fa11a0cbc8177 100644 --- a/src/plugins/eva/engine/compute_functions.ml +++ b/src/plugins/eva/engine/compute_functions.ml @@ -85,6 +85,7 @@ let pre_analysis () = Widen.precompute_widen_hints (); Builtins.prepare_builtins (); Eva_perf.reset (); + Statistics.reset_all (); (* We may be resuming Value from a previously crashed analysis. Clear degeneration states *) Eva_utils.DegenerationPoints.clear (); @@ -363,6 +364,7 @@ module Make (Abstract: Abstractions.Eva) = struct post_analysis (); Abstract.Dom.post_analysis final_state; Summary.print_summary (); + Statistics.export_as_csv (); restore_signals () in let cleanup () = diff --git a/src/plugins/eva/engine/iterator.ml b/src/plugins/eva/engine/iterator.ml index c05c4a2f10b16094f37ca59e57c63161cf4f5389..2a0c7af021ac216b6eae8cea7f8315e3604f3ece 100644 --- a/src/plugins/eva/engine/iterator.ml +++ b/src/plugins/eva/engine/iterator.ml @@ -36,6 +36,7 @@ let check_signals, signal_abort = let dkey = Self.dkey_iterator let dkey_callbacks = Self.dkey_callbacks +let stat_iterations = Statistics.register_statement_stat "iterations" let blocks_share_locals b1 b2 = match b1.blocals, b2.blocals with @@ -463,7 +464,7 @@ module Make_Dataflow end; (* Get vertex store *) let store = get_vertex_store v in - (* Join incoming s tates *) + (* Join incoming states *) let flow = Partitioning.join sources store in let flow = match v.vertex_start_of with @@ -562,6 +563,7 @@ module Make_Dataflow not (process_vertex ~widening:true v) || !iteration_count = 0 do Self.debug ~dkey "iteration %d" !iteration_count; + Option.iter (Statistics.incr stat_iterations) v.vertex_start_of; iterate_list w; incr iteration_count; done; diff --git a/src/plugins/eva/engine/mem_exec.ml b/src/plugins/eva/engine/mem_exec.ml index 71a68968d66278547885435ca8aae20ffc1e569b..a4a530a9741beeddfabb84ce64c3b793ee629878 100644 --- a/src/plugins/eva/engine/mem_exec.ml +++ b/src/plugins/eva/engine/mem_exec.ml @@ -20,6 +20,8 @@ (* *) (**************************************************************************) +let stat_hits = Statistics.register_function_stat "memexec-hits" +let stat_misses = Statistics.register_function_stat "memexec-misses" module SaveCounter = State_builder.SharedCounter(struct let name = "Mem_exec.save_counter" end) @@ -263,10 +265,14 @@ module Make let args = List.map (function `Bottom -> None | `Value v -> Some v) args in let previous = ActualArgs.Map.find args previous_kf in find_match_in_previous kf previous state; + Statistics.incr stat_misses kf; None with - | Not_found -> None + | Not_found -> + Statistics.incr stat_misses kf; + None | Result_found (outputs, i) -> + Statistics.incr stat_hits kf; let call_result = outputs in Some (call_result, i) diff --git a/src/plugins/eva/engine/transfer_stmt.ml b/src/plugins/eva/engine/transfer_stmt.ml index 40d9b76071d483c8e5be05e37b31888150a2afa0..71042b2b2e41baab8d8f7d0c49e811f686231910 100644 --- a/src/plugins/eva/engine/transfer_stmt.ml +++ b/src/plugins/eva/engine/transfer_stmt.ml @@ -731,7 +731,6 @@ module Make (Abstract: Abstractions.Eva) = struct let stack_with_call = (kf, ki_call) :: Eva_utils.call_stack () in let cvalue_state = Domain.get_cvalue_or_top state in Db.Value.Call_Value_Callbacks.apply (cvalue_state, stack_with_call); - Db.Value.merge_initial_state (Eva_utils.call_stack ()) cvalue_state; let kind = `Builtin None in Cvalue_callbacks.apply_call_hooks stack_with_call kf kind cvalue_state diff --git a/src/plugins/eva/legacy/eval_op.ml b/src/plugins/eva/legacy/eval_op.ml index 211afbcf983aea4a31991cd1fd39d420d7835b7a..aa9227c45553d7d538902228d7a64968d56395e2 100644 --- a/src/plugins/eva/legacy/eval_op.ml +++ b/src/plugins/eva/legacy/eval_op.ml @@ -201,7 +201,7 @@ let pretty_offsetmap typ fmt offsm = then Format.fprintf fmt "%s" (Unicode.emptyset_string ()) else begin match Cvalue.V_Offsetmap.single_interval_value offsm with - | Some value -> Cvalue.V_Or_Uninitialized.pretty fmt value; + | Some value -> Cvalue.V_Or_Uninitialized.pretty_typ (Some typ) fmt value; | None -> Cvalue.V_Offsetmap.pretty_generic ~typ () fmt offsm; pretty_stitched_offsetmap fmt typ offsm diff --git a/src/plugins/eva/parameters.ml b/src/plugins/eva/parameters.ml index a8a1b273ecc4111d11114502ac711dbd8902ef92..dca2f98df5726fbd57b4aacb43f2e598e21ace42 100644 --- a/src/plugins/eva/parameters.ml +++ b/src/plugins/eva/parameters.ml @@ -1091,6 +1091,18 @@ module NumerorsLogFile = function in the given file" end) +let () = Parameter_customize.set_group messages +module StatisticsFile = + Filepath + (struct + let option_name = "-eva-statistics-file" + let arg_name = "file.csv" + let file_kind = "CSV" + let existence = Fc_Filepath.Indifferent + let help = "Dump some internal statistics about the analysis" + end) + + (* ------------------------------------------------------------------------- *) (* --- Interpreter mode --- *) (* ------------------------------------------------------------------------- *) diff --git a/src/plugins/eva/parameters.mli b/src/plugins/eva/parameters.mli index 4d8288faaa60f03efafc777f3859fa4e41fea8f5..61daa88642517dc801a2a65b73d7b82e80ce6210 100644 --- a/src/plugins/eva/parameters.mli +++ b/src/plugins/eva/parameters.mli @@ -125,6 +125,7 @@ module ShowSlevel: Parameter_sig.Int module PrintCallstacks: Parameter_sig.Bool module ReportRedStatuses: Parameter_sig.Filepath module NumerorsLogFile: Parameter_sig.Filepath +module StatisticsFile: Parameter_sig.Filepath module MemExecAll: Parameter_sig.Bool diff --git a/src/plugins/eva/partitioning/partition.ml b/src/plugins/eva/partitioning/partition.ml index f0b7663f535570ad0678aa5c6f3f4617de67430c..14723800087101c1b1049d3fd7a0b910ff631278 100644 --- a/src/plugins/eva/partitioning/partition.ml +++ b/src/plugins/eva/partitioning/partition.ml @@ -655,8 +655,8 @@ struct in List.fold_left transfer [] p - let iter (f : state -> unit) (p : t) : unit = - List.iter (fun (_k,x) -> f x) p + let iter (f : key -> state -> unit) (p : t) : unit = + List.iter (fun (k, x) -> f k x) p let join_duplicate_keys (p : t) : t = let cmp (k, _) (k', _) = Key.compare k k' in diff --git a/src/plugins/eva/partitioning/partition.mli b/src/plugins/eva/partitioning/partition.mli index e1f6d42ab427ffc10fd192ba905db7fb1737731d..caf4e08c2487c27dba54be9916b43945669c14d4 100644 --- a/src/plugins/eva/partitioning/partition.mli +++ b/src/plugins/eva/partitioning/partition.mli @@ -195,7 +195,7 @@ sig val transfer : ((key * state) -> (key * state) list) -> t -> t val transfer_keys : t -> action -> t - val iter : (state -> unit) -> t -> unit + val iter : (key -> state -> unit) -> t -> unit val filter_map: (key -> state -> state option) -> t -> t val join_duplicate_keys: t -> t diff --git a/src/plugins/eva/partitioning/partitioning_index.ml b/src/plugins/eva/partitioning/partitioning_index.ml index 8379820d3bff92866607ee46d8f34b1065d6541d..422d29c424b36cfd050c73f464ae880d6c6cbf62 100644 --- a/src/plugins/eva/partitioning/partitioning_index.ml +++ b/src/plugins/eva/partitioning/partitioning_index.ml @@ -20,6 +20,10 @@ (* *) (**************************************************************************) +let stat_hits = Statistics.register_global_stat "partitioning-index-hits" +let stat_misses = Statistics.register_global_stat "partitioning-index-misses" + + (** Partition of the abstract states, computed for each node by the dataflow analysis. *) module Make (Domain : Abstract.Domain.External) @@ -86,6 +90,11 @@ module Make (Domain : Abstract.Domain.External) then false else (Index.add states prefix state; true) + let add state partition = + let r = add state partition in + Statistics.incr (if r then stat_misses else stat_hits) (); + r + let iter f { states; others } = Index.iter (fun _k v -> f v) states; List.iter f others diff --git a/src/plugins/eva/partitioning/partitioning_parameters.ml b/src/plugins/eva/partitioning/partitioning_parameters.ml index f2ecaebbb2c88b0fa3e27a5e530fabc22e51d95f..bbea9b87aed55ef78df676d4cb53fb1d5ffdaa4e 100644 --- a/src/plugins/eva/partitioning/partitioning_parameters.ml +++ b/src/plugins/eva/partitioning/partitioning_parameters.ml @@ -109,7 +109,7 @@ struct let universal_splits = let add name l = try - let vi = Globals.Vars.find_from_astinfo name VGlobal in + let vi = Globals.Vars.find_from_astinfo name Global in let monitor = Partition.new_monitor ~split_limit in let expr = Partition.Expression (Cil.evar vi) in Partition.Split (expr, Partition.Dynamic, monitor) :: l diff --git a/src/plugins/eva/partitioning/trace_partitioning.ml b/src/plugins/eva/partitioning/trace_partitioning.ml index ea47c4aa9a23114915f126f9062413b27b10fc41..2e38c548ff027ad0587432d265d6e0beaff02f6a 100644 --- a/src/plugins/eva/partitioning/trace_partitioning.ml +++ b/src/plugins/eva/partitioning/trace_partitioning.ml @@ -23,6 +23,8 @@ open Cil_types open Partition +let stat_max_widenings = Statistics.register_statement_stat "max-widenings" + module Make (Abstract: Abstractions.Eva) (Kf : sig val kf: kernel_function end) = @@ -40,8 +42,8 @@ struct type state = Domain.t type store = { - rationing: Partition.rationing; (* slevel rationing at this point *) flow_actions : action list; (* partitioning actions to be applied *) + rationing: bool; (* Is there a slevel rationing in above actions? *) store_stmt : stmt option; store_index : Index.t; (* Index of all states stored: used to quickly remove new states that have already been propagated. *) @@ -59,6 +61,7 @@ struct mutable widened_state : state option; mutable previous_state : state; mutable widening_counter : int; + mutable widening_steps : int; (* count the number of successive widenings *) } type widening = { @@ -69,13 +72,27 @@ struct (* Constructors *) let empty_store ~(stmt : stmt option) : store = - let limit, merge, flow_actions = match stmt with - | None -> max_int, false, [] - | Some stmt -> slevel stmt, merge stmt, flow_actions stmt + let rationing_parameters, flow_actions = match stmt with + | None -> None, [] + | Some stmt -> + let flow_actions = flow_actions stmt in + (* A skip statement is created on each split annotation: do not ration + states on them to avoid meddling in successive split directives. *) + if Cil.is_skip stmt.skind && flow_actions <> [] + then None, flow_actions + else Some (slevel stmt, merge stmt), flow_actions + in + let rationing = + match rationing_parameters with + | None -> Partition.new_rationing ~limit:max_int ~merge:false + | Some (limit, merge) -> Partition.new_rationing ~limit ~merge + in + let flow_actions = + (Ration rationing) :: Update_dynamic_splits :: flow_actions in - let rationing = Partition.new_rationing ~limit ~merge in { - rationing; flow_actions; + flow_actions; + rationing = rationing_parameters <> None; store_stmt = stmt; store_index = Index.empty (); store_partition = Partition.empty; @@ -106,7 +123,7 @@ struct Partition.iter (fun _key state -> Domain.pretty fmt state) s.store_partition let pretty_flow (fmt : Format.formatter) (flow : flow) = - Flow.iter (Domain.pretty fmt) flow + Flow.iter (fun _ -> Domain.pretty fmt) flow (* Accessors *) @@ -258,50 +275,49 @@ struct let flow_states = List.fold_left Flow.union Flow.empty sources_states in - (* Handle ration stamps *) - dest.incoming_states <- dest.incoming_states + Flow.size flow_states; - let rationing_action = Ration dest.rationing in - (* Handle Split / Merge operations *) - let flow_actions = Update_dynamic_splits :: dest.flow_actions in (* Execute actions *) - let actions = rationing_action :: flow_actions in let flow_states = - List.fold_left Flow.transfer_keys flow_states actions + List.fold_left Flow.transfer_keys flow_states dest.flow_actions in - (* Add states to the store but filter out already propagated states *) - let update key current_state = - (* Inclusion test *) - let state = - try - let previous_state = Partition.find key dest.store_partition in - if Domain.is_included current_state previous_state then - (* The current state is included in the previous; stop *) - None - else begin - (* Propagate the join of the two states *) - if is_loop_head then - Self.feedback ~level:1 ~once:true ~current:true - "starting to merge loop iterations"; - Some (Domain.join previous_state current_state) - end - with - (* There is no previous state, propagate normally *) - Not_found -> Some current_state - in - (* Add the propagated state to the store *) - let add s = - dest.store_partition <- Partition.replace key s dest.store_partition; - in - Option.iter add state; - (* Filter out already propagated states (only at statements). *) - if dest.store_stmt = None - then state - else Extlib.opt_filter (fun s -> Index.add s dest.store_index) state + (* Add the propagated state to the store *) + let add_state key s = + dest.store_partition <- Partition.replace key s dest.store_partition; in - let flow = Flow.join_duplicate_keys flow_states in - let flow = Flow.filter_map update flow in - Option.iter (partitioning_feedback dest flow) dest.store_stmt; - flow + if not (dest.rationing) then begin + Flow.iter add_state flow_states; + flow_states + end else begin + (* Handle ration stamps *) + dest.incoming_states <- dest.incoming_states + Flow.size flow_states; + (* Add states to the store but filter out already propagated states *) + let update key current_state = + (* Inclusion test *) + let state = + try + let previous_state = Partition.find key dest.store_partition in + if Domain.is_included current_state previous_state then + (* The current state is included in the previous; stop *) + None + else begin + (* Propagate the join of the two states *) + if is_loop_head then + Self.feedback ~level:1 ~once:true ~current:true + "starting to merge loop iterations"; + Some (Domain.join previous_state current_state) + end + with + (* There is no previous state, propagate normally *) + Not_found -> Some current_state + in + Option.iter (add_state key) state; + (* Filter out already propagated states. *) + Extlib.opt_filter (fun s -> Index.add s dest.store_index) state + in + let flow = Flow.join_duplicate_keys flow_states in + let flow = Flow.filter_map update flow in + Option.iter (partitioning_feedback dest flow) dest.store_stmt; + flow + end let widen (w : widening) (flow : flow) : flow = let stmt = w.widening_stmt in @@ -336,6 +352,8 @@ struct w.previous_state <- next; w.widened_state <- Some next; w.widening_counter <- widening_period - 1; + w.widening_steps <- w.widening_steps + 1; + Statistics.grow stat_max_widenings stmt w.widening_steps; Some next end with Not_found -> @@ -345,7 +363,9 @@ struct let ws = { widened_state = None; previous_state = curr; - widening_counter = widening_delay - 1; } + widening_counter = widening_delay - 1; + widening_steps = 0 + } in w.widening_partition <- Partition.replace key ws w.widening_partition end; diff --git a/src/plugins/eva/utils/eva_annotations.ml b/src/plugins/eva/utils/eva_annotations.ml index dc8a7b04de93c3339b11c2a6491735cc636c6c9f..8a626416fecf5ab947f5dd52142218fb32d3b535 100644 --- a/src/plugins/eva/utils/eva_annotations.ml +++ b/src/plugins/eva/utils/eva_annotations.ml @@ -62,12 +62,18 @@ type allocation_kind = By_stack | Fresh | Fresh_weak | Imprecise exception Parse_error +(* Where an Eva directive is applied. *) +type kind = + | Here (* The directive is applied when encountered. *) + | Stmt (* The directive has effect on the next statement. *) + | Loop (* The directive concerns a loop. *) + module type Annotation = sig type t val name : string - val is_loop_annot : bool + val kind : kind val parse : typing_context:Logic_typing.typing_context -> lexpr list -> t val export : t -> acsl_extension_kind val import : acsl_extension_kind -> t @@ -87,16 +93,19 @@ struct print fmt (import lp) let () = - if is_loop_annot then - Acsl_extension.register_code_annot_next_loop name typer ~printer false - else - Acsl_extension.register_code_annot_next_stmt name typer ~printer false + let register = + match kind with + | Here -> Acsl_extension.register_code_annot + | Stmt -> Acsl_extension.register_code_annot_next_stmt + | Loop -> Acsl_extension.register_code_annot_next_loop + in + register name typer ~printer false let get stmt = let filter_add _emitter annot acc = match annot.annot_content with - | Cil_types.AExtended (_, is_loop_annot', {ext_name=name'; ext_kind}) - when name' = name && is_loop_annot' = is_loop_annot -> + | Cil_types.AExtended (_, is_loop_annot, {ext_name=name'; ext_kind}) + when name' = name && is_loop_annot = (kind = Loop) -> import ext_kind :: acc | _ -> acc in @@ -106,7 +115,7 @@ struct let loc = Cil_datatype.Stmt.loc stmt in let param = M.export annot in let extension = Logic_const.new_acsl_extension name loc false param in - let annot_node = Cil_types.AExtended ([], is_loop_annot, extension) in + let annot_node = Cil_types.AExtended ([], kind = Loop, extension) in let code_annotation = Logic_const.new_code_annotation annot_node in Annotations.add_code_annot emitter stmt code_annotation end @@ -116,7 +125,7 @@ module Slevel = Register (struct type t = slevel_annotation let name = "slevel" - let is_loop_annot = false + let kind = Here let parse ~typing_context:_ = function | [{lexpr_node = PLvar "default"}] -> SlevelDefault @@ -161,7 +170,7 @@ module Unroll = Register (struct type t = unroll_annotation let name = "unroll" - let is_loop_annot = true + let kind = Loop let parse ~typing_context = function | [] -> UnrollFull @@ -191,6 +200,8 @@ struct when possible, to avoid changes due to its reconversion to a C term. *) type t = split_term * Cil_types.term option + let kind = Here + let term_to_exp = Logic_to_c.term_to_exp ?result:None let parse ~typing_context:context = function @@ -231,19 +242,16 @@ end module Split = Register (struct include SplitTermAnnotation let name = "split" - let is_loop_annot = false end) module Merge = Register (struct include SplitTermAnnotation let name = "merge" - let is_loop_annot = false end) module DynamicSplit = Register (struct include SplitTermAnnotation let name = "dynamic_split" - let is_loop_annot = false end) let get_slevel_annot stmt = @@ -275,7 +283,7 @@ let add_flow_annot ~emitter stmt flow_annotation = module Subdivision = Register (struct type t = int let name = "subdivide" - let is_loop_annot = false + let kind = Stmt let parse ~typing_context:_ = function | [{lexpr_node = PLconstant (IntConstant i)}] -> @@ -316,7 +324,7 @@ module Allocation = struct include Register (struct type t = allocation_kind let name = "eva_allocate" - let is_loop_annot = false + let kind = Stmt let parse ~typing_context:_ = function | [{lexpr_node = PLvar s}] -> Extlib.the ~exn:Parse_error (of_string s) @@ -356,7 +364,7 @@ let get_allocation = Allocation.get module ArraySegmentation = Register (struct type t = Cil_types.varinfo * Cil_types.offset * Cil_types.exp list let name = "array_partition" - let is_loop_annot = false + let kind = Here let convert = function | {term_node = TLval (TVar {lv_origin=Some vi}, toffset)} :: tbounds -> @@ -402,7 +410,7 @@ let read_array_segmentation ext = ArraySegmentation.import ext.ext_kind module DomainScope = Register (struct type t = string * Cil_types.varinfo list let name = "eva_domain_scope" - let is_loop_annot = false + let kind = Here let parse ~typing_context:context = let parse_domain = function diff --git a/src/plugins/eva/utils/eva_utils.ml b/src/plugins/eva/utils/eva_utils.ml index 75d902623d8bce4deb8a0a2bcc8eb28181a5b2c8..7dbc948a1e05968b67aeee3d0ae3c17ccae81c3e 100644 --- a/src/plugins/eva/utils/eva_utils.ml +++ b/src/plugins/eva/utils/eva_utils.ml @@ -138,6 +138,11 @@ let create_new_var name typ = let is_const_write_invalid typ = Cil.typeHasQualifier "const" typ +let find_return_var kf = + match (Kernel_function.find_return kf).skind with + | Return (Some ({enode = Lval ((Var vi, NoOffset))}), _) -> Some vi + | _ | exception Kernel_function.No_Statement -> None + (* Find if a postcondition contains [\result] *) class postconditions_mention_result = object inherit Visitor.frama_c_inplace diff --git a/src/plugins/eva/utils/eva_utils.mli b/src/plugins/eva/utils/eva_utils.mli index 0903cdabad18fdaa60b3c33e59be36f1a4e93f8a..e02e47c866017db14b252a76791b8f7cf046af87 100644 --- a/src/plugins/eva/utils/eva_utils.mli +++ b/src/plugins/eva/utils/eva_utils.mli @@ -72,6 +72,10 @@ val is_const_write_invalid: typ -> bool (** Detect that the type is const, and that option [-global-const] is set. In this case, we forbid writing in a l-value that has this type. *) +val find_return_var: kernel_function -> varinfo option +(** Returns the varinfo returned by the given function. + Returns None if the function returns void or has no return statement. *) + val postconditions_mention_result: Cil_types.funspec -> bool (** Does the post-conditions of this specification mention [\result]? *) @@ -118,6 +122,10 @@ val deps_of_expr: (** Given a function computing the location of lvalues, computes the memory dependencies of an expression. *) +val deps_of_lval: (lval -> Precise_locs.precise_location) -> lval -> deps +(** Given a function computing the location of lvalues, computes the memory + dependencies of an lvalue. *) + (** Computes the height of an expression, that is the maximum number of nested operations in this expression. *) val height_expr: exp -> int diff --git a/src/plugins/eva/utils/statistics.ml b/src/plugins/eva/utils/statistics.ml new file mode 100644 index 0000000000000000000000000000000000000000..508a68db4ad07966275613466a6fd24c6ce5b10a --- /dev/null +++ b/src/plugins/eva/utils/statistics.ml @@ -0,0 +1,212 @@ +(**************************************************************************) +(* *) +(* This file is part of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* 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). *) +(* *) +(**************************************************************************) + +(* Statistics are stored in a dictionary, implemented as an hashtable from + keys to integers. + + [Key] is the representation of the dictionary keys: a couple of a registered + statistic (type ['a t]) accompanied by the function or the statement the stat + is about (type ['a]). + + Statistics must be registered before usage. The registry keeps track of the + registered statistics and allow the reloading of projects by matching the + previous stats to the current ones. +*) + +(* --- Type --- *) + +type _ kind = + | Global : unit kind + | Function : Cil_types.kernel_function kind + | Statement : Cil_types.stmt kind + +type 'a t = { + id: int; + name: string; + kind: 'a kind; +} + + +(* --- Registry --- *) + +type registered_stat = Registered : 'a t -> registered_stat [@@unboxed] + +let kind_to_string : type a. a kind -> string = function + | Global -> "global" + | Function -> "function" + | Statement -> "statement" + +let registry = Hashtbl.create 13 +let last_id = ref 0 + +let register (type a) (name : string) (kind : a kind) : a t = + try + (* If the stat is already registered, return the previous one *) + let Registered stat = Hashtbl.find registry name in + match stat.kind, kind with (* equality must be ensured to return the right type of stat *) + | Global, Global -> stat + | Function, Function -> stat + | Statement, Statement -> stat + | _ -> + Self.fatal + "%s statistic \"%s\" was already registered with as a %s statistic" + name (kind_to_string kind) (kind_to_string stat.kind) + with Not_found -> + (* Otherwise, create a new record for the stat *) + incr last_id; + let stat = { id = !last_id; name; kind } in + Hashtbl.add registry name (Registered stat); + stat + +let register_global_stat name = + register name Global + +let register_function_stat name = + register name Function + +let register_statement_stat name = + register name Statement + + +(* --- Keys --- *) + +type key = Key : 'a t * 'a -> key + +module Key_Datatype = struct + include Datatype.Serializable_undefined + + type t = key + let name = "Statistics.Key" + let rehash (Key (s, x)) = + (Key (register s.name s.kind, x)) + let reprs = [Key ({ id = 0; name="dummy"; kind=Global }, ())] + let equal = Datatype.from_compare + let compare (Key (s1,x1)) (Key (s2,x2)) = + let c = s1.id - s2.id in + if c <> 0 then c else + match s1.kind, s2.kind with + | Global, Global -> 0 + | Function, Function -> Kernel_function.compare x1 x2 + | Statement, Statement -> Cil_datatype.Stmt.compare x1 x2 + | Global, (Function | Statement) -> -1 + | (Function | Statement), Global -> 1 + | Function, Statement -> -1 + | Statement, Function -> 1 + let hash (Key (s,x)) = + let h = match s.kind with + | Global -> 0 + | Function -> Kernel_function.hash x + | Statement -> Cil_datatype.Stmt.hash x + in + Hashtbl.hash (s.id, h) + let copy k = k + let pretty fmt (Key (s,x)) = + match s.kind with + | Global -> + Format.fprintf fmt "%s" s.name + | Function -> + Format.fprintf fmt "%s:%a" s.name Kernel_function.pretty x + | Statement -> + let loc = Cil_datatype.Stmt.loc x in + Format.fprintf fmt "%s:%a" s.name Cil_datatype.Location.pretty loc +end + +module Key = struct + include Datatype.Make_with_collections (Key_Datatype) + + let name (Key (s, _x)) = s.name + + let pretty_kf fmt (Key (s, x)) = + match s.kind with + | Global -> () + | Function -> Kernel_function.pretty fmt x + | Statement -> Kernel_function.(pretty fmt (find_englobing_kf x)) + + let pretty_stmt fmt (Key (s, x)) = + match s.kind with + | Global | Function -> () + | Statement -> Cil_datatype.Location.pretty fmt (Cil_datatype.Stmt.loc x) +end + +(* --- Projectified state --- *) + +module State = + State_builder.Hashtbl + (Key.Hashtbl) + (Datatype.Int) + (struct + let name = "Eva.Statistics.State" + let dependencies = [ Self.state ] + let size = 17 + end) + + +(* --- Statistics update --- *) + +let set (type a) (stat : a t) (x : a) value = + let k = Key (stat,x) in + State.replace k value + +let update (type a) (stat : a t) (x : a) (f : int -> int) = + let k = Key (stat,x) in + State.replace k (f (State.find_opt k |> Option.value ~default:0)) + +let incr (type a) (stat : a t) (x : a) = + update stat x (fun v -> v + 1) + +let grow (type a) (stat : a t) (x : a) value = + update stat x (fun v -> max v value) + +let reset_all () = + State.clear () + + +(* -- Export --- *) + +let export_as_list () = + State.to_seq () |> List.of_seq |> + List.sort (fun (k1,_v1) (k2,_v2) -> Key.compare k1 k2) + +let export_as_csv_to_channel out_channel = + let fmt = Format.formatter_of_out_channel out_channel in + let l = export_as_list () in + let pp_stat fmt (key, value) = + Format.fprintf fmt "%s\t%a\t%a\t%d\n" + (Key.name key) + Key.pretty_kf key + Key.pretty_stmt key + value + in + List.iter (pp_stat fmt) l + +let export_as_csv_to_file filename = + let out_channel = open_out (filename : Filepath.Normalized.t :> string) in + export_as_csv_to_channel out_channel + +let export_as_csv ?filename () = + match filename with + | None -> + if not (Parameters.StatisticsFile.is_empty ()) then + let filename = Parameters.StatisticsFile.get () in + export_as_csv_to_file filename + | Some filename -> + export_as_csv_to_file filename diff --git a/src/plugins/gui/dgraph_helper.no.ml b/src/plugins/eva/utils/statistics.mli similarity index 70% rename from src/plugins/gui/dgraph_helper.no.ml rename to src/plugins/eva/utils/statistics.mli index 14eba81d27164f539ed3a8a2ae3503d340e2db7f..ca402e73218f526d265cf2b19a624bc27910b93a 100644 --- a/src/plugins/gui/dgraph_helper.no.ml +++ b/src/plugins/eva/utils/statistics.mli @@ -20,21 +20,24 @@ (* *) (**************************************************************************) -let window_msg_unavailable () = - let buttons = GWindow.Buttons.ok in - let message_type = `WARNING in - let message = - "Frama-C has not been compiled against a library with \ - working graph visualization. Property dependencies graph can't be shown." - in - let dialog = - GWindow.message_dialog ~buttons ~show:true ~message_type ~message () - in - let callback _ = dialog#destroy () in - ignore (dialog#connect#response ~callback) +type 'a t -let graph_window ~parent:_ ~title:_ _ = - window_msg_unavailable () +(* Register a statistic class *) +val register_global_stat : string -> unit t +val register_function_stat : string -> Cil_types.kernel_function t +val register_statement_stat : string -> Cil_types.stmt t -let graph_window_through_dot ~parent:_ ~title:_ _ = - window_msg_unavailable () +(* Set the stat to the given value *) +val set : 'a t -> 'a -> int -> unit + +(* Adds 1 to the stat or set it to 1 if undefined *) +val incr : 'a t -> 'a -> unit + +(* Set the stat to the maximum between the current value and the given value *) +val grow : 'a t -> 'a -> int -> unit + +(* Reset all statistics to zero *) +val reset_all: unit -> unit + +(* Export the computed statistics as CSV *) +val export_as_csv : ?filename:Filepath.Normalized.t -> unit -> unit diff --git a/src/plugins/gui/GSourceView.3.ml b/src/plugins/gui/GSourceView.ml similarity index 100% rename from src/plugins/gui/GSourceView.3.ml rename to src/plugins/gui/GSourceView.ml diff --git a/src/plugins/gui/GSourceView.3.mli b/src/plugins/gui/GSourceView.mli similarity index 100% rename from src/plugins/gui/GSourceView.3.mli rename to src/plugins/gui/GSourceView.mli diff --git a/src/plugins/gui/debug_manager.ok.ml b/src/plugins/gui/debug_manager.ok.ml deleted file mode 100644 index 94453da44d22430360722bd12ab3d4b41139a4b1..0000000000000000000000000000000000000000 --- a/src/plugins/gui/debug_manager.ok.ml +++ /dev/null @@ -1,79 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2023 *) -(* 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). *) -(* *) -(**************************************************************************) - -(* Require Dgraph included in OCamlgraph/Ocamlgraph_gtk, thus GnomeCanvas *) - -open DGRAPH_MODULE - -let graph_view ~packing mk_dot = - let f = - try Extlib.temp_file_cleanup_at_exit "framac_graph_view" "dot" - with Extlib.Temp_file_error s -> - Gui_parameters.abort "cannot create temporary file: %s" s - in - mk_dot f; - snd - (DGraphContainer.Dot.from_dot_with_commands - ~status:DGraphContainer.Global - ~packing - f) - -let state_dependency_graph ~packing () = - graph_view ~packing State_dependency_graph.dump - -(* [JS 2011/07/05] to be reimplemented *) -let status_dependency_graph ~packing:_ () = assert false -(* let g = Properties_status.Consolidation_tree.get_full_graph () in - graph_view ~packing (Properties_status.Consolidation_tree.dump g)*) - -let graph_window main_window title mk_view = - let height = int_of_float (float main_window#default_height *. 3. /. 4.) in - let width = int_of_float (float main_window#default_width *. 3. /. 4.) in - let window = - GWindow.window ~width ~height ~title ~resizable:true ~position:`CENTER () - in - let view = mk_view ~packing:window#add () in - window#show (); - view#adapt_zoom () - -open Menu_manager - -let () = - Design.register_extension - (fun window -> - let mk_graph = graph_window window#main_window in - ignore - ((window#menu_manager ())#add_debug - ~show:(fun () -> Gui_parameters.debug_atleast 1) - [ (let s = "State Dependency Graph" in - menubar s - (Unit_callback (fun () -> mk_graph s state_dependency_graph))); - (let s = "Status Graph" in - menubar s - (Unit_callback (fun () -> mk_graph s status_dependency_graph))) - ])) - -(* -Local Variables: -compile-command: "make -C ../../.." -End: -*) diff --git a/src/plugins/gui/design.ml b/src/plugins/gui/design.ml index fe652f9a031e25d469d9d157905c5d17c10593bb..d9e13758325b50ceeb393c0d654d61e97542e8bb 100644 --- a/src/plugins/gui/design.ml +++ b/src/plugins/gui/design.ml @@ -854,7 +854,7 @@ class main_window () : main_window_extension_points = width, if final_h then height else new_height in let main_window = - Gtk_compat.window + GWindow.window ?icon:framac_icon ~title:"Frama-C" ~position:`CENTER diff --git a/src/plugins/gui/dune b/src/plugins/gui/dune index aaeb10faf883bcfc3eefb69390af8f4a7328acf7..eb4fd75ad7130dcc2296fab28e96f71f65fc8e59 100644 --- a/src/plugins/gui/dune +++ b/src/plugins/gui/dune @@ -25,9 +25,6 @@ (deps (universe)) (action (progn (echo "GUI:" %{lib-available:frama-c.gui} "\n") - (echo " - lablgtk2:" %{lib-available:lablgtk2} "\n") - (echo " - lablgtk2.gnomecanvas:" %{lib-available:lablgtk2.gnomecanvas} "\n") - (echo " - lablgtk2.sourceview2:" %{lib-available:lablgtk2.sourceview2} "\n") (echo " - lablgtk3:" %{lib-available:lablgtk3} "\n") (echo " - lablgtk3-sourceview3:" %{lib-available:lablgtk3-sourceview3} "\n") ; From a GUI hook registered by RteGen. @@ -42,44 +39,6 @@ (name frama_c_gui) (public_name frama-c.gui) (optional) - (modules - wutil wutil_once widget wbox wfile wpane wpalette wtext wtable - gui_parameters - gtk_helper gtk_form - source_viewer pretty_source source_manager book_manager - warning_manager - filetree - launcher - menu_manager - history - gui_printers - design - analyses_manager file_manager project_manager - help_manager - property_navigator GSourceView gtk_compat - dgraph_helper -) (flags -open Frama_c_kernel -linkall :standard -w -9) - (libraries frama-c.init.gui frama-c.kernel - (select gtk_compat.ml from - (lablgtk3 lablgtk3-sourceview3 -> gtk_compat.3.ml) - (lablgtk2 lablgtk2.gnomecanvas lablgtk2.sourceview2 -> gtk_compat.2.ml) - ) - (select GSourceView.ml from - (lablgtk3 lablgtk3-sourceview3 -> GSourceView.3.ml) - (lablgtk2 lablgtk2.gnomecanvas lablgtk2.sourceview2 -> GSourceView.2.ml) - ) - (select GSourceView.mli from - (lablgtk3 lablgtk3-sourceview3 -> GSourceView.3.mli) - (lablgtk2 lablgtk2.gnomecanvas lablgtk2.sourceview2 -> GSourceView.2.mli) - ) - (select dgraph_helper.ml from - (!lablgtk3-sourceview3 ocamlgraph.dgraph -> dgraph_helper.yes.ml) - ( -> dgraph_helper.no.ml) - ) - (select debug_manager.ml from - (!lablgtk3-sourceview3 ocamlgraph.dgraph -> debug_manager.ok.ml) - ( -> debug_manager.ko.ml) - ) -) + (libraries frama-c.init.gui frama-c.kernel lablgtk3 lablgtk3-sourceview3) ) diff --git a/src/plugins/gui/gtk_compat.2.ml b/src/plugins/gui/gtk_compat.2.ml deleted file mode 100644 index 68b113a4127ca8e9db29b94fc700ef27d1c92856..0000000000000000000000000000000000000000 --- a/src/plugins/gui/gtk_compat.2.ml +++ /dev/null @@ -1,74 +0,0 @@ -(**************************************************************************) -(* *) -(* This file is part of Frama-C. *) -(* *) -(* Copyright (C) 2007-2023 *) -(* 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). *) -(* *) -(**************************************************************************) - -module Pango = struct - open Wutil_once - - let small_font = - once (fun f -> - let f = Pango.Font.copy f in - let s = Pango.Font.get_size f in - Pango.Font.set_size f (s-2) ; f) - - let bold_font = - once (fun f -> - let f = Pango.Font.copy f in - Pango.Font.set_weight f `BOLD ; f) - - let modify_font phi widget = - widget#misc#modify_font (phi widget#misc#pango_context#font_description) - - let set_small_font w = modify_font small_font w - let set_bold_font w = modify_font bold_font w -end - -let get_toolbar_index (toolbar:GButton.toolbar) (item:GButton.tool_item) = - toolbar#get_item_index item - -let window - ?(kind:Gtk.Tags.window_type option) - ?(title:string option) - ?(decorated:bool option) - ?(deletable:bool option) - ?(focus_on_map:bool option) - ?(icon:GdkPixbuf.pixbuf option) - ?(icon_name:string option) - ?(modal:bool option) - ?(position:Gtk.Tags.window_position option) - ?(resizable:bool option) - ?(screen:Gdk.screen option) - ?(type_hint:Gdk.Tags.window_type_hint option) - ?(urgency_hint:bool option) - ?(wmclass:(string * string) option) - ?(border_width:int option) - ?(width:int option) - ?(height:int option) - ?(show:bool option) - () - = - let allow_shrink = resizable in - let allow_grow = resizable in - ignore wmclass; - GWindow.window - ?kind ?title ?decorated ?deletable ?focus_on_map ?icon ?icon_name - ?modal ?position ?resizable ?allow_grow ?allow_shrink ?screen - ?type_hint ?urgency_hint ?border_width ?width ?height ?show () diff --git a/src/plugins/gui/help_manager.ml b/src/plugins/gui/help_manager.ml index 5a9f2a5d04cae97f1fb2b0a96af33e62b3c49efe..d0e1fedf9ea17fd08e0c576e6348fef59e01418b 100644 --- a/src/plugins/gui/help_manager.ml +++ b/src/plugins/gui/help_manager.ml @@ -43,6 +43,7 @@ let show main_ui = "Philippe Herrmann"; "Maxime Jacquemin"; "Florent Kirchner"; + "Alexander Kogtenkov"; "Tristan Le Gall"; "Jean-Christophe Léchenet"; "Matthieu Lemerre"; @@ -63,6 +64,7 @@ let show main_ui = "Armand Puccetti"; "Félix Ridoux"; "Virgile Robles"; + "Jan Rochel"; "Muriel Roger"; "Julien Signoles"; "Nicolas Stouls"; diff --git a/src/plugins/gui/menu_manager.ml b/src/plugins/gui/menu_manager.ml index 86429c985623cbfb393970ba5a5c3a9e4feb21f2..26fc68df230d6d2aaac763921a1e6df2e4553232 100644 --- a/src/plugins/gui/menu_manager.ml +++ b/src/plugins/gui/menu_manager.ml @@ -168,7 +168,7 @@ class menu_manager ?packing (_:Gtk_helper.host) = | None, Some sep -> max 0 - (Gtk_compat.get_toolbar_index toolbar (sep:>GButton.tool_item)) + (toolbar#get_item_index (sep:>GButton.tool_item)#as_tool_item) | Some p, _ -> p) in let toolbar_packing w = diff --git a/src/plugins/gui/property_navigator.ml b/src/plugins/gui/property_navigator.ml index 4423a1d43b266f2f75872708276333c0d06368c0..3f874465f59b47884281ad734ce6e00f19b98259 100644 --- a/src/plugins/gui/property_navigator.ml +++ b/src/plugins/gui/property_navigator.ml @@ -564,16 +564,6 @@ let make_panel (main_ui:main_window_extension_points) = ~headers_visible:true ~packing:sc#add () in - ignore - (view#connect#row_activated - ~callback:(fun path _col -> - match model#custom_get_iter path with - | Some { MODEL.finfo = { ip = ip } } -> - let format_graph ppf = - Consolidation_graph.dump (Consolidation_graph.get ip) ppf in - Dgraph_helper.graph_window_through_dot - ~parent:main_ui#main_window ~title:"Dependencies" format_graph - | None -> ())); view#selection#set_select_function (fun path currently_selected -> if not currently_selected then diff --git a/src/plugins/gui/wutil.ml b/src/plugins/gui/wutil.ml index 995b4af8f4e8d48440e23e439e21c030fa6bf631..e0f404a42ce0d7abf8b4f3dbf3f77fb34dbd5ac5 100644 --- a/src/plugins/gui/wutil.ml +++ b/src/plugins/gui/wutil.ml @@ -32,8 +32,23 @@ let once = Wutil_once.once (* --- Pango Properties --- *) (* -------------------------------------------------------------------------- *) -include Gtk_compat.Pango - +let small_font = + once (fun (f: GPango.font_description) -> + let f = f#copy in + let size = f#size - 2 in + f#modify ~size (); f) + +let bold_font = + once (fun (f: GPango.font_description) -> + let f = f#copy in + let weight = `BOLD in + f#modify ~weight (); f) + +let modify_font phi (widget: #GObj.widget) = + widget#misc#modify_font (phi widget#misc#pango_context#font_description) + +let set_small_font w = modify_font small_font w +let set_bold_font w = modify_font bold_font w let set_font w name = w#misc#modify_font_by_name name let set_monospace w = set_font w "monospace" diff --git a/src/plugins/impact/compute_impact.ml b/src/plugins/impact/compute_impact.ml index 66da42c04b433b1daff3572074ee3a0c0a109373..6f78536af6a6deb3c7e433fab4d0ca57dc01c4f5 100644 --- a/src/plugins/impact/compute_impact.ml +++ b/src/plugins/impact/compute_impact.ml @@ -711,7 +711,7 @@ let skip () = (fun name l -> let vi = try - Base.of_varinfo (Globals.Vars.find_from_astinfo name VGlobal) + Base.of_varinfo (Globals.Vars.find_from_astinfo name Global) with Not_found -> if name = "NULL" then Base.null else diff --git a/src/plugins/impact/gui/register_gui.ml b/src/plugins/impact/gui/register_gui.ml index 2158d07c4c481d2b1b6262117052a26de99687d1..640c23d7428cbb0f2a4283a84be9f1ca947e1284 100644 --- a/src/plugins/impact/gui/register_gui.ml +++ b/src/plugins/impact/gui/register_gui.ml @@ -158,17 +158,6 @@ let impact_highlighter buffer loc ~start ~stop = in apply_on_stmt hilight loc -let reason_graph_window parent ?in_kf reason = - try - let mk_dot_file = Reason_graph.to_dot_formatter ?in_kf reason in - Dgraph_helper.graph_window_through_dot - ~parent ~title:"Impact graph" mk_dot_file - with - | Sys_error _ as exn -> - Options.error "issue when generating impact graph: %s" - (Printexc.to_string exn) - - let impact_statement restrict s = let kf = Kernel_function.find_englobing_kf s in let skip = Compute_impact.skip () in @@ -216,12 +205,6 @@ let impact_statement_ui (main_ui:Design.main_window_extension_points) s = main_ui#rehighlight () ) -let impact_graph_of_function (main_ui:Design.main_window_extension_points) kf = - let g = ReasonGraph.get () in - let open Reason_graph in - if not (Reason.Set.is_empty g.reason_graph) then - reason_graph_window main_ui#main_window ~in_kf:kf g - let pretty_info = ref true let pp_impact_on_inputs (main_ui:Design.main_window_extension_points) kf = @@ -297,14 +280,6 @@ let impact_selector if button = 3 || FollowFocus.get () then ( let callback () = ignore (impact_statement_ui main_ui s) in ignore (popup_factory#add_item "_Impact analysis" ~callback); - if Options.Reason.get ()then begin - let g = ReasonGraph.get () in - if not Reason_graph.(Reason.Set.is_empty g.reason_graph) then begin - let callback () = - reason_graph_window main_ui#main_window ~in_kf:kf g in - ignore (popup_factory#add_item "Impact _graph" ~callback); - end; - end; if FollowFocus.get () then ignore (Glib.Idle.add (fun () -> callback (); false)) ); @@ -328,14 +303,6 @@ let impact_selector let kf = Globals.Functions.get vi in pp_impact_on_inputs main_ui kf; end; - if button = 3 then begin - let g = ReasonGraph.get () in - let open Reason_graph in - if not (Reason.Set.is_empty g.reason_graph) then - let kf = Globals.Functions.get vi in - let callback () = impact_graph_of_function main_ui kf in - ignore (popup_factory#add_item "_Impact graph" ~callback); - end | _ -> () let impact_panel main_ui = diff --git a/src/plugins/instantiate/global_context.ml b/src/plugins/instantiate/global_context.ml index 178fb6d0cb4afe7a79391442f4ea3c2c5e689f75..c48802ba74273d601e294059d137cdd30e98cb7e 100644 --- a/src/plugins/instantiate/global_context.ml +++ b/src/plugins/instantiate/global_context.ml @@ -29,7 +29,7 @@ let axiomatics = Table.create 13 let get_variable name make = if Table.mem varinfos name then Table.find varinfos name else begin - try Globals.Vars.find_from_astinfo name VGlobal + try Globals.Vars.find_from_astinfo name Global with Not_found -> let vi = make () in Table.add varinfos name vi ; diff --git a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif index 8df66b349d84643bc8b6e4ba28cf9e3d3517eee6..1e15a794fc46bf3b502bb9f2a30f7f41ee3db199 100644 --- a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif +++ b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif @@ -7278,8 +7278,8 @@ "startLine": 613, "startColumn": 30, "endLine": 613, - "endColumn": 61, - "byteLength": 31 + "endColumn": 62, + "byteLength": 32 } } } @@ -7746,8 +7746,8 @@ "startLine": 627, "startColumn": 30, "endLine": 627, - "endColumn": 63, - "byteLength": 33 + "endColumn": 64, + "byteLength": 34 } } } diff --git a/src/plugins/server/kernel_ast.ml b/src/plugins/server/kernel_ast.ml index 0cfafb80824a07954033b64b754e8bc9cab341e2..df5fc860bc5bbaad1dc850a7101a8f5cf9797303 100644 --- a/src/plugins/server/kernel_ast.ml +++ b/src/plugins/server/kernel_ast.ml @@ -40,11 +40,16 @@ let () = Request.register ~package let changed_signal = Request.signal ~package ~name:"changed" ~descr:(Md.plain "Emitted when the AST has been changed") +let ast_changed () = Request.emit changed_signal + let ast_update_hook f = - Ast.add_hook_on_update f; - Ast.apply_after_computed (fun _ -> f ()) + begin + Ast.add_hook_on_update f; + Ast.apply_after_computed (fun _ -> f ()); + end -let () = ast_update_hook (fun _ -> Request.emit changed_signal) +let () = ast_update_hook ast_changed +let () = Annotations.add_hook_on_change ast_changed (* -------------------------------------------------------------------------- *) (* --- File Positions --- *) @@ -200,7 +205,8 @@ struct let to_json loc = `String (tag loc) let of_json js = try find (Js.to_string js) - with Not_found -> Data.failure "not a localizable marker" + with Not_found -> + Data.failure "invalid marker (%a)" Json.pp_dump js end @@ -320,6 +326,13 @@ struct | Some vi -> Globals.Functions.mem vi | None -> false + let is_function_pointer = function + | PLval (_, _, (Mem _, NoOffset as lval)) + when Cil.(isFunctionType (typeOfLval lval)) -> true + | PLval (_, _, lval) + when Cil.(isFunPtrType (Cil.typeOfLval lval)) -> true + | _ -> false + let is_fundecl = function | PVDecl(Some _,Kglobal,vi) -> vi.vglob && Globals.Functions.mem vi | _ -> false @@ -377,6 +390,14 @@ struct ~get:(fun (tag, _) -> is_function tag) model + let () = + States.column + ~name:"isFunctionPointer" + ~descr:(Md.plain "Whether it is a function pointer") + ~data:(module Jbool) + ~get:(fun (tag, _) -> is_function_pointer tag) + model + let () = States.column ~name:"isFunDecl" @@ -394,11 +415,15 @@ struct model let () = - States.column + let get (tag, _) = + let pos = fst (Printer_tag.loc_of_localizable tag) in + if Cil_datatype.Position.(equal unknown pos) then None else Some pos + in + States.option ~name:"sloc" ~descr:(Md.plain "Source location") ~data:(module Position) - ~get:(fun (tag, _) -> fst (Printer_tag.loc_of_localizable tag)) + ~get model let array = States.register_array @@ -442,6 +467,7 @@ let () = Request.register ~package let () = Request.register ~package ~kind:`GET ~name:"printFunction" ~descr:(Md.plain "Print the AST of a function") + ~signals:[changed_signal] ~input:(module Function) ~output:(module Jtext) begin fun kf -> let libc = Kernel.PrintLibc.get () in @@ -474,9 +500,9 @@ struct let is_builtin kf = Cil_builtins.is_builtin (Kernel_function.get_vi kf) - let is_stdlib kf = + let is_extern kf = let vi = Kernel_function.get_vi kf in - Cil.is_in_libc vi.vattr + vi.vstorage = Extern let iter f = Globals.Functions.iter @@ -514,13 +540,19 @@ struct ~descr:(Md.plain "Is the function from the Frama-C stdlib?") ~data:(module Data.Jbool) ~default:false - ~get:is_stdlib; + ~get:Kernel_function.is_in_libc; States.column model ~name:"builtin" ~descr:(Md.plain "Is the function a Frama-C builtin?") ~data:(module Data.Jbool) ~default:false ~get:is_builtin; + States.column model + ~name:"extern" + ~descr:(Md.plain "Is the function extern?") + ~data:(module Data.Jbool) + ~default:false + ~get:is_extern; States.column model ~name:"sloc" ~descr:(Md.plain "Source location") diff --git a/src/plugins/server/states.ml b/src/plugins/server/states.ml index 005896b6ed5f566bf0189fb0b60a27e0408f9e7d..00b346c51657caf06acd642c091d0325cce252b5 100644 --- a/src/plugins/server/states.ml +++ b/src/plugins/server/states.ml @@ -22,22 +22,25 @@ open Data +(* -------------------------------------------------------------------------- *) +(* --- Hooks --- *) +(* -------------------------------------------------------------------------- *) + type 'a callback = ('a -> unit) -> unit -let install signal hook = function - | None -> () - | Some add_hook -> - let once = ref true in - let install ok = - if ok && !once then - begin - once := false ; - add_hook hook ; - end - in Request.on_signal signal install - -let install_emit signal add_hook = - install signal (fun _ -> Request.emit signal) add_hook +let install_hook signal hook add_hook = + let once = ref true in + let install ok = + if ok && !once then + begin + once := false ; + add_hook hook ; + Request.emit signal ; + end + in Request.on_signal signal install + +let register_hook signal add_hook = + install_hook signal (fun _ -> Request.emit signal) add_hook (* -------------------------------------------------------------------------- *) (* --- Values --- *) @@ -59,7 +62,7 @@ let register_value (type a) ~package ~name ~descr ~package ~name:(Package.Derived.getter id).name ~descr:(plain "Getter for state" @ href) ~kind:`GET ~input:(module Junit) ~output get in - install_emit signal add_hook ; + Option.iter (register_hook signal) add_hook ; signal (* -------------------------------------------------------------------------- *) @@ -85,7 +88,7 @@ let register_state (type a) ~package ~name ~descr ~package ~name:(Package.Derived.setter id).name ~descr:(plain "Setter for state" @ href) ~kind:`SET ~input:(module D) ~output:(module Junit) set in - install_emit signal add_hook ; + Option.iter (register_hook signal) add_hook ; signal (* -------------------------------------------------------------------------- *) @@ -381,9 +384,9 @@ let register_array ~package ~name ~descr ~key ~kind:`GET ~input:(module Junit) ~output:(module Junit) (fun () -> reload array) ; synchronize array ; - install signal (update array) add_update_hook ; - install signal (remove array) add_remove_hook ; - install signal (fun () -> reload array) add_reload_hook ; + Option.iter (install_hook signal (update array)) add_update_hook ; + Option.iter (install_hook signal (remove array)) add_remove_hook ; + Option.iter (install_hook signal (fun () -> reload array)) add_reload_hook ; array (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/server/states.mli b/src/plugins/server/states.mli index 21d7deb7882939536c0400ccd77354f99f2d6a13..947c2a424edd71367a0c205eabd2d4ac84cf8f35 100644 --- a/src/plugins/server/states.mli +++ b/src/plugins/server/states.mli @@ -26,6 +26,10 @@ open Package type 'a callback = ('a -> unit) -> unit +(** Connect a hook registry to a signal. As soon as the signal is being + traced, a hook to emit the signal is registered. *) +val register_hook : Request.signal -> 'a callback -> unit + (** Register a (projectified) value and generates the associated signal and request: - Signal [<name>.sig] is emitted on value updates; diff --git a/src/plugins/studia/Studia.ml b/src/plugins/studia/Studia.ml index 90b7d6fcb243c3f5b47599b0dd574ee96ede36a4..d7eeebd84a2d6ce4bafe8045e92447f70790eb3d 100644 --- a/src/plugins/studia/Studia.ml +++ b/src/plugins/studia/Studia.ml @@ -28,18 +28,23 @@ include end : sig module Writes: sig + type t = + | Assign of Cil_types.stmt + (** Direct assignment. *) + | CallDirect of Cil_types.stmt + (** Modification by a called leaf function. *) + | CallIndirect of Cil_types.stmt + (** Modification inside the body of a called function. *) + | GlobalInit of Cil_types.varinfo * Cil_types.initinfo + (** Initialization of a global variable. *) + | FormalInit of + Cil_types.varinfo * + (Cil_types.kernel_function * Cil_types.stmt list) list + (** Initialization of a formal parameter, with a list of callsites. *) - (** Given an effect [e], something is directly modified by [e] (through an - affectation, or through a call to a leaf function) if [direct] holds, and - indirectly (through the effects of a call) otherwise. *) - type effects = { - direct: bool (** Direct affectation [lv = ...], or modification through - a call to a leaf function. *); - indirect: bool (** Modification inside the body of called function - [f(...)]*); - } - - val compute: Locations.Zone.t -> (Cil_types.stmt * effects) list + val compare: t -> t -> int + + val compute: Locations.Zone.t -> t list (** [compute z] finds all the statements that modifies [z], and for each statement, indicates whether the modification is direct or indirect. *) @@ -47,8 +52,13 @@ include (** Computations of the statements that read a given memory zone. *) module Reads: sig + type t = + | Direct of Cil_types.stmt + (** Direct read by a statement. *) + | Indirect of Cil_types.stmt + (** Indirect read through a function call. *) - val compute: Locations.Zone.t -> (Cil_types.stmt * Writes.effects) list + val compute: Locations.Zone.t -> t list (** [compute z] finds all the statements that read [z]. The [effects] information indicates whether the read occur on the given statement, or through an inner call for [Call] instructions. *) diff --git a/src/plugins/studia/gui/studia_gui.ml b/src/plugins/studia/gui/studia_gui.ml index cd82d707405d22440dd23cbfd389c5d7c55f63d2..ac71b45402b35c43c9b1dfdcbeb63232a9ce56ca 100644 --- a/src/plugins/studia/gui/studia_gui.ml +++ b/src/plugins/studia/gui/studia_gui.ml @@ -80,7 +80,6 @@ module Kfs_containing_highlighted_stmt = end) let default_icon_name = "gtk-apply" -let default_icon = Datatype.String.Set.singleton default_icon_name module Make_StmtMapState (Info:sig val name: string end) = @@ -140,29 +139,44 @@ struct ^"highlight the statements that reads the location pointed to \ by D at L") - let indirect_icon = Datatype.String.Set.singleton "gtk-jump-to" + let indirect_icon_name = "gtk-jump-to" - let conv l = - let aux acc (stmt, effects) = - let empty = Datatype.String.Set.empty in - let direct = if effects.Writes.direct then default_icon else empty in - let indirect = if effects.Writes.indirect then indirect_icon else empty in - let s = Datatype.String.Set.union direct indirect in - if Datatype.String.Set.is_empty s then acc else Stmt.Map.add stmt s acc + let add_icon map stmt icon = + let update_icons pre = + Some(Datatype.String.Set.(add icon (Option.value ~default:empty pre))) in - List.fold_left aux Stmt.Map.empty l + Stmt.Map.update stmt update_icons map + + let add_read map = function + | Reads.Direct stmt -> add_icon map stmt default_icon_name + | Indirect stmt -> add_icon map stmt indirect_icon_name + + let add_write map = function + | Writes.Assign stmt + | CallDirect stmt -> add_icon map stmt default_icon_name + | CallIndirect stmt -> add_icon map stmt indirect_icon_name + | GlobalInit _ -> map + | FormalInit (_, callsites) -> + let calls = List.flatten (List.map snd callsites) in + List.fold_left + (fun map stmt -> add_icon map stmt default_icon_name) + map + calls let compute op _kf stmt tlv = let t = Logic_const.term (TLval tlv) (Cil.typeOfTermLval tlv) in let z = eval_tlval stmt t in let r, s = match op with - | `Reads -> Reads.compute z, "Reads" - | `Writes -> Writes.compute z, "Writes" + | `Reads -> + List.fold_left add_read Stmt.Map.empty (Reads.compute z), "Reads" + | `Writes -> + List.fold_left add_write Stmt.Map.empty (Writes.compute z), "Writes" in + State.set r; Options.feedback "%s computed" s; - match r with - | [] -> clear (); s ^ " computed; no statement found." - | defs -> State.set (conv defs); s ^ " computed" + if Stmt.Map.is_empty r + then s ^ " computed; no statement found." + else s ^ " computed" let tag_stmt stmt = try diff --git a/src/plugins/studia/reads.ml b/src/plugins/studia/reads.ml index c4920a11f573cc86e3ecbcf648f6cefb80c52ee1..3bebf797fa3bda62c11cf80191be51eec1a06226 100644 --- a/src/plugins/studia/reads.ml +++ b/src/plugins/studia/reads.ml @@ -25,12 +25,15 @@ open Cil_types open Locations -open Writes + +type t = + | Direct of Cil_types.stmt + | Indirect of Cil_types.stmt class find_read zlval = object inherit Visitor.frama_c_inplace - val mutable res = ([] : (stmt * effects) list) + val mutable res : t list = [] method! vstmt_aux stmt = let aux_call lvopt _kf args _loc = @@ -50,7 +53,7 @@ class find_read zlval = object let direct = Zone.intersects deps zlval in (* now determine if the functions called at [stmt] read directly or indirectly [zlval] *) - let aux_kf effects kf = + let aux_kf (direct, indirect) kf = let inputs = !Db.Inputs.get_internal kf in (* TODO: change to this once we can get "full" inputs through Inout. Currently, non operational inputs disappear, and this function @@ -59,18 +62,19 @@ class find_read zlval = object let inputs = inout.Inout_type.over_inputs in *) if Zone.intersects inputs zlval then if Eva.Analysis.use_spec_instead_of_definition kf then - (* Direst, as there is no body for this funtion. *) - { effects with direct = true } + (* Direct, as there is no body for this function. *) + (true, indirect) else - { effects with indirect = true } (* Indirect effect *) + (direct, true) (* Indirect effect *) else - effects (* this function pointer does not read [zlval] *) + (direct, indirect) (* this function pointer does not read [zlval] *) in let kfs = Eva.Results.callee stmt in - let effects = - List.fold_left aux_kf {direct; indirect = false} kfs - in - res <- (stmt, effects) :: res + let direct, indirect = List.fold_left aux_kf (direct, false) kfs in + if direct then + res <- Direct stmt :: res; + if indirect then + res <- Indirect stmt :: res; end in match stmt.skind with @@ -83,13 +87,13 @@ class find_read zlval = object | Instr _ -> let z = !Db.Inputs.statement stmt in if Zone.intersects z zlval then begin - res <- (stmt, {direct = true; indirect = false}) :: res + res <- Direct stmt :: res end; Cil.SkipChildren | If (e, _, _, _) | Switch (e, _, _, _) | Return (Some e, _) -> let z = !Db.Inputs.expr stmt e in if Zone.intersects z zlval then begin - res <- (stmt, {direct = true; indirect = false}) :: res + res <- Direct stmt :: res end; Cil.DoChildren | _ -> Cil.DoChildren diff --git a/src/plugins/studia/reads.mli b/src/plugins/studia/reads.mli index b219e2f283f23ded934c3fe8c3468aa72c32bbcc..e632f51cb9c51a04101e61343b1a6167163b566c 100644 --- a/src/plugins/studia/reads.mli +++ b/src/plugins/studia/reads.mli @@ -22,7 +22,13 @@ (** Computations of the statements that read a given memory zone. *) -val compute: Locations.Zone.t -> (Cil_types.stmt * Writes.effects) list +type t = + | Direct of Cil_types.stmt + (** Direct read by a statement. *) + | Indirect of Cil_types.stmt + (** Indirect read through a function call. *) + +val compute: Locations.Zone.t -> t list (** [compute z] finds all the statements that read [z]. The [effects] information indicates whether the read occur on the given statement, or through an inner call for [Call] instructions. *) diff --git a/src/plugins/studia/studia_request.ml b/src/plugins/studia/studia_request.ml index f657ba818805deb8c6335b6e10a40d68917787a6..f877c39ba0b6db79432de7a162386c5ccd7567f4 100644 --- a/src/plugins/studia/studia_request.ml +++ b/src/plugins/studia/studia_request.ml @@ -63,22 +63,30 @@ module Effects = struct R.to_json end - -type kind = Reads | Writes - -let compute kind zone = - let stmts = match kind with - | Reads -> Reads.compute zone - | Writes -> Writes.compute zone +let compute_writes zone = + let reads = Writes.compute zone in + let add acc = function + | Writes.Assign stmt | CallDirect stmt -> + { acc with direct = stmt :: acc.direct } + | CallIndirect stmt -> + { acc with indirect = stmt :: acc.indirect } + | FormalInit (_vi, callsites) -> + let calls = List.flatten (List.map snd callsites) in + { acc with direct = calls @ acc.direct } + | GlobalInit (_vi, _initinfo) -> + acc (* for now ignore global initializations *) in - let add_if b stmt acc = if b then stmt :: acc else acc in - let add acc (stmt, e) = - let direct = add_if e.Writes.direct stmt acc.direct in - let indirect = add_if e.Writes.indirect stmt acc.indirect in - { direct; indirect } + let empty = { direct = []; indirect = []; } in + List.fold_left add empty reads + +let compute_reads zone = + let reads = Reads.compute zone in + let add acc = function + | Reads.Direct stmt -> { acc with direct = stmt :: acc.direct } + | Indirect stmt -> { acc with indirect = stmt :: acc.indirect } in let empty = { direct = []; indirect = []; } in - List.fold_left add empty stmts + List.fold_left add empty reads let lval_location kinstr lval = Eva.Results.(before_kinstr kinstr |> eval_address lval |> as_zone) @@ -88,11 +96,11 @@ let () = Request.register ~package ~descr:(Markdown.plain "Get the list of statements that read a lval.") ~input:(module Kernel_ast.Lval) ~output:(module Effects) - (fun (kinstr, lval) -> compute Reads (lval_location kinstr lval)) + (fun (kinstr, lval) -> compute_reads (lval_location kinstr lval)) let () = Request.register ~package ~kind:`GET ~name:"getWritesLval" ~descr:(Markdown.plain "Get the list of statements that write a lval.") ~input:(module Kernel_ast.Lval) ~output:(module Effects) - (fun (kinstr, lval) -> compute Writes (lval_location kinstr lval)) + (fun (kinstr, lval) -> compute_writes (lval_location kinstr lval)) diff --git a/src/plugins/studia/writes.ml b/src/plugins/studia/writes.ml index 58e71335ff2ee663684d97c38fdd0f7d2e71a46c..5958368970b0acd176334fff1d5163aecef5a54e 100644 --- a/src/plugins/studia/writes.ml +++ b/src/plugins/studia/writes.ml @@ -28,32 +28,61 @@ open Cil_types open Locations -type effects = { - direct: bool; - indirect: bool; -} +type t = + | Assign of Cil_types.stmt + | CallDirect of Cil_types.stmt + | CallIndirect of Cil_types.stmt + | GlobalInit of Cil_types.varinfo * Cil_types.initinfo + | FormalInit of + Cil_types.varinfo * + (Cil_types.kernel_function * Cil_types.stmt list) list + +let (<?>) c lcmp = + if c <> 0 then c else Lazy.force lcmp + +let compare w1 w2 = + let open Cil_datatype in + let module List = Transitioning.List in + match w1, w2 with + | Assign s1, Assign s2 + | CallDirect s1, CallDirect s2 + | CallIndirect s1, CallIndirect s2 -> Stmt.compare s1 s2 + | GlobalInit (v1, i1), GlobalInit (v2, i2) -> + Varinfo.compare v1 v2 <?> lazy (Initinfo.compare i1 i2) + | FormalInit (v1, cs1), FormalInit (v2, cs2) -> + let compare_callsites (kf1, stmts1) (kf2, stmts2) = + Kf.compare kf1 kf2 <?> lazy (List.compare Stmt.compare stmts1 stmts2) + in + Varinfo.compare v1 v2 <?> lazy (List.compare compare_callsites cs1 cs2) + | Assign _, _ -> 1 + | _, Assign _ -> -1 + | CallDirect _, _ -> 1 + | _, CallDirect _ -> -1 + | CallIndirect _, _ -> 1 + | _, CallIndirect _ -> -1 + | GlobalInit _, _ -> 1 + | _, GlobalInit _ -> -1 (** Does the functions called at [stmt] modify directly or indirectly [zlval] *) let effects_of_call stmt zlval effects = - let aux_kf effects kf = + let aux_kf (direct, indirect) kf = let inout = !Db.Operational_inputs.get_internal_precise ~stmt kf in let out = inout.Inout_type.over_outputs in if Zone.intersects out zlval then if Eva.Analysis.use_spec_instead_of_definition kf then - { effects with direct = true } (* Mark the effect as direct, there is - no body for this funtion. *) + (true, indirect) (* Direct effect: there is no body for this funtion. *) else - { effects with indirect = true } (* Indirect effect *) + (direct, true) (* Indirect effect *) else - effects + (direct, indirect) in let kfs = Eva.Results.callee stmt in List.fold_left aux_kf effects kfs -class find_write zlval = object (self) +class find_write_insts zlval = object (self) inherit Visitor.frama_c_inplace - val mutable res = ([] : (stmt * effects) list) + val mutable res : t list = [] method! vinst i = let stmt = Option.get self#current_stmt in @@ -63,23 +92,24 @@ class find_write zlval = object (self) the call. *) let z = !Db.Outputs.statement stmt in if Zone.intersects z zlval then - let direct_write = match lvopt with + let direct = match lvopt with | None -> false | Some lv -> Eva.Results.(before stmt |> eval_address lv |> as_zone_result) |> Result.fold ~ok:(Zone.intersects zlval) ~error:(fun _ -> false) in - let effects = - effects_of_call stmt zlval {direct = direct_write; indirect =false} - in - res <- (stmt, effects) :: res + let direct, indirect = effects_of_call stmt zlval (direct, false) in + if direct then + res <- CallDirect stmt :: res; + if indirect then + res <- CallIndirect stmt :: res; in match i with | Set _ | Local_init(_, AssignInit _, _) -> (* Effect only throuh the written l-value *) let z = !Db.Outputs.statement stmt in if Zone.intersects z zlval then begin - res <- (stmt, {direct = true; indirect = false}) :: res + res <- Assign stmt :: res end | Call (lvopt, f, args, loc) -> aux_call lvopt f args loc | Local_init(v, ConsInit(f, args, k), l) -> @@ -91,8 +121,8 @@ class find_write zlval = object (self) method result = res end -let compute z = - let vis = new find_write z in +let inst_writes z = + let vis = new find_write_insts z in let aux_kf_fundec kf = let all_out = !Db.Operational_inputs.get_internal_precise kf in let zout = all_out.Inout_type.over_outputs in @@ -107,3 +137,18 @@ let compute z = in Globals.Functions.iter aux_kf; vis#result + +let base_inits base acc = + match Base.to_varinfo base with + | exception Base.Not_a_C_variable -> acc + | vi when vi.vglob -> + let initinfo = Globals.Vars.find vi in + GlobalInit (vi, initinfo) :: acc + | vi when vi.vformal -> + let kf = Option.get (Kernel_function.find_defining_kf vi) in + let callsites = Eva.Results.callsites kf in + FormalInit (vi, callsites) :: acc + | _ -> acc (* Local init will be found by [inst_writes] *) + +let compute z = + inst_writes z @ Zone.fold_bases base_inits z [] diff --git a/src/plugins/studia/writes.mli b/src/plugins/studia/writes.mli index 1e71e184973f09cc4c6798eea0f114ed31ecee4d..8bb6e8bdb9732463f60e92ce9ec39662f4d92d7d 100644 --- a/src/plugins/studia/writes.mli +++ b/src/plugins/studia/writes.mli @@ -22,15 +22,22 @@ (** Computations of the statements that write a given memory zone. *) -(** Given an effect [e], something is directly modified by [e] (through an - affectation, or through a call to a leaf function) if [direct] holds, and - indirectly (through the effects of a call) otherwise. *) -type effects = { - direct: bool (** Direct affectation [lv = ...], or modification through - a call to a leaf function. *); - indirect: bool (** Modification inside the body of called function [f(...)]*); -} +type t = + | Assign of Cil_types.stmt + (** Direct assignment. *) + | CallDirect of Cil_types.stmt + (** Modification by a called leaf function. *) + | CallIndirect of Cil_types.stmt + (** Modification inside the body of a called function. *) + | GlobalInit of Cil_types.varinfo * Cil_types.initinfo + (** Initialization of a global variable. *) + | FormalInit of + Cil_types.varinfo * + (Cil_types.kernel_function * Cil_types.stmt list) list + (** Initialization of a formal parameter, with a list of callsites. *) -val compute: Locations.Zone.t -> (Cil_types.stmt * effects) list +val compare: t -> t -> int + +val compute: Locations.Zone.t -> t list (** [compute z] finds all the statements that modifies [z], and for each statement, indicates whether the modification is direct or indirect. *) diff --git a/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle b/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle index 085bd49daedba21356626eea68d343d1c78c6d25..c490429033d6bee109ace320bcb85741b8b84e64 100644 --- a/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle +++ b/src/plugins/variadic/tests/erroneous/oracle/exec.res.oracle @@ -1,8 +1,8 @@ -[variadic] FRAMAC_SHARE/libc/unistd.h:800: +[variadic] FRAMAC_SHARE/libc/unistd.h:807: Declaration of variadic function execl. -[variadic] FRAMAC_SHARE/libc/unistd.h:805: +[variadic] FRAMAC_SHARE/libc/unistd.h:812: Declaration of variadic function execle. -[variadic] FRAMAC_SHARE/libc/unistd.h:810: +[variadic] FRAMAC_SHARE/libc/unistd.h:817: Declaration of variadic function execlp. [variadic:typing] exec.c:5: Warning: Incorrect type for argument 3. The argument will be cast from int to char *. diff --git a/src/plugins/variadic/tests/known/oracle/exec.res.oracle b/src/plugins/variadic/tests/known/oracle/exec.res.oracle index d8d3c2140b9386b1b0c6a2afaf849ff544614822..f0bfef85da9002bc9642c397b3102812e008369b 100644 --- a/src/plugins/variadic/tests/known/oracle/exec.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/exec.res.oracle @@ -1,8 +1,8 @@ -[variadic] FRAMAC_SHARE/libc/unistd.h:800: +[variadic] FRAMAC_SHARE/libc/unistd.h:807: Declaration of variadic function execl. -[variadic] FRAMAC_SHARE/libc/unistd.h:805: +[variadic] FRAMAC_SHARE/libc/unistd.h:812: Declaration of variadic function execle. -[variadic] FRAMAC_SHARE/libc/unistd.h:810: +[variadic] FRAMAC_SHARE/libc/unistd.h:817: Declaration of variadic function execlp. [variadic] exec.c:9: Translating call to execle to a call to execve. [variadic:typing] exec.c:11: Warning: diff --git a/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle b/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle index 1304870fba51e541b9e5f3b40786a6c0ce6ca7aa..3d9efbe798806b409376f8f17c78a10d34e509c1 100644 --- a/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/exec_failed_requirement.res.oracle @@ -1,8 +1,8 @@ -[variadic] FRAMAC_SHARE/libc/unistd.h:800: +[variadic] FRAMAC_SHARE/libc/unistd.h:807: Declaration of variadic function execl. -[variadic] FRAMAC_SHARE/libc/unistd.h:805: +[variadic] FRAMAC_SHARE/libc/unistd.h:812: Declaration of variadic function execle. -[variadic] FRAMAC_SHARE/libc/unistd.h:810: +[variadic] FRAMAC_SHARE/libc/unistd.h:817: Declaration of variadic function execlp. [variadic] exec_failed_requirement.c:7: Translating call to execl to a call to execv. diff --git a/src/plugins/variadic/tests/known/oracle/printf.res.oracle b/src/plugins/variadic/tests/known/oracle/printf.res.oracle index 7ee761f24d504c42269186b8ff7fffa29191c376..91a4df4a5fabb46de2645a409d2f0f21e0c1f7f7 100644 --- a/src/plugins/variadic/tests/known/oracle/printf.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/printf.res.oracle @@ -509,7 +509,7 @@ int printf_va_21(char const * restrict format, unsigned long param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_22(char const * restrict format, int param0); +int printf_va_22(char const * restrict format, long param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -617,8 +617,8 @@ int main(void) size_t z; ptrdiff_t t; char *string = (char *)"Hello world !\n"; - wchar_t *wstring = L"H" "e" "l" "l" "o" " " "w" "o" "r" "l" "d" " " "!" - "\\n" ; + wchar_t *wstring = (wchar_t *)L"H" "e" "l" "l" "o" " " "w" "o" "r" "l" "d" + " " "!" "\\n" ; char c = (char)'4'; unsigned char uhh = (unsigned char)42; unsigned short uh = (unsigned short)42; @@ -631,7 +631,7 @@ int main(void) uint64_t u64 = 42ul; int8_t i8 = (int8_t)42; uint_least64_t uleast64 = (uint_least64_t)42u; - int_fast32_t ifast32 = 42; + int_fast32_t ifast32 = (int_fast32_t)42; printf("Hello world !\n"); /* printf_va_1 */ printf("%s%n",string,& i); /* printf_va_2 */ printf("%ls",wstring); /* printf_va_3 */ @@ -653,7 +653,7 @@ int main(void) printf("%lu",u64); /* printf_va_19 */ printf("%hhi",(int)i8); /* printf_va_20 */ printf("%lx",uleast64); /* printf_va_21 */ - printf("%d",ifast32); /* printf_va_22 */ + printf("%ld",ifast32); /* printf_va_22 */ printf("%f %Le\n",f,L); /* printf_va_23 */ printf("%c\n",(int)c); /* printf_va_24 */ printf("%p ",(void *)string); /* printf_va_25 */ 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 61261c69b7f3e3af3676c8f2ecadcda889a2b9fa..9a98767e77768581ae88fd9ab8c72c787968a65c 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 @@ -139,7 +139,7 @@ int main(void) short tt; unsigned int ui = (unsigned int)42; char *string = (char *)"foo"; - wchar_t *wstring = L"b" "a" "r" ; + wchar_t *wstring = (wchar_t *)L"b" "a" "r" ; int volatile nondet = 0; switch (nondet) { case 0: printf("%n",(int *)(& tt)); /* 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 3b67607452bdcfe8fa313f2f737c266505abb507..23f119932584c4d6bbed35b7ec4336d082b6d0db 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 @@ -367,7 +367,7 @@ int main(void) f ∈ {42.} ld ∈ {42.} string ∈ {{ "42" }} - rc ∈ {0} + rc ∈ {OK} __retres ∈ {0} /* Generated by Frama-C */ #include "errno.h" diff --git a/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle b/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle index c31c436e505d57cd2728188cdb8bad388f31249d..8af3312245852398624861dd9ce724d859bdcd50 100644 --- a/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/swprintf.res.oracle @@ -105,11 +105,11 @@ int main(void) if (nondet) { size_t tmp; tmp = wcslen((wchar_t const *)(data)); - swprintf(dest,tmp,(wchar_t const *)L"%" "l" "s" ,data); /* swprintf_va_1 */ + swprintf(dest,tmp,L"%" "l" "s" ,data); /* swprintf_va_1 */ /*@ assert \false; */ ; } tmp_0 = wcslen((wchar_t const *)(data)); - swprintf(dest,tmp_0 / (size_t)2,(wchar_t const *)L"%" "l" "s" ,data); /* swprintf_va_2 */ + swprintf(dest,tmp_0 / (size_t)2,L"%" "l" "s" ,data); /* swprintf_va_2 */ __retres = 0; return __retres; } diff --git a/src/plugins/variadic/tests/known/oracle/wchar.res.oracle b/src/plugins/variadic/tests/known/oracle/wchar.res.oracle index f1a366040cbd837b60f664d8e632a2e5128fd36d..2a071e17fd01fd098b3e9d9afa7497d698bf87a0 100644 --- a/src/plugins/variadic/tests/known/oracle/wchar.res.oracle +++ b/src/plugins/variadic/tests/known/oracle/wchar.res.oracle @@ -256,21 +256,20 @@ int main(void) int j; wchar_t input[0x100] = {102, 111, 114, 116, 121, 45, 116, 119, 111, 32, 105, 115, 0}; - wprintf((wchar_t const *)L"%" "d" " " "%" "l" "d" "\\n" ,42,42L); /* wprintf_va_1 */ - wprintf((wchar_t const *)L"%" "1" "0" "d" " " "%" "0" "1" "0" "d" "\\n" , - 42,42); /* wprintf_va_2 */ - wprintf((wchar_t const *)L"%" "d" " " "%" "x" " " "%" "o" " " "%" "#" "x" - " " "%" "#" "o" "\\n" ,42,42u,42u,42u,42u); /* wprintf_va_3 */ - wprintf((wchar_t const *)L"%" "2" "." "1" "f" " " "%" "+" "." "0" "e" " " - "%" "E" "\\n" ,42.0,42.0,42.0); /* wprintf_va_4 */ - wprintf((wchar_t const *)L"%" "*" "d" " " "\\n" ,4,2); /* wprintf_va_5 */ - wprintf((wchar_t const *)L"%" "l" "s" " " "\\n" ,L"4" "2" ); /* wprintf_va_6 */ - swprintf(wstring,(size_t)0x100,(wchar_t const *)L"%" "s" " " "=" " " "%" - "d" ,(char *)L"4" "2" " " "+" " " "4" "2" ,42 + 42); /* swprintf_va_1 */ - wscanf((wchar_t const *)L"%" "l" "s" ,wstring); /* wscanf_va_1 */ - wscanf((wchar_t const *)L"%" "d" " " "%" "d" ,& i,& j); /* wscanf_va_2 */ - swscanf((wchar_t const *)(input),(wchar_t const *)L"%" "l" "s" " " "%" "*" - "s" " " "%" "d" ,wstring,& i); /* swscanf_va_1 */ + wprintf(L"%" "d" " " "%" "l" "d" "\\n" ,42,42L); /* wprintf_va_1 */ + wprintf(L"%" "1" "0" "d" " " "%" "0" "1" "0" "d" "\\n" ,42,42); /* wprintf_va_2 */ + wprintf(L"%" "d" " " "%" "x" " " "%" "o" " " "%" "#" "x" " " "%" "#" "o" + "\\n" ,42,42u,42u,42u,42u); /* wprintf_va_3 */ + wprintf(L"%" "2" "." "1" "f" " " "%" "+" "." "0" "e" " " "%" "E" "\\n" , + 42.0,42.0,42.0); /* wprintf_va_4 */ + wprintf(L"%" "*" "d" " " "\\n" ,4,2); /* wprintf_va_5 */ + wprintf(L"%" "l" "s" " " "\\n" ,(wchar_t *)L"4" "2" ); /* wprintf_va_6 */ + swprintf(wstring,(size_t)0x100,L"%" "s" " " "=" " " "%" "d" ,(char *)L"4" + "2" " " "+" " " "4" "2" ,42 + 42); /* swprintf_va_1 */ + wscanf(L"%" "l" "s" ,wstring); /* wscanf_va_1 */ + wscanf(L"%" "d" " " "%" "d" ,& i,& j); /* wscanf_va_2 */ + swscanf((wchar_t const *)(input),L"%" "l" "s" " " "%" "*" "s" " " "%" "d" , + wstring,& i); /* swscanf_va_1 */ __retres = 0; return __retres; } diff --git a/src/plugins/wp/Auto.ml b/src/plugins/wp/Auto.ml index e22f14b72d75e97409c511be0a785b033adba681..e2e040243ca5d34c14d347c4978dc086ec4fc813 100644 --- a/src/plugins/wp/Auto.ml +++ b/src/plugins/wp/Auto.ml @@ -109,6 +109,7 @@ let intuition = TacNormalForm.strategy let range = TacRange.strategy let split = TacSplit.strategy let definition = TacUnfold.strategy +let compute = TacCompute.strategy let instance = TacInstance.strategy let lemma = TacLemma.strategy diff --git a/src/plugins/wp/Auto.mli b/src/plugins/wp/Auto.mli index b85f8fa008b1ae98a3154ea9d15ce6dd84dfd530..a5329fad4848a4ff9b6c56bd62983aa5fa11d1f1 100644 --- a/src/plugins/wp/Auto.mli +++ b/src/plugins/wp/Auto.mli @@ -43,6 +43,7 @@ val intuition : ?priority:float -> selection -> strategy val range : ?priority:float -> selection -> vmin:int -> vmax:int -> strategy val split : ?priority:float -> selection -> strategy val definition : ?priority:float -> selection -> strategy +val compute : ?priority:float -> selection -> strategy (* -------------------------------------------------------------------------- *) (** {2 Registered Heuristics} *) diff --git a/src/plugins/wp/Cache.ml b/src/plugins/wp/Cache.ml index 6a60e4b06802e14ad3e7e258c436199f8208e917..247f0324a9f2996e9e96ddef70a33970fbd3fd0d 100644 --- a/src/plugins/wp/Cache.ml +++ b/src/plugins/wp/Cache.ml @@ -105,14 +105,6 @@ let parse_mode ~origin ~fallback = function "Unknown %s mode %S (use %s instead)" origin m fallback ; raise Not_found -let mode_name = function - | NoCache -> "none" - | Update -> "update" - | Replay -> "replay" - | Rebuild -> "rebuild" - | Offline -> "offline" - | Cleanup -> "cleanup" - module MODE = WpContext.StaticGenerator(Datatype.Unit) (struct type key = unit @@ -134,7 +126,7 @@ module MODE = WpContext.StaticGenerator(Datatype.Unit) end) let get_mode = MODE.get -let set_mode m = MODE.clear () ; Wp_parameters.Cache.set (mode_name m) +let set_mode m = MODE.set () m let is_active = function | NoCache -> false @@ -145,16 +137,16 @@ let is_updating = function | Update | Rebuild | Cleanup -> true let time_fits time = function - | None | Some 0 -> true - | Some limit -> time <= float limit + | None | Some 0.0 -> true + | Some limit -> time <= limit let steps_fits steps = function | None | Some 0 -> true | Some limit -> steps <= limit let time_seized time = function - | None | Some 0 -> false - | Some limit -> float limit <= time + | None | Some 0.0 -> false + | Some limit -> limit <= time let steps_seized steps steplimit = steps <> 0 && @@ -162,7 +154,7 @@ let steps_seized steps steplimit = | None | Some 0 -> false | Some limit -> limit <= steps -let promote ~timeout ~steplimit (res : VCS.result) = +let promote ?timeout ?steplimit (res : VCS.result) = match res.verdict with | VCS.NoResult | VCS.Computing _ -> VCS.no_result | VCS.Failed -> res @@ -257,7 +249,7 @@ type 'a digest = Why3Provers.t -> 'a -> string type 'a runner = - timeout:int option -> steplimit:int option -> Why3Provers.t -> 'a -> + timeout:float option -> steplimit:int option -> Why3Provers.t -> 'a -> VCS.result Task.task let get_result ~digest ~runner ~timeout ~steplimit prover goal = @@ -273,7 +265,7 @@ let get_result ~digest ~runner ~timeout ~steplimit prover goal = let hash = lazy (digest prover goal) in let result = get_cache_result ~mode hash - |> promote ~timeout ~steplimit |> VCS.cached in + |> promote ?timeout ?steplimit |> VCS.cached in if VCS.is_verdict result then begin diff --git a/src/plugins/wp/Cache.mli b/src/plugins/wp/Cache.mli index 928acecfa3d21d93fc63aec1ef9687d41b2dcae6..5ee0e5deec01408f4c1c2c5e1d9f00b1f33576e3 100644 --- a/src/plugins/wp/Cache.mli +++ b/src/plugins/wp/Cache.mli @@ -38,9 +38,14 @@ val cleanup_cache : unit -> unit type 'a digest = Why3Provers.t -> 'a -> string type 'a runner = - timeout:int option -> steplimit:int option -> Why3Provers.t -> 'a -> + timeout:float option -> steplimit:int option -> Why3Provers.t -> 'a -> VCS.result Task.task +val promote: ?timeout:float -> ?steplimit:int -> VCS.result -> VCS.result +(** Converts some known results to the given limits. + In particular, if the result shall be discarded with respect to the limits, + the function returns [VCS.no_result]. *) + val get_result: digest:('a digest) -> runner:('a runner) -> 'a runner val clear_result: digest:('a digest) -> Why3Provers.t -> 'a -> unit diff --git a/src/plugins/wp/Changelog b/src/plugins/wp/Changelog index 18db349af158e27999facca833c2c08da6111457..e5014c708ca44c9f13901cc81eb4f44c82067707 100644 --- a/src/plugins/wp/Changelog +++ b/src/plugins/wp/Changelog @@ -20,24 +20,46 @@ # <Prover>: prover ############################################################################### -######################## +############################################################################### Plugin WP <next-release> -######################## +############################################################################### + +- WP [2023-06-05] Tactic Compute (new, generalize Definition and Split) +- WP [2023-06-05] Tactic Absurd now also applies to proof goal +- WP [2023-06-05] Option -wp-prop extended to lemma and function names +- TIP [2023-06-05] Activation of Strategies +- WP [2023-06-05] New option -wp-no-strategy-engine to deactivate strategies +- WP [2023-06-05] New option -wp-script=mode (see also -wp-cache-env) +- WP [2023-06-05] New option -wp-status to print unproved goals +- WP [2023-06-05] New option -wp-tactic to search for tactics +- WP [2023-06-05] New option -wp-strategy s,... for default strategies +- WP [2023-06-05] ACSL extension 'strategy' for proof strategies +- WP [2023-06-05] ACSL extension 'proof' for proof resolution hints + +############################################################################### +Plugin WP 27.0 (Cobalt) +############################################################################### +- WP [2023-05-03] new warning against unions (see -wp-warn-key "union") +- WP [2023-04-03] Default timeout set to 2s +- WP [2023-03-29] fix option -wp-split to only split conditions +- WP [2023-03-29] new option -wp-split-switch to split switches +- WP [2023-03-29] new option -wp-split-conj to split conjunctive goals +- WP [2023-03-29] renamed option -wp-split-depth into -wp-split-cnf - WP [2023-03-14] Upgrade to Why3 1.6.0 - WP [2023-02-03] new option -wp-why3-extra-config for providing additional Why3 configuration files -##################### +############################################################################### Plugin WP 26.1 (Iron) -##################### +############################################################################### - WP [2022-12-02] Fixes 'terminates' goals generation when some 'terminates' or 'decreases' clauses are missing. -##################### +############################################################################### Plugin WP 26.0 (Iron) -##################### +############################################################################### - WP [2022-10-14] 'calls' ACSL extension moved into the kernel; option -wp-dynamic marked as obsolete @@ -45,9 +67,9 @@ Plugin WP 26.0 (Iron) - Cmd [2022-07-29] Improves the WP JSON report provided by -wp-report-json -########################## +############################################################################### Plugin WP 25.0 (Manganese) -########################## +############################################################################### - WP [2022-05-06] Upgrade to Why3 1.5 - WP [2022-02-28] New option -wp-fct-timeout, used to customize the @@ -67,9 +89,9 @@ Plugin WP 25.0 (Manganese) split conjunctions into multiple hypotheses. - WP [2021-11-08] Removed legacy WP engine and option -wp-legacy -######################### +############################################################################### Plugin WP 24.0 (Chromium) -######################### +############################################################################### - WP [2021-10-25] Removes -wp-overflows option (unsound) - WP [2021-06-11] Adds an experimental support of "terminates" clauses. @@ -85,15 +107,15 @@ Plugin WP 24.0 (Chromium) option -wp-smoke-dead-assumes - TIP [2021-05-31] Generalized Overflow tactic -######################### +############################################################################### Plugin WP 23.1 (Vanadium) -######################### +############################################################################### - WP [2021-07-15] Fix a crash related to opaque structures memory typing -######################### +############################################################################### Plugin WP 23.0 (Vanadium) -######################### +############################################################################### - WP [2021-03-01] Section « Limitation & Roadmap » added to the WP manual. - WP [2021-03-01] New internal WP engine, fixing many issues related to @@ -109,9 +131,9 @@ Plugin WP 23.0 (Vanadium) - TIP [2020-11-05] New tactic: Induction - WP [2020-11-04] Removed option -wp-bits (now always enabled) -######################### +############################################################################### Plugin WP 22.0 (Titanium) -######################### +############################################################################### - WP [2020-10-14] New warning "pedantic-assigns". WP needs precise 'assigns ... \from ...' specification about out @@ -132,16 +154,16 @@ Plugin WP 22.0 (Titanium) - WP [2020-07-06] New option -wp-cache-print - WP [2020-06-12] Supports the \initialized ACSL predicate -######################### +############################################################################### Plugin WP 21.1 (Scandium) -######################### +############################################################################### -* WP [2020-06-23] Fixes Coq region function -* WP [2020-06-23] Fixes MemTyped structure loader for wp-rte -######################### +############################################################################### Plugin WP 21.0 (Scandium) -######################### +############################################################################### - WP [2020-04-10] Full support for Why3 IEEE float library - WP [2020-04-10] Removed option -wp-check @@ -171,9 +193,9 @@ Plugin WP 21.0 (Scandium) - TIP [2018-02-20] Extends bitwise tactics to dis-equalities - WP [2018-02-18] Additional lemmas about logical shift compositions -########################## +############################################################################### Plugin WP 20.0 (Calcium) -########################## +############################################################################### - TIP [2019-09-17] Using all selected Why-3 provers for proof search - Gui [2019-09-17] Updated panel for provers, models, cache, etc. @@ -198,9 +220,9 @@ Plugin WP 20.0 (Calcium) o Qed [2019-06-27] More secure API for quantifier management - Qed [2019-05-09] Transform (some) boolean quantifications into variable assignments -########################## +############################################################################### Plugin WP 19.0 (Potassium) -########################## +############################################################################### - Wp [2019-05-09] Fixes -wp-simplify-is-cint simplifier - Wp [2019-04-26] Now requires -warn-invalid-bool @@ -226,9 +248,9 @@ Plugin WP 19.0 (Potassium) - Qed [2017-10-27] New simplifications for validity and ranges - TIP [2017-10-27] New tacticals for validity and ranges -###################### +############################################################################### Plugin WP 18.0 (Argon) -###################### +############################################################################### - Wp [2018-10-25] Added support for ACSL \offset construct - Wp [2018-09-04] Option -wp-warn-separation changed into -wp-warn-memory-model @@ -239,9 +261,9 @@ Plugin WP 18.0 (Argon) - Qed [2018-06-20] Added more simplifications for invertible functions - TIP [2018-06-07] Extends tactical 'Split' to distribution of qualitifiers -################################## +############################################################################### Plugin WP 17.0 (Chlorine-20180501) -################################## +############################################################################### - WP [2018-03-08] Add the missing ACSL math builtins (see manual) - WP [2018-02-12] Experimental support for _Bool range (-wp-bool-range) @@ -266,9 +288,9 @@ Plugin WP 17.0 (Chlorine-20180501) - Qed [2017-10-27] New simplifications for validirt and ranges - TIP [2017-10-27] New tacticals for validity and ranges -################################ +############################################################################### Plugin WP 16.0 (Sulfur-20171101) -################################ +############################################################################### - WP [2017-10-18] Support for LoopCurrent and LoopEntry - TIP [2017-04-25] Options -wp-time-{extra|margin} for more stability @@ -286,9 +308,9 @@ Plugin WP 16.0 (Sulfur-20171101) - WP [2017-03-12] Reduction of equalities with logic functions - WP [2017-03-12] More simplifications wrt integer domains -#################################### +############################################################################### Plugin WP 15.0 (Phosphorus-20170501) -#################################### +############################################################################### - Qed [2017-12-13] Transforms some quantifications into let constructs - WP [2017-05-15] Extract inductive predicates as Inductive in Coq @@ -314,9 +336,9 @@ Plugin WP 15.0 (Phosphorus-20170501) - WP [2016-11-17] Warn against access to volatile l-values - WP [2016-11-17] Fix volatile access (see -wp-no-volatile) -################################# +############################################################################### Plugin WP 14.0 (Silicon-20161101) -################################# +############################################################################### - WP [2016-04-08] Unified variable usage for all models - WP [2016-10-06] Simplification of arithmetics models @@ -324,9 +346,9 @@ Plugin WP 14.0 (Silicon-20161101) - WP [2016-10-06] Use cint and cfloat models by default - WP [2016-10-06] Fix -wp-rte with respect to models and kernel options -################################## +############################################################################### Plugin WP 1.0 (Aluminium_20160502) -################################## +############################################################################### - Coq [2016-03-30] Fixed bug #2214 (coq realbase) - WP [2016-03-29] Support for why3 0.87 (and ide) @@ -344,9 +366,9 @@ Plugin WP 1.0 (Aluminium_20160502) - WP [2015-11-19] New options to set prover commands - Coq [2015-11-19] Support for Proof General 4.3 -################################## +############################################################################### Plugin WP 0.9 (Magnesium_20151002) -################################## +############################################################################### - WP [2015-09-02] Added support for float-classification. (\is_NaN, \is_finite, \is_infinite, \is_plus_infinity, \is_minus_infinity). @@ -393,9 +415,9 @@ Plugin WP 0.9 (Magnesium_20151002) - WP [2014-09-24] Now accept patterns in drivers. -* WP [2014-09-15] Fixed bug #1828 (separation of locals/formals/heap). -############################### +############################################################################### Plugin WP 0.8 (Sodium_20150201) -############################### +############################################################################### - WP [2014-09-05] Drivers for min/max. - Typed [2014-09-04] Simplification of assigns and separated. @@ -407,9 +429,9 @@ Plugin WP 0.8 (Sodium_20150201) - Cmd [2014-05-22] Added option -wp-filename-truncation to truncate proof obligation filenames. -############################# +############################################################################### Plugin WP 0.8 (Neon_20140301) -############################# +############################################################################### - Gui [2014-01-30] Edition of current proof script (right-click). - Gui [2014-01-30] Consistent icons with status. @@ -423,18 +445,18 @@ Plugin WP 0.8 (Neon_20140301) - WP [2013-12-09] Clever assigns everything with formals and locals. - WP [2013-11-26] More type constraints in typed memory model. -################################# +############################################################################### Plugin WP 0.7 (Fluorine_20130501) -################################# +############################################################################### -* Typed [2013-05-23] Better trigger generation for arrays with Alt-Ergo. -* Provers [2013-05-23] Fixed various bugs with drivers and provers. -* WP [2013-05-23] Fixed various bugs on floats. -* Typed [2013-05-23] Fixed bug on address differences and offsets. -################################# +############################################################################### Plugin WP 0.7 (Fluorine_20130401) -################################# +############################################################################### -* Makefile [2013-04-17] Fixed bug #1385 about ocamllex.opt. -! Cmd [2013-04-15] Removed now useless options -wp-huge, -wp-dot, @@ -456,9 +478,9 @@ Plugin WP 0.7 (Fluorine_20130401) - WP [2012-10-09] Drivers for linking ACSL symbols to external libs (-wp-driver). -############################### +############################################################################### Plugin WP 0.6 (Oxygen_20120901) -############################### +############################################################################### - WP [2012-09-14] Experimental simplifier with new 'Typed' model (see manual). @@ -479,9 +501,9 @@ o! WP [2012-09-05] Enhanced Ocaml API (see manual). Old bindings - Cmd [2012-02-03] Extended support for external libraries: Options -wp-coq-lib, -wp-why-lib and now -wp-alt-ergo-lib. -################################# +############################################################################### Plugin WP 0.5 (Nitrogen_20111001) -################################# +############################################################################### +* Store [2012-01-03] Adding guard for 'fresh' axiomatization in Store. + WP [2011-12-23] Timing. @@ -492,9 +514,9 @@ Plugin WP 0.5 (Nitrogen_20111001) See options -wp-include, -wp-tactic, -wp-coq-lib and -wp-why-lib. - Cmd [2011-11-21] Adding support for multi-provers in command line. -################################# +############################################################################### Plugin WP 0.4 (Nitrogen_20111001) -################################# +############################################################################### - WP [2011-10-24] Further improvement for proof of assigns clauses. - WP [2011-10-14] A warning is now emitted for missing assigns clauses. @@ -546,9 +568,9 @@ Plugin WP 0.4 (Nitrogen_20111001) -* Gui [2011-04-15] Fixed bug on PO status (wrong PO identification). -* Gui [2011-04-13] Fixed bug #711 (cyclic dependencies). -############################### +############################################################################### Plugin WP 0.3 (Carbon_20110201) -############################### +############################################################################### -* Coq [2011-04-08] Fixed bug #740 for Coq on Windows. WP now uses directly coqtop -compile instead of coqc. @@ -568,18 +590,18 @@ Plugin WP 0.3 (Carbon_20110201) -* Coq [2011-01-04] Fixed bug #702 on Coq output with large integers. -* WP [2011-03-10] Proof of requires of the main entry point (bug #675). -############################### +############################################################################### Plugin WP 0.2 (Carbon_20101202) -############################### +############################################################################### -* Coq [2010-12-16] Fixed bug #639: no more compilation to shared directory. - Gui [2010-12-16] Accessibility of all provers from gui. -############################### +############################################################################### Plugin WP 0.1 (Carbon_20101201) -############################### +############################################################################### - WP [2010-12-06] New WP plugin. -############################# +############################################################################### diff --git a/src/plugins/wp/Cvalues.ml b/src/plugins/wp/Cvalues.ml index ff71b075302ba46fd5682cf37e513a29e6dcb467..bd6fb1e508851b437cc911cb88fea7ac58cfb288 100644 --- a/src/plugins/wp/Cvalues.ml +++ b/src/plugins/wp/Cvalues.ml @@ -127,7 +127,7 @@ and init_comp_value value ci = match ci.cfields with | None -> initialized_value_opaque_comp value ci | Some fields -> - let make f = Cfield (f, KInit), init_value value (object_of f.ftype) in + let make f = cfield ~kind:KInit f, init_value value (object_of f.ftype) in Lang.F.e_record (List.map make fields) let initialized_obj = init_value e_true @@ -249,7 +249,7 @@ struct match c.cfields with | None -> Logic Lang.t_prop | Some fields -> - let value f = e_getfield (e_var s) (Lang.Cfield (f, KValue)) in + let value f = e_getfield (e_var s) (Lang.cfield f) in let def = p_all (fun f -> is_typ f.ftype (value f)) fields in Predicate(Def,def) in { @@ -443,7 +443,7 @@ module EQCOMP = WpContext.Generator(Cil_datatype.Compinfo) | Some fields -> let def = p_all (fun f -> - let fd = Cfield (f, KValue) in + let fd = cfield f in !equal_rec (Ctypes.object_of f.ftype) (e_getfield ra fd) (e_getfield rb fd)) fields diff --git a/src/plugins/wp/Definitions.ml b/src/plugins/wp/Definitions.ml index 9eb47df7d5599e95c15d5a9e1266577b7dacdd08..b0bdacd34142ed670c1c29679e9748331ff321f4 100644 --- a/src/plugins/wp/Definitions.ml +++ b/src/plugins/wp/Definitions.ml @@ -321,7 +321,7 @@ class virtual visitor main = | Some (LTsum cs) -> let cases = List.map (fun c -> - Lang.CTOR c , + Lang.ctor c , List.map self#vtau_of_ltype c.ctor_params ) cs in Qed.Engine.Tsum cases @@ -340,7 +340,7 @@ class virtual visitor main = (List.map (fun f -> let t = Lang.tau_of_ctype f.ftype in - self#vtau t ; Cfield (f, KValue) , t + self#vtau t ; cfield f , t )) r.cfields in self#on_comp r fts ; @@ -358,7 +358,7 @@ class virtual visitor main = (List.map (fun f -> let t = Lang.init_of_ctype f.ftype in - self#vtau t ; Cfield (f, KInit) , t + self#vtau t ; cfield ~kind:KInit f , t )) r.cfields in self#on_icomp r fts ; @@ -462,8 +462,8 @@ class virtual visitor main = begin symbols <- DF.add f symbols ; match f with - | Model { m_source = Extern e } -> self#vlibrary e.ext_library - | Model { m_source = Generated _ } | ACSL _ -> self#vlfun f + | FUN { m_source = Extern e } -> self#vlibrary e.ext_library + | FUN { m_source = Generated _ } | ACSL _ -> self#vlfun f | CTOR c -> self#vadt (Lang.adt c.ctor_type) end diff --git a/src/plugins/wp/Lang.ml b/src/plugins/wp/Lang.ml index c647b8120caaeffa12eeb3b67b128ebb12683499..e136f5b7960e00efa2cff1568f989eeca8077b4b 100644 --- a/src/plugins/wp/Lang.ml +++ b/src/plugins/wp/Lang.ml @@ -225,10 +225,7 @@ let rec tau_of_ltype t = | Ltype _ as b when Logic_const.is_boolean_type b -> Logic.Bool | Ltype(lt,lts) -> atype lt (List.map tau_of_ltype lts) -let tau_of_return l = - match l.l_type with - | None -> Logic.Prop - | Some t -> tau_of_ltype t +let tau_of_return = function None -> Logic.Prop | Some t -> tau_of_ltype t (* -------------------------------------------------------------------------- *) (* --- Datatypes --- *) @@ -311,10 +308,17 @@ let datatype ~library name = let m = new_extern ~link:name ~library ~debug:name in Mtype m + +let field_observers = ref [] +let field_observe fd = List.iter (fun k -> k fd) !field_observers ; fd +let on_field f = field_observers := f :: !field_observers + +let cfield ?(kind=KValue) fd = field_observe @@ Cfield(fd,kind) + let record ~link ~library fts = let m = new_extern ~link ~library ~debug:link in let r = { fields = [] } in - let fs = List.map (fun (f,t) -> Mfield(m,r,f,t)) fts in + let fs = List.map (fun (f,t) -> field_observe @@ Mfield(m,r,f,t)) fts in r.fields <- fs ; Mrecord(m,r) let field t f = @@ -402,10 +406,10 @@ type lfun = (** Registered in Definition.t, only *) | CTOR of Cil_types.logic_ctor_info (** Not registered in Definition.t, directly converted/printed *) - | Model of model + | FUN of lsymbol (** Generated or External function *) -and model = { +and lsymbol = { m_category : lfun category ; m_params : sort list ; m_result : sort ; @@ -418,13 +422,21 @@ and source = | Generated of WpContext.context option * string | Extern of Engine.link extern +let lfun_observers = ref [] +let lfun_observe lf = List.iter (fun k -> k lf) !lfun_observers ; lf +let on_lfun f = lfun_observers := f :: !lfun_observers + +let acsl lf = lfun_observe (ACSL lf) +let ctor cf = lfun_observe (CTOR cf) +let lsymbol m = lfun_observe (FUN m) + let tau_of_lfun phi ts = match phi with - | ACSL f -> tau_of_return f + | ACSL f -> tau_of_return f.l_type | CTOR c -> if c.ctor_type.lt_params = [] then Logic.Data(Atype c.ctor_type,[]) else raise Not_found - | Model m -> match m.m_result with + | FUN m -> match m.m_result with | Sint -> Int | Sreal -> Real | Sbool -> Bool @@ -432,7 +444,7 @@ let tau_of_lfun phi ts = let is_coloring_lfun = function | ACSL _ | CTOR _ -> false - | Model { m_coloring } -> m_coloring + | FUN { m_coloring } -> m_coloring type balance = Nary | Left | Right @@ -481,7 +493,7 @@ let symbolf match result with Some t -> fun _ -> t | None -> not_found in let result = match result with Some t -> Kind.of_tau t | None -> sort in - Model { + lsymbol { m_category = category ; m_params = params ; m_result = result ; @@ -509,7 +521,7 @@ let extern_p ~library ?bool ?prop ?link ?(params=[]) ?(coloring=false) () = | _ , _ , _ -> assert false in let debug = Export.debug link in - Model { + lsymbol { m_category = Logic.Function; m_params = params ; m_result = Logic.Sprop; @@ -522,7 +534,7 @@ let extern_fp ~library ?(params=[]) ?link ?(coloring=false) phi = let link = match link with | None -> Engine.F_call phi | Some link -> Engine.F_call link in - Model { + lsymbol { m_category = Logic.Function ; m_params = params ; m_result = Logic.Sprop; @@ -538,7 +550,7 @@ let generated_f ?context ?category ?params ?sort ?result ?coloring name = symbolf ?context ?category ?params ?sort ?result ?coloring name let generated_p ?context ?(coloring=false) name = - Model { + lsymbol { m_category = Logic.Function ; m_params = [] ; m_result = Logic.Sprop; @@ -558,14 +570,14 @@ struct let debug = function | ACSL f -> logic_id f | CTOR c -> ctor_id c - | Model({m_source=Generated(_,n)}) -> n - | Model({m_source=Extern e}) -> e.ext_debug + | FUN({m_source=Generated(_,n)}) -> n + | FUN({m_source=Extern e}) -> e.ext_debug let hash = function | ACSL f -> Logic_info.hash f | CTOR c -> Logic_ctor_info.hash c - | Model({m_source=Generated(_,n)}) -> Datatype.String.hash n - | Model({m_source=Extern e}) -> e.ext_id + | FUN({m_source=Generated(_,n)}) -> Datatype.String.hash n + | FUN({m_source=Extern e}) -> e.ext_id let compare_context c1 c2 = match c1 , c2 with @@ -587,9 +599,9 @@ struct let compare f g = if f==g then 0 else match f , g with - | Model {m_source=mf} , Model {m_source=mg} -> compare_source mf mg - | Model _ , _ -> (-1) - | _ , Model _ -> 1 + | FUN {m_source=mf} , FUN {m_source=mg} -> compare_source mf mg + | FUN _ , _ -> (-1) + | _ , FUN _ -> 1 | ACSL f , ACSL g -> Logic_info.compare f g | ACSL _ , _ -> (-1) | _ , ACSL _ -> 1 @@ -600,12 +612,12 @@ struct let pretty fmt f = Format.pp_print_string fmt (debug f) let category = function - | Model m -> m.m_category + | FUN m -> m.m_category | ACSL _ -> Logic.Function | CTOR _ -> Logic.Constructor let sort = function - | Model m -> m.m_result + | FUN m -> m.m_result | ACSL { l_type=None } -> Logic.Sprop | ACSL { l_type=Some t } -> sort_of_ltype t | CTOR _ -> Logic.Sdata @@ -613,7 +625,7 @@ struct let parameters = ref (fun _ -> []) let params = function - | Model m -> m.m_params + | FUN m -> m.m_params | CTOR ct -> List.map sort_of_ltype ct.ctor_params | (ACSL _) as f -> !parameters f @@ -642,15 +654,20 @@ class virtual idprinting = method link = function | ACSL f -> Engine.F_call (self#sanitize_fun (logic_id f)) | CTOR c -> Engine.F_call (self#sanitize_fun (ctor_id c)) - | Model({m_source=Generated(_,n)}) -> Engine.F_call (self#sanitize_fun n) - | Model({m_source=Extern e}) -> e.ext_link + | FUN({m_source=Generated(_,n)}) -> Engine.F_call (self#sanitize_fun n) + | FUN({m_source=Extern e}) -> e.ext_link end let name_of_lfun = function | ACSL f -> logic_id f | CTOR c -> ctor_id c - | Model({m_source=Generated(_,f)}) -> f - | Model({m_source=Extern e}) -> e.ext_debug + | FUN({m_source=Generated(_,f)}) -> f + | FUN({m_source=Extern e}) -> e.ext_debug + +let context_of_lfun = function + | ACSL _ | CTOR _ + | FUN({m_source=Extern _}) -> None + | FUN({m_source=Generated(ctxt,_)}) -> ctxt let name_of_field = function | Mfield(_,_,f,_) -> f diff --git a/src/plugins/wp/Lang.mli b/src/plugins/wp/Lang.mli index f39c4ae1d6357125ed4d9ae14637a2295a07db0e..bdb9af7a61b4e6c6f276457c569557b77e7f8a46 100644 --- a/src/plugins/wp/Lang.mli +++ b/src/plugins/wp/Lang.mli @@ -63,21 +63,21 @@ and 'a extern = { ext_debug : string; (** just for printing during debugging *) } and fields = { mutable fields : field list } -and field = +and field = private | Mfield of mdt * fields * string * tau | Cfield of fieldinfo * datakind and tau = (field,adt) Logic.datatype type t_builtin = E_mdt of mdt | E_poly of (tau list -> tau) -type lfun = +type lfun = private | ACSL of Cil_types.logic_info (** Registered in Definition.t, only *) | CTOR of Cil_types.logic_ctor_info (** Not registered in Definition.t directly converted/printed *) - | Model of model (** *) + | FUN of lsymbol (** External or Generated logic symbol *) -and model = { +and lsymbol = { m_category : lfun category ; m_params : sort list ; m_result : sort ; @@ -99,6 +99,7 @@ val record : link:string -> library:string -> (string * tau) list -> adt val comp : compinfo -> adt val comp_init : compinfo -> adt +val cfield : ?kind:datakind -> fieldinfo -> field val field : adt -> string -> field val fields_of_adt : adt -> field list val fields_of_tau : tau -> field list @@ -108,6 +109,12 @@ val adt : logic_type_info -> adt (** Must not be a builtin *) type balance = Nary | Left | Right +val on_lfun : (lfun -> unit) -> unit +val on_field : (field -> unit) -> unit + +val acsl : logic_info -> lfun +val ctor : logic_ctor_info -> lfun + val extern_s : library:library -> ?link:Engine.link -> @@ -158,7 +165,7 @@ val extern_t: val tau_of_object : c_object -> tau val tau_of_ctype : typ -> tau val tau_of_ltype : logic_type -> tau -val tau_of_return : logic_info -> tau +val tau_of_return : logic_type option -> tau val tau_of_lfun : lfun -> tau option list -> tau val tau_of_field : field -> tau val tau_of_record : field -> tau @@ -196,6 +203,8 @@ val parameters : (lfun -> sort list) -> unit val name_of_lfun : lfun -> string val name_of_field : field -> string +val context_of_lfun : lfun -> WpContext.context option +(** LFuns are unique by name and context *) val is_coloring_lfun : lfun -> bool diff --git a/src/plugins/wp/Letify.ml b/src/plugins/wp/Letify.ml index 1a23cd256d121a01b27b912b693a155a9da3de9a..a10eb79cfdbe2c303e8cc99cf505b4caf116a4f7 100644 --- a/src/plugins/wp/Letify.ml +++ b/src/plugins/wp/Letify.ml @@ -68,10 +68,10 @@ struct let frank = function | ACSL _ -> 0 | CTOR _ -> 3 - | Model { m_category = Function } -> 0 - | Model { m_category = Injection } -> 1 - | Model { m_category = Operator _ } -> 2 - | Model { m_category = Constructor } -> 3 + | FUN { m_category = Function } -> 0 + | FUN { m_category = Injection } -> 1 + | FUN { m_category = Operator _ } -> 2 + | FUN { m_category = Constructor } -> 3 let reduce env a b = if F.is_subterm a b then add_sigma env b a else diff --git a/src/plugins/wp/LogicCompiler.ml b/src/plugins/wp/LogicCompiler.ml index 72eaba5ea25c27e4a9b9932edd8aae31a049b090..10eb12ec3c36ea830b2ae1b37c2ec52ffda6d488 100644 --- a/src/plugins/wp/LogicCompiler.ml +++ b/src/plugins/wp/LogicCompiler.ml @@ -428,6 +428,7 @@ struct let occurs_ps x ps = List.exists (F.occursp x) ps let compile_step + (tres: logic_type option) (name:string) (types:string list) (profile:logic_var list) @@ -435,10 +436,11 @@ struct (cc : env -> 'a -> 'b) (filter : 'b -> var -> bool) (data : 'a) - : var list * trigger list * pred list * 'b * sig_param list = + : tau * var list * trigger list * pred list * 'b * sig_param list = let frame = logic_frame name types in in_frame frame begin fun () -> + let tres = Lang.tau_of_return tres in let env,domain,sigv = profile_env Logic_var.Map.empty [] [] profile in let env = default_label env labels in let result = cc env data in @@ -464,7 +466,7 @@ struct (Sigma.domain sigma) acc) frame.labels (parp,sigp) in - parm , frame.triggers , domain , result , sigm + tres, parm , frame.triggers , domain , result , sigm end () let cc_term : (env -> Cil_types.term -> term) ref @@ -505,9 +507,9 @@ struct let compile_lemma cluster name ~kind types labels lemma = let qs,prop = strip_forall [] lemma in - let xs,tgs,domain,prop,_ = + let _,xs,tgs,domain,prop,_ = let cc_pred = pred `Positive in - compile_step name types qs labels cc_pred in_pred prop in + compile_step None name types qs labels cc_pred in_pred prop in let weak = Wp_parameters.WeakIntModel.get () in let lemma = if weak then prop else F.p_hyps domain prop in { @@ -557,48 +559,55 @@ struct (* -------------------------------------------------------------------------- *) let compile_lbpure cluster l = - let lfun = ACSL l in - let tau = Lang.tau_of_return l in - let parp,sigp = Lang.local profile_sig l.l_profile in - let ldef = { - d_lfun = lfun ; - d_types = List.length l.l_tparams ; - d_params = parp ; - d_cluster = cluster ; - d_definition = Logic tau ; - } in - Definitions.update_symbol ldef ; - Signature.update l (SIG sigp) ; - parp,sigp + let frame = logic_frame l.l_var_info.lv_name l.l_tparams in + in_frame frame + begin fun () -> + let lfun = Lang.acsl l in + let tau = Lang.tau_of_return l.l_type in + let parp,sigp = Lang.local profile_sig l.l_profile in + let ldef = { + d_lfun = lfun ; + d_types = List.length l.l_tparams ; + d_params = parp ; + d_cluster = cluster ; + d_definition = Logic tau ; + } in + Definitions.update_symbol ldef ; + Signature.update l (SIG sigp) ; + parp,sigp + end () (* -------------------------------------------------------------------------- *) (* --- Compiling Abstract Logic Function (in axiomatic with no reads) --- *) (* -------------------------------------------------------------------------- *) let compile_lbnone cluster l vars = - let lfun = ACSL l in - let tau = Lang.tau_of_return l in - let parm,sigm = Lang.local (profile_mem l) vars in - let ldef = { - d_lfun = lfun ; - d_types = List.length l.l_tparams ; - d_params = parm ; - d_cluster = cluster ; - d_definition = Logic tau ; - } in - Definitions.define_symbol ldef ; - type_for_signature l ldef sigm ; SIG sigm + let frame = logic_frame l.l_var_info.lv_name l.l_tparams in + in_frame frame + begin fun () -> + let lfun = Lang.acsl l in + let tau = Lang.tau_of_return l.l_type in + let parm,sigm = Lang.local (profile_mem l) vars in + let ldef = { + d_lfun = lfun ; + d_types = List.length l.l_tparams ; + d_params = parm ; + d_cluster = cluster ; + d_definition = Logic tau ; + } in + Definitions.define_symbol ldef ; + type_for_signature l ldef sigm ; SIG sigm + end () (* -------------------------------------------------------------------------- *) (* --- Compiling Logic Function with Reads --- *) (* -------------------------------------------------------------------------- *) let compile_lbreads cluster l ts = - let lfun = ACSL l in + let lfun = Lang.acsl l in let name = l.l_var_info.lv_name in - let tau = Lang.tau_of_return l in - let xs,_,_,(),s = - compile_step name l.l_tparams l.l_profile l.l_labels + let tau,xs,_,_,(),s = + compile_step l.l_type name l.l_tparams l.l_profile l.l_labels reads in_reads ts in let ldef = { @@ -616,15 +625,16 @@ struct (* -------------------------------------------------------------------------- *) let compile_rec name l cc filter data = + let tau = l.l_type in let types = l.l_tparams in let profile = l.l_profile in let labels = l.l_labels in - let result = compile_step name types profile labels cc filter data in + let result = compile_step tau name types profile labels cc filter data in if LogicUsage.is_recursive l then begin - let (_,_,_,_,s) = result in + let (_,_,_,_,_,s) = result in Signature.update l (SIG s) ; - compile_step name types profile labels cc filter data + compile_step tau name types profile labels cc filter data end else result @@ -634,13 +644,12 @@ struct let compile_lbterm cluster l t = let name = l.l_var_info.lv_name in - let tau = Lang.tau_of_return l in - let xs,_,_,r,s = compile_rec name l term in_term t in + let tau,xs,_,_,r,s = compile_rec name l term in_term t in match F.repr r with | Qed.Logic.Kint c -> CST c | _ -> let ldef = { - d_lfun = ACSL l ; + d_lfun = Lang.acsl l ; d_types = List.length l.l_tparams ; d_params = xs ; d_cluster = cluster ; @@ -654,10 +663,10 @@ struct (* -------------------------------------------------------------------------- *) let compile_lbpred cluster l p = - let lfun = ACSL l in + let lfun = Lang.acsl l in let name = l.l_var_info.lv_name in let cc_pred = pred `Positive in - let xs,_,_,r,s = compile_rec name l cc_pred in_pred p in + let _,xs,_,_,r,s = compile_rec name l cc_pred in_pred p in let ldef = { d_lfun = lfun ; d_types = List.length l.l_tparams ; @@ -690,9 +699,9 @@ struct (* Compile cases with default definition and collect used chunks *) let support = List.fold_left (fun support (case,labels,types,lemma) -> - let _,_,_,_,s = + let _,_,_,_,_,s = let cc_pred = pred `Positive in - compile_step case types [] labels cc_pred in_pred lemma in + compile_step l.l_type case types [] labels cc_pred in_pred lemma in let labels_used = LogicUsage.get_induction_labels l case in List.fold_left (heap_case labels_used) support s) Heap.Map.empty cases in @@ -713,7 +722,7 @@ struct support (parp,sigp) ) () in (* Set global Signature *) - let lfun = ACSL l in + let lfun = Lang.acsl l in let ldef = { d_lfun = lfun ; d_types = List.length l.l_tparams ; @@ -770,7 +779,7 @@ struct | { ctor_name = l_name ; ctor_params = ts } as const -> let vs, cs = List.split (List.map term_constraint ts) in let ts = List.map Lang.F.e_var vs in - let const = F.e_fun ~result:tau_lt (CTOR const) ts in + let const = F.e_fun ~result:tau_lt (Lang.ctor const) ts in let is_lt = F.p_call lfun [const] in { l_name ; @@ -918,7 +927,7 @@ struct | CST c -> e_zint c | SIG sparam -> let es = call_params env phi labels sparam parameters in - F.e_fun ~result (ACSL phi) es + F.e_fun ~result (Lang.acsl phi) es let call_pred env (phi:logic_info) @@ -928,7 +937,7 @@ struct | CST _ -> assert false | SIG sparam -> let es = call_params env phi labels sparam parameters in - F.p_call (ACSL phi) es + F.p_call (Lang.acsl phi) es (* -------------------------------------------------------------------------- *) (* --- Variable Bindings --- *) diff --git a/src/plugins/wp/LogicSemantics.ml b/src/plugins/wp/LogicSemantics.ml index 5a97311dcea09458488de9cd8ed397b040c8960d..96baad2451d79132d57ae02a8a6182fc4bd6c0f4 100644 --- a/src/plugins/wp/LogicSemantics.ml +++ b/src/plugins/wp/LogicSemantics.ml @@ -130,7 +130,7 @@ struct | TNoOffset -> v | TModel _ -> Wp_parameters.not_yet_implemented "Model field" | TField(f,offset) -> - let v_f = L.map (fun r -> e_getfield r (Cfield (f, KValue))) v in + let v_f = L.map (fun r -> e_getfield r (cfield f)) v in access_offset env v_f offset | TIndex(k,offset) -> let rk = C.logic env k in @@ -145,9 +145,10 @@ struct | TNoOffset -> v | TModel _ -> Wp_parameters.not_yet_implemented "Model field" | TField(f,offset) -> - let r_f = e_getfield r (Cfield (f, KValue)) in + let fd = cfield f in + let r_f = e_getfield r fd in let r_fv = update_offset env r_f offset v in - e_setfield r (Cfield (f, KValue)) r_fv + e_setfield r fd r_fv | TIndex(k,offset) -> let k = val_of_term env k in let r_kv = update_offset env (e_get r k) offset v in @@ -692,7 +693,7 @@ struct | TDataCons(c,ts) -> let es = List.map (val_of_term env) ts in let r = match LogicBuiltins.ctor c with - | ACSLDEF -> e_fun (CTOR c) es + | ACSLDEF -> e_fun (Lang.ctor c) es | HACK phi -> phi es | LFUN f -> e_fun f es ~result:(Lang.tau_of_ltype t.term_type) in Vexp r diff --git a/src/plugins/wp/MemLoader.ml b/src/plugins/wp/MemLoader.ml index 2b1cbfa0dff61c0c971c1f64e87a0af94c7e3f8a..74ab9a5ba647851441dc579580eedcfcb6e1ae7a 100644 --- a/src/plugins/wp/MemLoader.ml +++ b/src/plugins/wp/MemLoader.ml @@ -277,7 +277,7 @@ struct | Some fields -> let def = List.map (fun f -> - Cfield (f, Info.kind) , + cfield ~kind:Info.kind f, Info.load sigma (object_of f.ftype) (M.field loc f) ) fields in diff --git a/src/plugins/wp/MemMemory.ml b/src/plugins/wp/MemMemory.ml index 75148e0b2ad8c622ce136f1fcd05b141b18c31d9..5db102a4dcf67d0e16f65c803bf4bfe2dc6084ee 100644 --- a/src/plugins/wp/MemMemory.ml +++ b/src/plugins/wp/MemMemory.ml @@ -462,3 +462,15 @@ let separated ~shift ~addrof ~sizeof s1 s2 = r_disjoint (range s1) (range s2) (* -------------------------------------------------------------------------- *) +(* --- Unsupported Unions --- *) +(* -------------------------------------------------------------------------- *) + +let wkey = Wp_parameters.register_warn_category "union" + +let unsupported_union (fd : Cil_types.fieldinfo) = + if not fd.fcomp.cstruct then + Wp_parameters.warning ~once:true ~wkey + "Accessing union fields with WP might be unsound.@\n\ + Please refer to WP manual." + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/MemMemory.mli b/src/plugins/wp/MemMemory.mli index a8ac29bfbbe5aa9fd5a57b8fdc28e3afbd4398d4..094cbb0bdc479fa0e6ced313eafc9449dccf740d 100644 --- a/src/plugins/wp/MemMemory.mli +++ b/src/plugins/wp/MemMemory.mli @@ -134,4 +134,8 @@ val included : sizeof:(Ctypes.c_object -> term) -> 'a Sigs.rloc -> 'a Sigs.rloc -> pred +(** {2 Unsupported Union Fields} *) + +val unsupported_union : Cil_types.fieldinfo -> unit + (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/MemTyped.ml b/src/plugins/wp/MemTyped.ml index 9766ce052c7ec692002da0e7dcd66121f3442c60..c9748c9f908676f3425372043beb8e2961829f91 100644 --- a/src/plugins/wp/MemTyped.ml +++ b/src/plugins/wp/MemTyped.ml @@ -425,7 +425,10 @@ module Shift = WpContext.Generator(Cobj) dfun.d_lfun end) -let field l f = e_fun (ShiftField.get f) [l] +let field l f = + MemMemory.unsupported_union f ; + e_fun (ShiftField.get f) [l] + let shift l obj k = e_fun (Shift.get obj) [l;k] module LITERAL = diff --git a/src/plugins/wp/MemVar.ml b/src/plugins/wp/MemVar.ml index 168c67c9aa0278f6d6fd7378eec05b4ae8394184..4c35bd2787c830e28c7874dbaa7fa31f0b6e48cc 100644 --- a/src/plugins/wp/MemVar.ml +++ b/src/plugins/wp/MemVar.ml @@ -546,6 +546,9 @@ struct | CARR of MemoryContext.validity (* In-context array *) | HEAP (* In-heap variable *) + let is_heap_allocated = function + | CREF | CVAL -> false | HEAP | CTXT _ | CARR _ -> true + type loc = | Ref of varinfo | Val of mem * varinfo * ofs list (* The varinfo has {i not} been contextualized yet *) @@ -713,10 +716,13 @@ struct let pointer_loc p = Loc (M.pointer_loc p) let pointer_val l = M.pointer_val (mloc_of_loc l) - let field l f = match l with + let field l f = + match l with | Loc l -> Loc (M.field l f) | Ref x -> noref ~op:"field access to" x - | Val(m,x,ofs) -> Val(m,x,ofs @ [Field f]) + | Val(m,x,ofs) -> + if not @@ is_heap_allocated m then MemMemory.unsupported_union f ; + Val(m,x,ofs @ [Field f]) let rec ofs_shift obj k = function | [] -> [Shift(obj,k)] @@ -765,7 +771,7 @@ struct let rec access_gen kind a = function | [] -> a - | Field f :: ofs -> access_gen kind (e_getfield a (Cfield (f, kind))) ofs + | Field f :: ofs -> access_gen kind (e_getfield a (cfield ~kind f)) ofs | Shift(_,k) :: ofs -> access_gen kind (e_get a k) ofs let access = access_gen KValue @@ -774,7 +780,7 @@ struct let rec update_gen kind a ofs v = match ofs with | [] -> v | Field f :: ofs -> - let phi = Cfield (f, kind) in + let phi = cfield ~kind f in let a_f = F.e_getfield a phi in let a_f_v = update_gen kind a_f ofs v in F.e_setfield a phi a_f_v @@ -901,9 +907,6 @@ struct exception ShiftMismatch - let is_heap_allocated = function - | CREF | CVAL -> false | HEAP | CTXT _ | CARR _ -> true - let shift_mismatch l = Wp_parameters.fatal "Invalid shift : %a" pretty l @@ -1209,7 +1212,7 @@ struct | TComp({ cfields = Some fields },_) -> F.p_all (fun fd -> - forall_pointers phi (e_getfield v (Cfield (fd, KValue))) fd.ftype) + forall_pointers phi (e_getfield v (cfield fd)) fd.ftype) fields | TArray(elt,_,_) -> let k = Lang.freshvar Qed.Logic.Int in @@ -1319,14 +1322,14 @@ struct (*TODO: optimized version for terminal [Field _] and [Index _] *) | Field f :: ofs -> - let cf = Cfield (f, kind) in + let cf = cfield ~kind f in let af = e_getfield a cf in let bf = e_getfield b cf in let hs = assigned_path kind hs xs ys af bf ofs in List.fold_left (fun hs g -> if Fieldinfo.equal f g then hs else - let cg = Cfield (g, kind) in + let cg = cfield ~kind g in let ag = e_getfield a cg in let bg = e_getfield b cg in let eqg = p_forall ys (p_equal ag bg) in diff --git a/src/plugins/wp/Pattern.ml b/src/plugins/wp/Pattern.ml new file mode 100644 index 0000000000000000000000000000000000000000..469258d7681c616991c174738131752f7d2b7337 --- /dev/null +++ b/src/plugins/wp/Pattern.ml @@ -0,0 +1,767 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* 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 Logic_typing +open Logic_ptree + +(* -------------------------------------------------------------------------- *) +(* --- Pattern Engine --- *) +(* -------------------------------------------------------------------------- *) + +type 'a loc = { loc : location ; value : 'a } + +type pvar = string loc +type ast = node loc +and node = + | Any + | Pany of ast list + | Pvar of pvar + | Named of pvar * ast + | Range of int * int + | Int of Integer.t + | Bool of bool + | String of string + | Assoc of assoc * ast list + | Binop of ast * binop * ast + | Call of string * ast list * bool (* trailing .. *) + | Times of Integer.t * ast + | List of ast list + | Field of ast * string + | Get of ast * ast + | Set of ast * ast * ast +and assoc = [ `Add | `Mul | `Concat | `Land | `Lor | `Lxor ] +and binop = [ `Div | `Mod | `Repeat | `Eq | `Lt | `Le | `Ne | `Lsl | `Lsr ] + +let self p = + let pattern,self = match p.value with + | Named(x,_) | Pvar x -> p , x + | _ -> + let x = { loc = p.loc ; value= "\\target" } in + { loc = p.loc ; value = Named(x,p) } , x + in + pattern , { loc = p.loc ; value = Pvar self } + +let unroll op = function + | { value = Assoc(f,xs) } when f = op -> xs + | e -> [e] + +let assoc op a b = + { + loc = fst a.loc, snd b.loc ; + value = Assoc(op,unroll op a @ unroll op b) ; + } + +let concat ~loc es = + let es = List.map (unroll `Concat) es in + { loc ; value = Assoc(`Concat, List.concat es) } + +module Vmap = Map.Make(String) + +type context = { + typing : typing_context ; + mutable value : bool ; + mutable pvars : pvar Vmap.t ; +} + +type pattern = ast +type value = ast + +(* -------------------------------------------------------------------------- *) +(* --- Node Parsing --- *) +(* -------------------------------------------------------------------------- *) + +let context typing = { typing ; value = false ; pvars = Vmap.empty } + +let pint ctxt ~loc a = + try int_of_string a + with _ -> ctxt.typing.error loc "Invalid int %S" a + +let pinteger ctxt ~loc a = + try Integer.of_string a + with _ -> ctxt.typing.error loc "Invalid integer %S" a + +let pvar ctxt ~loc x = + try Vmap.find x ctxt.pvars with Not_found -> + if ctxt.value then + ctxt.typing.error loc "Unknown pattern variable '%s'" x + else + let pv = { loc ; value = x } in + ctxt.pvars <- Vmap.add x pv ctxt.pvars ; pv + +let pbound ctxt p = + let loc = p.lexpr_loc in + match p.lexpr_node with + | PLconstant (IntConstant a) -> pint ctxt ~loc a + | _ -> ctxt.typing.error loc "Invalid bound (int expected)" + +let rec ptrail rps = function + | [] -> List.rev rps,false + | [{ lexpr_node = PLrange(None,None) }] -> List.rev rps,true + | p::ps -> ptrail (p::rps) ps + +let rec parse ctxt p = + let loc = p.lexpr_loc in + match p.lexpr_node with + | PLvar "_" when not ctxt.value -> { loc ; value = Any } + | PLvar x -> { loc ; value = Pvar (pvar ctxt ~loc x) } + | PLnamed(x,p) -> + let pv = pvar ctxt ~loc x in + let pn = parse ctxt p in + { loc ; value = Named(pv,pn) } + | PLtrue -> { loc ; value = Bool true } + | PLfalse -> { loc ; value = Bool false } + | PLconstant (IntConstant n) -> + { loc ; value = Int (pinteger ctxt ~loc n) } + | PLconstant (StringConstant s) -> + { loc ; value = String s } + | PLrange(Some a,Some b) when not ctxt.value -> + { loc ; value = Range(pbound ctxt a,pbound ctxt b) } + | PLapp("\\any",[],ps) when not ctxt.value -> + { loc ; value = Pany (List.map (parse ctxt) ps) } + | PLapp("\\concat",[],[]) -> { loc ; value = List [] } + | PLapp("\\concat",[],ps) -> concat ~loc @@ List.map (parse ctxt) ps + | PLapp("\\repeat",[],[p;q]) -> parse_binop ctxt ~loc `Repeat p q + | PLapp(lf,[],ps) -> + let ps,trail = if ctxt.value then ps,false else ptrail [] ps in + { loc ; value = Call(lf,List.map (parse ctxt) ps,trail) } + | PLunop(Uminus,a) -> + let a = parse ctxt a in + { loc = a.loc ; value = Times(Integer.minus_one,a) } + | PLunop(Ubw_not,a) -> + let a = parse ctxt a in + { loc = a.loc ; value = Call("lf:lnot",[a],false) } + | PLbinop(a,Bmul,b) -> + let a = parse ctxt a in + let b = parse ctxt b in + begin + match a.value with + | Int k -> { loc ; value = Times(k,b) } + | _ -> assoc `Mul a b + end + | PLbinop(a,Bsub,b) -> + let a = parse ctxt a in + let b = parse ctxt b in + let b = { loc = b.loc ; value = Times(Integer.minus_one,b) } in + assoc `Add a b + | PLbinop(a,Badd,b) -> assoc `Add (parse ctxt a) (parse ctxt b) + | PLbinop(a,Bbw_or,b) -> assoc `Lor (parse ctxt a) (parse ctxt b) + | PLbinop(a,Bbw_and,b) -> assoc `Land (parse ctxt a) (parse ctxt b) + | PLbinop(a,Bbw_xor,b) -> assoc `Lxor (parse ctxt a) (parse ctxt b) + | PLbinop(a,Bdiv,b) -> parse_binop ctxt ~loc `Div a b + | PLbinop(a,Bmod,b) -> parse_binop ctxt ~loc `Mod a b + | PLbinop(a,Blshift,b) -> parse_binop ctxt ~loc `Lsl a b + | PLbinop(a,Brshift,b) -> parse_binop ctxt ~loc `Lsr a b + | PLrel(a,Lt,b) -> parse_binop ctxt ~loc `Lt a b + | PLrel(a,Le,b) -> parse_binop ctxt ~loc `Le a b + | PLrel(a,Gt,b) -> parse_binop ctxt ~loc `Lt b a + | PLrel(a,Ge,b) -> parse_binop ctxt ~loc `Le b a + | PLrel(a,Eq,b) -> parse_binop ctxt ~loc `Eq a b + | PLrel(a,Neq,b) -> parse_binop ctxt ~loc `Ne a b + | PLempty -> { loc ; value = List [] } + | PLlist ps -> { loc ; value = List (List.map (parse ctxt) ps) } + | PLrepeat(p,n) -> parse_binop ctxt ~loc `Repeat p n + | PLdot(a,fd) -> { loc ; value = Field(parse ctxt a,fd) } + | PLarrget(a,b) -> + begin + match b.lexpr_node with + | PLarrget(k,v) -> + { loc ; value = Set(parse ctxt a,parse ctxt k,parse ctxt v) } + | _ -> + { loc ; value = Get(parse ctxt a,parse ctxt b) } + end + | _ -> + ctxt.typing.error loc + (if ctxt.value then "Invalid value" else "Invalid pattern") + +and parse_binop ctxt ~loc op a b = + { loc ; value = Binop(parse ctxt a,op,parse ctxt b) } + +let pa_pattern ctxt p = ctxt.value <- false ; parse ctxt p +let pa_value ctxt p = ctxt.value <- true ; parse ctxt p + +(* -------------------------------------------------------------------------- *) +(* --- Pretty --- *) +(* -------------------------------------------------------------------------- *) + +let rec pp fmt (a : ast) = + match a.value with + | Any -> Format.pp_print_string fmt "_" + | Pvar x -> Format.pp_print_string fmt x.value + | Named (x,v) -> Format.fprintf fmt "%s:%a" x.value pp v + | Range(a,b) -> Format.fprintf fmt "(%d..%d)" a b + | Int n -> Integer.pretty fmt n + | Bool b -> Format.pp_print_string fmt (if b then "\\true" else "\\false") + | String s -> Format.fprintf fmt "%S" s + | Assoc(`Land,[]) -> Format.pp_print_string fmt "-1" + | Assoc(`Mul,[]) -> Format.pp_print_string fmt "1" + | Assoc((`Add|`Lor|`Lxor),[]) -> Format.pp_print_string fmt "0" + | Assoc(`Concat,[]) -> Format.pp_print_string fmt "[| |]" + | Assoc(op,v::vs) -> + let op = match op with + | `Add -> '+' + | `Mul -> '*' + | `Concat | `Lxor -> '^' + | `Land -> '&' + | `Lor -> '|' + in + Format.fprintf fmt "@[<hov 2>(%a" pp v ; + List.iter (Format.fprintf fmt "@ %c %a" op pp) vs ; + Format.fprintf fmt ")@]" + | Binop(a,op,b) -> + let op = match op with + | `Div -> "/" + | `Mod -> "%" + | `Eq -> "==" + | `Ne -> "!=" + | `Lt -> "<" + | `Le -> "<=" + | `Repeat -> "*^" + | `Lsl -> "<<" + | `Lsr -> ">>" + in Format.fprintf fmt "@[<hov 2>(%a@ %s %a)@]" pp a op pp b + | Times(k,v) -> Format.fprintf fmt "%a*%a" Integer.pretty k pp v + | Get(a,k) -> Format.fprintf fmt "@[<hov 2>%a[@,%a]@]" pp a pp k + | Set(a,k,v) -> Format.fprintf fmt "@[<hov 2>%a[@,%a@ -> %a]@]" pp a pp k pp v + | List [] -> Format.pp_print_string fmt "[| |]" + | List (v::vs) -> + Format.fprintf fmt "@[<hov 2>[| %a" pp v ; + List.iter (Format.fprintf fmt " ;@ %a" pp) vs ; + Format.fprintf fmt " |]@]" + | Field(v,id) -> Format.fprintf fmt "%a.%s" pp v id + | Call(id,[],true) -> Format.fprintf fmt "%s(..)" id + | Call(id,[],false) -> Format.fprintf fmt "%s()" id + | Call(id,v::vs,trail) -> + Format.fprintf fmt "@[<hov 2>%s(%a" id pp v ; + List.iter (Format.fprintf fmt ",@ %a" pp) vs ; + if trail then Format.fprintf fmt ",@ .." ; + Format.fprintf fmt ")@]" + | Pany [] -> Format.pp_print_string fmt "\\never" + | Pany (v::vs) -> + Format.fprintf fmt "@[<hov 2>\\any(%a" pp v ; + List.iter (Format.fprintf fmt ",@ %a" pp) vs ; + Format.fprintf fmt ")@]" + +let pp_value = pp +let pp_pattern = pp + +(* -------------------------------------------------------------------------- *) +(* --- Pattern Matching --- *) +(* -------------------------------------------------------------------------- *) + +type sigma = Tactical.selection Vmap.t + +type penv = { + mutable sigma : sigma ; + mutable marked : Lang.F.Tset.t ; + select : Lang.F.term -> Tactical.selection ; +} + +let merge env (x : pvar) e = + try + let s = Vmap.find x.value env.sigma in + let v = Tactical.selected s in + if not (Lang.F.equal v e) then + raise Not_found + with Not_found -> + env.sigma <- Vmap.add x.value (env.select e) env.sigma + +let rec is_any (p : pattern) = + match p.value with + | Any | Pvar _ -> true + | Named(_,q) -> is_any q + | _ -> false + +let rec pmatch env (p : pattern) e = + match p.value , Lang.F.repr e with + | Any , _ -> () + | Pvar x , _ -> merge env x e + | Named(x,p) , _ -> merge env x e ; pmatch env p e + | Range(a,b) , Kint n -> + begin + match Integer.to_int_opt n with + | Some v when a <= v && v <= b -> () + | _ -> raise Not_found + end + | Bool true , True -> () + | Bool false , False -> () + | Assoc(`Add,ps) , Add es -> pac env Lang.F.e_sum [] ps es + | Assoc(`Mul,ps) , Mul es -> pac env Lang.F.e_prod [] ps es + | Assoc(`Lor,ps) , Fun(lf,es) when lf == Cint.f_lor -> + pac env (Lang.F.e_fun lf) [] ps es + | Assoc(`Land,ps) , Fun(lf,es) when lf == Cint.f_land -> + pac env (Lang.F.e_fun lf) [] ps es + | Assoc(`Lxor,ps) , Fun(lf,es) when lf == Cint.f_lxor -> + pac env (Lang.F.e_fun lf) [] ps es + | Binop(p,`Div,q) , Div(a,b) -> pbinop env p q a b + | Binop(p,`Eq,q) , Div(a,b) -> pbinop env p q a b + | Binop(p,`Ne,q) , Div(a,b) -> pbinop env p q a b + | Binop(p,`Lt,q) , Div(a,b) -> pbinop env p q a b + | Binop(p,`Le,q) , Div(a,b) -> pbinop env p q a b + | Binop(p,`Lsl,q) , Fun(lf,[a;b]) when lf == Cint.f_lsl -> pbinop env p q a b + | Binop(p,`Lsr,q) , Fun(lf,[a;b]) when lf == Cint.f_lsr -> pbinop env p q a b + | Times(b,p) , Times(a,e) -> + let q,r = Integer.c_div_rem a b in + if Integer.is_zero r then pmatch env p (Lang.F.e_times q e) + else raise Not_found + | Get(pa,pk) , Aget(a,k) -> + pmatch env pa a ; pmatch env pk k + | Set(pa,pk,pv) , Aset(a,k,v) -> + pmatch env pa a ; pmatch env pk k ; pmatch env pv v + | Field(pv,fid) , Rget(v,fd) when Lang.name_of_field fd = fid -> + pmatch env pv v + | Call(fid,ps,trail) , Fun(lf,es) when Lang.name_of_lfun lf = fid -> + begin + match Lang.Fun.category lf with + | Operator op -> + if op.associative then + let rps = if trail then [{ loc = p.loc ; value = Any }] else [] in + if op.commutative then + pac env (Lang.F.e_fun lf) rps ps es + else + passoc env (Lang.F.e_fun lf) rps ps [] es + else + pargs env ps trail es + | _ -> pargs env ps trail es + end + | Binop(pl,`Repeat,pn) , Fun(lf,[l;n]) when lf == Vlist.f_repeat -> + pmatch env pl l ; pmatch env pn n + | List _vs , _ -> () + | Pany ps , _ -> + let ok = List.exists (fun p -> ptry env p e) ps in + if not ok then raise Not_found + | _ -> raise Not_found + +and pbinop env p q a b = pmatch env p a ; pmatch env q b + +(* Associative matching : + - rps are (reversed) any-patterns to be matched with (reversed) rvs values + - invariant is (rev rps @ ps) being matched with (rev rvs @ vs) *) +and passoc env op rps ps rvs vs = + match ps with + | [] -> pany env op (List.rev rps) (List.rev_append rvs vs) + | p::ps -> + if is_any p then passoc env op (p::rps) ps rvs vs + else + match vs with + | [] -> raise Not_found + | v::vs -> + if ptry env p v then + begin + pany env op (List.rev rps) (List.rev rvs) ; + passoc env op [] ps [] vs + end + else + passoc env op rps ps (v::rvs) vs + +(* AC matching: + - rps are (reversed) any-patterns + - invariant is (rev rs @ ps) being matched with es *) +and pac env op rps ps es = + match ps with + | p::ps -> + if is_any p then pac env op (p::rps) ps es + else + let ep = List.find (ptry env p) es in + let es = List.filter (fun e -> not @@ Lang.F.equal ep e) es in + pac env op rps ps es + | [] -> pany env op (List.rev rps) es + +(* Match with backtracking *) +and ptry env p e = + let s0 = env.sigma in + try pmatch env p e ; true + with Not_found -> env.sigma <- s0 ; false + +(* Matching any-patterns rs with es *) +and pany env op rs es = + match rs , es with + | [] , [] -> () + | rs , [] -> + let e = op [] in + List.iter (fun r -> pmatch env r e) rs + | r::rs , e::es -> pmatch env r e ; pany env op rs es + | [] , _::_ -> raise Not_found + +(* Pairwise matching *) +and pargs env ps trail es = + match ps , es with + | [] , [] -> () + | [] , _ when trail -> () + | p::ps , e::es -> pmatch env p e ; pargs env ps trail es + | _ -> raise Not_found + +(* Deep matching with marking *) +let rec pchildren env p e = + let rs = ref [] in + Lang.F.lc_iter (fun e -> rs := e :: !rs) e ; + List.exists (pchild env p) (List.rev !rs) + +and pchild env p e = + if Lang.F.lc_closed e then + not (Lang.F.Tset.mem e env.marked) && + begin + env.marked <- Lang.F.Tset.add e env.marked ; + ptry env p e || pchildren env p e + end + else + pchildren env p e + +let rec plist f = + function [] -> None | x::xs -> + match f x with + | Some _ as result -> result + | None -> plist f xs + +(* -------------------------------------------------------------------------- *) +(* --- Pattern Lookup --- *) +(* -------------------------------------------------------------------------- *) + +type lookup = { + head: bool ; + goal: bool ; + hyps: bool ; + pattern: pattern ; +} + +let pclause { head ; pattern } clause sigma prop = + let tprop = Lang.F.e_prop prop in + let select t = + if t == tprop then Tactical.Clause clause else Tactical.Inside(clause,t) in + let env = { sigma ; select ; marked = Lang.F.Tset.empty } in + let pcond t = + if ptry env pattern t || (not head && pchildren env pattern t) + then Some env.sigma else None + in + match Lang.F.repr tprop with + | And ts -> plist pcond ts + | _ -> pcond tprop + +(* --- Step Ordering --- *) + +let queue = Queue.create () + +let order (s : Conditions.step) : int = + match s.condition with + | Have _ -> 0 + | When _ -> 1 + | Branch _ -> 2 + | Core _ -> 3 + | Init _ -> 4 + | Type _ -> 5 + | Either _ -> 6 + | State _ -> 7 + +let priority sa sb = order sa - order sb + +let push (step : Conditions.step) = + match step.condition with + | Have _ | When _ | Core _ | Init _ | Type _ | State _ -> () + | Branch(_,sa,sb) -> Queue.push sa queue ; Queue.push sb queue + | Either cs -> List.iter (fun s -> Queue.push s queue) cs + +(* --- Step Matching --- *) + +let pstep ctxt sigma (step : Conditions.step) = + let term = Conditions.head step in + let clause = Tactical.Step step in + pclause ctxt clause sigma term + +(* --- Sequence Matching --- *) + +let rec psequence ctxt sigma (seq : Conditions.sequence) = + let steps = List.sort priority (Conditions.list seq) in + match plist (pstep ctxt sigma) steps with + | Some _ as result -> + Queue.clear queue ; result + | None -> + List.iter push steps ; + if Queue.is_empty queue then None else + psequence ctxt sigma (Queue.pop queue) + +(* --- Hypotheses Matching --- *) + +let phyps ctxt sigma (seq : Conditions.sequent) = + if not ctxt.hyps then None else + psequence ctxt sigma (fst seq) + +let pgoal ctxt sigma (seq : Conditions.sequent) = + if not ctxt.goal then None else + let goal = snd seq in + let clause = Tactical.Goal goal in + pclause ctxt clause sigma goal + +let empty = Vmap.empty + +let psequent ctxt sigma (seq : Conditions.sequent) = + match pgoal ctxt sigma seq with + | Some _ as result -> result + | None -> phyps ctxt sigma seq + +(* -------------------------------------------------------------------------- *) +(* --- Composing Values --- *) +(* -------------------------------------------------------------------------- *) + +let () = Lang.on_lfun + begin fun lf -> + let id = "lf:" ^ Lang.name_of_lfun lf in + Tactical.add_computer id (Lang.F.e_fun lf) + end + +let () = Lang.on_field + begin fun fd -> + let id = "fd:" ^ Lang.name_of_field fd in + Tactical.add_computer id (fun es -> Lang.F.e_getfield (List.hd es) fd) + end + +let error ~loc msg = + Wp_parameters.logwith (fun _evt -> raise Not_found) ~source:(fst loc) msg + +let getvar env (x : string loc) : Tactical.selection = + try Vmap.find x.value env + with Not_found -> + error ~loc:x.loc "Pattern variable '%s' not bound" x.value + +let rec select (env : sigma) (a : value) = + let loc = a.loc in + let cc = select env in + match a.value with + | Any -> error ~loc "Pattern _ is not a value" + | Pany _ -> error ~loc "Pattern \\any(..) is not a value" + | String s -> error ~loc "String %S is not a value" s + | Pvar x -> getvar env x + | Named (_,v) -> cc v + | Range(a,b) -> Tactical.range a b + | Int n -> Tactical.cint n + | Bool b -> Tactical.compose (if b then "wp:true" else "wp:false") [] + | Assoc(op,vs) -> + let op = match op with + | `Add -> "wp:add" + | `Mul -> "wp:mul" + | `Concat -> "wp:concat" + | `Lor -> "lf:lor" + | `Land -> "lf:land" + | `Lxor -> "lf:lxor" + in Tactical.compose op (List.map (cc) vs) + | Binop(a,op,b) -> + let op = match op with + | `Div -> "wp:div" + | `Mod -> "wp:mod" + | `Eq -> "wp:eq" + | `Ne -> "wp:neq" + | `Lt -> "wp:lt" + | `Le -> "wp:leq" + | `Repeat -> "wp:repeat" + | `Lsl -> "lf:lsl" + | `Lsr -> "lf:lsr" + in compose env ~loc op [a;b] + | Times(k,v) -> Tactical.compose "wp:mul" [Tactical.cint k;cc v] + | Get(a,k) -> Tactical.compose "wp:get" [cc a;cc k] + | Set(a,k,v) -> Tactical.compose "wp:set" [cc a;cc k;cc v] + | List vs -> Tactical.compose "wp:list" (List.map cc vs) + | Field(v,id) -> compose env ~loc ("fd:" ^ id) [v] + | Call(id,vs,_) -> compose env ~loc ("lf:" ^ id) vs + +and compose env ~loc id vs = + match Tactical.compose id (List.map (select env) vs) with + | Tactical.Empty -> error ~loc "Computer %S not found" id + | result -> result + +let bool (a : value) = + match a.value with + | Bool b -> b + | _ -> error ~loc:a.loc "Not a boolean value (%a)" pp a + +let string (a : value) = + match a.value with + | String s -> s + | _ -> error ~loc:a.loc "Not a string value (%a)" pp a + +(* -------------------------------------------------------------------------- *) +(* --- Typechecking --- *) +(* -------------------------------------------------------------------------- *) + +type vtype = + | Tnone | Tany | Numerical | Boolean | String + | List of vtype + | Array of vtype * vtype + | Type of Lang.F.tau + +let vint = Type Qed.Logic.Int +let vbool = Type Qed.Logic.Bool +let vlist = List Tany + +let list = function + | Type t -> Type (Vlist.alist t) + | Tnone -> Tnone + | v -> List v + +let array vk ve = + match vk , ve with + | Type tk, Type te -> Type (Qed.Logic.Array(tk,te)) + | Tnone , _ | _ , Tnone -> Tnone + | _ -> Array(vk,ve) + +let rec vmerge va vb = + if va == vb then vb else + match va, vb with + | Tany , v | v, Tany -> v + (* numerical *) + | Numerical, Numerical -> Numerical + | Numerical, Type (Int | Real) -> vb + | Type (Int | Real), Numerical -> va + | Type Int , Type Real -> vb + | Type Real , Type Int -> va + (* boolean *) + | Boolean, Boolean -> Boolean + | Boolean, Type (Bool | Prop) -> vb + | Type (Bool | Prop) , Boolean -> va + | Type Bool , Type Prop -> vb + | Type Prop , Type Bool -> va + (* list *) + | List u , List v -> list (vmerge u v) + | (List m, Type t) | (Type t , List m) -> + begin + match Vlist.elist t with + | None -> Tnone + | Some te -> list (vmerge m (Type te)) + end + (* arrays *) + | Array(vk,ve) , Array(uk,ue) -> + array (vmerge vk uk) (vmerge ve ue) + | (Array(vk,ve) , Type(Array(tk,te))) + | (Type(Array(tk,te)) , Array(vk,ve)) -> + array (vmerge vk (Type tk)) (vmerge ve (Type te)) + (* types *) + | Type ta , Type tb -> if Lang.F.Tau.equal ta tb then vb else Tnone + | _ -> Tnone + +let rec vpretty fmt = function + | Tnone -> Format.fprintf fmt "\\none" + | Tany -> Format.fprintf fmt "\\any" + | List v -> Format.fprintf fmt "\\list(%a)" vpretty v + | Array(vk,ve) -> Format.fprintf fmt "%a[%a]" vpretty vk vpretty ve + | String -> Format.fprintf fmt "string" + | Numerical -> Format.fprintf fmt "number" + | Boolean -> Format.fprintf fmt "boolean" + | Type t -> Lang.F.Tau.pretty fmt t + +type env = vtype Vmap.t ref +let env () = ref Vmap.empty + +let tc_merge ~loc va vb = + let v = vmerge va vb in + if v = Tnone then + Wp_parameters.error ~source:(fst loc) "Invalid type %a (expected %a)" + vpretty va vpretty vb ; v + +let tc_var env ~loc vt x = + let vx = try Vmap.find x !env with Not_found -> Tany in + let vy = tc_merge ~loc vt vx in + if vx != vy then env := Vmap.add x vy !env ; vy + +let rec typecheck env vt (a : ast) = + let loc = a.loc in + match a.value with + | Any -> vt + | Pany ps -> List.fold_left (typecheck env) vt ps + | Pvar x -> tc_var env ~loc vt x.value + | Named(x,v) -> tc_var env ~loc (typecheck env vt v) x.value + | Range(a,b) -> + if a > b then Wp_parameters.error ~source:(fst loc) + "Invalid range %d..%d" a b ; + tc_merge ~loc vt (Type Qed.Logic.Int) + | Int _ -> tc_merge ~loc vt vint + | Bool _ -> tc_merge ~loc vt vbool + | String _ -> tc_merge ~loc vt String + | Assoc((`Lor|`Land|`Lxor),vs) -> + List.fold_left (typecheck env) (tc_merge ~loc vint vt) vs + | Assoc((`Add|`Mul),vs) -> + List.fold_left (typecheck env) (tc_merge ~loc Numerical vt) vs + | Assoc(`Concat,vs) -> + List.fold_left (typecheck env) (tc_merge ~loc vlist vt) vs + | Binop(a,(`Eq | `Ne),b) -> + let va = typecheck env Tany a in + let vb = typecheck env Tany b in + ignore @@ tc_merge ~loc va vb ; + tc_merge ~loc vt Boolean + | Binop(a,(`Lt | `Le),b) -> + let va = typecheck env Numerical a in + let vb = typecheck env Numerical b in + ignore @@ tc_merge ~loc va vb ; + tc_merge ~loc vt Boolean + | Binop(a,`Div,b) -> + let vn = tc_merge ~loc Numerical vt in + let va = typecheck env vn a in + let vb = typecheck env vn b in + tc_merge ~loc va vb + | Binop(a,(`Mod|`Lsl|`Lsr),b) -> + ignore @@ typecheck env vint a ; + ignore @@ typecheck env vint b ; + tc_merge ~loc vt vint + | Binop(a,`Repeat,b) -> + ignore @@ typecheck env vint b ; + typecheck env (tc_merge ~loc vlist vt) a + | Times(_,v) -> typecheck env (tc_merge ~loc Numerical vt) v + | List vs -> + let ve = List.fold_left (typecheck env) Tany vs in + tc_merge ~loc vt (List ve) + | Get(a,k) -> + let vk = typecheck env Tany k in + begin + match typecheck env (Array(vk,vt)) a with + | Array(_,ve) -> ve + | Type(Array(_,te)) -> Type te + | va -> Wp_parameters.error ~source:(fst a.loc) + "Not an array type (%a)" vpretty va ; vt + end + | Set(a,k,v) -> + let vk = typecheck env Tany k in + let ve = typecheck env vt v in + typecheck env (array vk ve) a + | Field(v,fid) -> + begin + match typecheck env Tany v with + | Type(Record fds) -> + begin + try + let (_,ft) = + List.find (fun (fd,_) -> Lang.name_of_field fd = fid) fds in + tc_merge ~loc vt (Type ft) + with Not_found -> vt + end + | Tany -> vt + | vr -> Wp_parameters.error ~source:(fst v.loc) + "Not a record type (%a)" vpretty vr ; vt + end + | Call(_f,vs,_) -> + List.iter (fun v -> ignore @@ typecheck env Tany v) vs ; vt + +let typecheck_vtau env ?tau v = + ignore @@ typecheck env (match tau with None -> Tany | Some t -> Type t) v + +let typecheck_value = typecheck_vtau +let typecheck_pattern = typecheck_vtau + +let typecheck_lookup env p = + ignore @@ typecheck env (if p.head then Boolean else Tany) p.pattern + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/Pattern.mli b/src/plugins/wp/Pattern.mli new file mode 100644 index 0000000000000000000000000000000000000000..750fafc9e30234f1e2ff4d21852c5f5ae4516785 --- /dev/null +++ b/src/plugins/wp/Pattern.mli @@ -0,0 +1,86 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* 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 Logic_typing +open Logic_ptree + +(* -------------------------------------------------------------------------- *) +(* --- Pattern Engine --- *) +(* -------------------------------------------------------------------------- *) + +type context +type pattern +type value + +(** Creates an empty environment *) +val context : typing_context -> context + +(** Parse a pattern and enrich the environement with pattern variables *) +val pa_pattern : context -> lexpr -> pattern + +(** Parse value according to the environement *) +val pa_value : context -> lexpr -> value + +(** Return a value that equals the pattern *) +val self : pattern -> pattern * value + +(** Pattern printer *) +val pp_pattern : Format.formatter -> pattern -> unit + +(** Value printer *) +val pp_value : Format.formatter -> value -> unit + +(** Matching lookup *) +type lookup = { + head: bool ; + goal: bool ; + hyps: bool ; + pattern: pattern ; +} + +(** Matching result *) +type sigma + +(** Empty results *) +val empty : sigma + +(** Matching sequent *) +val psequent : lookup -> sigma -> Conditions.sequent -> sigma option + +(** Composing values from matching results *) +val select : sigma -> value -> Tactical.selection + +(** Composing a boolean *) +val bool : value -> bool + +(** Composing a string *) +val string : value -> string + +(** Typechecking *) + +type env +val env : unit -> env +val typecheck_value : env -> ?tau:Lang.F.tau -> value -> unit +val typecheck_pattern : env -> ?tau:Lang.F.tau -> pattern -> unit +val typecheck_lookup : env -> lookup -> unit + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/ProofEngine.ml b/src/plugins/wp/ProofEngine.ml index b8c5854a739645e686cf7a00456dcb174a65088e..9c96cffeb933d00724f249fe6dcf618b91faa4f4 100644 --- a/src/plugins/wp/ProofEngine.ml +++ b/src/plugins/wp/ProofEngine.ml @@ -30,6 +30,7 @@ type node = { parent : node option ; mutable script : script ; mutable stats : Stats.stats ; + mutable strategy : string option ; (* hint *) mutable search_index : int ; mutable search_space : Strategy.t array ; (* sorted by priority *) } @@ -107,6 +108,7 @@ let proof ~main = let rec reset_node n = Wpo.clear_results n.goal ; if Wpo.is_tactic n.goal then Wpo.remove n.goal ; + n.strategy <- None ; match n.script with | Opened | Script _ -> () | Tactic(_,children) -> @@ -146,6 +148,11 @@ let iteri f tree = let k = ref 0 in walk (fun node -> f !k node ; incr k) r +let rec depth node = + match node.parent with + | None -> 0 + | Some p -> succ @@ depth p + (* -------------------------------------------------------------------------- *) (* --- Consolidating --- *) (* -------------------------------------------------------------------------- *) @@ -193,7 +200,8 @@ let consolidated wpo = (* -------------------------------------------------------------------------- *) let main t = t.main -let head t = match t.head with +let head t = t.head +let head_goal t = match t.head with | None -> t.main | Some n -> n.goal let tree n = proof ~main:n.tree @@ -335,6 +343,7 @@ let mk_tree_node ~tree ~anchor goal = { stats = Stats.empty ; search_index = 0 ; search_space = [| |] ; + strategy = None ; } let mk_root_node goal = { @@ -342,6 +351,7 @@ let mk_root_node goal = { parent = None ; script = Opened ; stats = Stats.empty ; + strategy = None ; search_index = 0 ; search_space = [| |] ; } @@ -452,4 +462,7 @@ let bound node = | Tactic _ | Opened -> [] | Script s -> s +let get_hint node = node.strategy +let set_hint node strategy = node.strategy <- Some strategy + (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/ProofEngine.mli b/src/plugins/wp/ProofEngine.mli index 4e0cd3d9f627b3ce66fa7b8174633baae4d523d6..5fdb346c81be8070ef5fb335450a5a36d9c04788 100644 --- a/src/plugins/wp/ProofEngine.mli +++ b/src/plugins/wp/ProofEngine.mli @@ -72,9 +72,10 @@ val current : tree -> current val goto : tree -> position -> unit val root : tree -> node val main : tree -> Wpo.t -val head : tree -> Wpo.t -val tree : node -> tree val goal : node -> Wpo.t +val tree : node -> tree +val head : tree -> node option +val head_goal : tree -> Wpo.t val tree_context : tree -> WpContext.t val node_context : node -> WpContext.t @@ -83,10 +84,14 @@ val proved : node -> bool val pending : node -> int val stats : node -> Stats.stats val parent : node -> node option +val depth : node -> int val children : node -> (string * node) list val tactical : node -> ProofScript.jtactic option val get_strategies : node -> int * Strategy.t array (* current index *) val set_strategies : node -> ?index:int -> Strategy.t array -> unit +val get_hint : node -> string option +val set_hint : node -> string -> unit + val forward : tree -> unit val cancel : tree -> unit val remove : tree -> node -> unit diff --git a/src/plugins/wp/ProofScript.ml b/src/plugins/wp/ProofScript.ml index dfb26837dc05d9782e81d8f885c6bb9f75a52920..a654b1f42123ab5f1fd26f30cb158de1e4e75766 100644 --- a/src/plugins/wp/ProofScript.ml +++ b/src/plugins/wp/ProofScript.ml @@ -278,24 +278,32 @@ type jtactic = { tactic : string ; params : Json.t ; select : Json.t ; + strategy : string option ; } -let jtactic ~title (tac : tactical) (sel : selection) = +let jtactic ?strategy (tac : tactical) (sel : selection) = { - header = title ; + header = tac#title ; tactic = tac#id ; params = json_of_parameters tac ; select = json_of_selection sel ; + strategy ; } let json_of_tactic t js = - `Assoc [ + let strategy = + match t.strategy with + | None -> [] + | Some s -> [ "strategy" , `String s ] + in + let tactical = [ "header" , `String t.header ; "tactic" , `String t.tactic ; "params" , t.params ; "select" , t.select ; "children" , `Assoc js ; - ] + ] in + `Assoc (strategy @ tactical) let children_of_json = function | `List js -> @@ -311,8 +319,11 @@ let tactic_of_json js = let tactic = js >? "tactic" |> Json.string in let params = try js >? "params" with Not_found -> `Null in let select = try js >? "select" with Not_found -> `Null in - let children = try js >? "children" |> children_of_json with Not_found -> [] in - Some( { header ; tactic ; params ; select } , children ) + let children = + try js >? "children" |> children_of_json with Not_found -> [] in + let strategy = + try Some (js >? "strategy" |> Json.string) with Not_found -> None in + Some( { header ; tactic ; params ; select ; strategy } , children ) with _ -> None (* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/ProofScript.mli b/src/plugins/wp/ProofScript.mli index 7d4d3400347a0e12f15edfa682b0893479138d38..7c4ab83e58fbdbcf8b0eb7b7b24eea9f8a659846 100644 --- a/src/plugins/wp/ProofScript.mli +++ b/src/plugins/wp/ProofScript.mli @@ -35,6 +35,7 @@ and jtactic = { tactic : string ; params : Json.t ; select : Json.t ; + strategy : string option ; } val is_prover : alternative -> bool @@ -54,7 +55,7 @@ val has_proof : jscript -> bool val decode : Json.t -> jscript val encode : jscript -> Json.t -val jtactic : title:string -> tactical -> selection -> jtactic +val jtactic : ?strategy:string -> tactical -> selection -> jtactic val configure : jtactic -> sequent -> (tactical * selection) option (** Json Codecs *) diff --git a/src/plugins/wp/ProofSession.ml b/src/plugins/wp/ProofSession.ml index 4e3e2eeaf3ac29456fa6a1f6bb91eb568becf1cb..678d280f5526a597d43ead2e0f096c8e6741e782 100644 --- a/src/plugins/wp/ProofSession.ml +++ b/src/plugins/wp/ProofSession.ml @@ -27,6 +27,58 @@ type script = | Script of string | Deprecated of string +type mode = + | Batch + | Update + | Dry + | Init + +let parse_mode ~origin ~fallback = function + | "batch" -> Batch + | "update" -> Update + | "dry" -> Dry + | "init" -> Init + | "" -> raise Not_found + | m -> + Wp_parameters.warning ~current:false + "Unknown %s mode %S (use %s instead)" origin m fallback ; + raise Not_found + +module MODE = WpContext.StaticGenerator(Datatype.Unit) + (struct + type key = unit + type data = mode + let name = "Wp.Script.mode" + let compile () = + try + if not (Wp_parameters.CacheEnv.get()) then + raise Not_found ; + let origin = "FRAMAC_WP_SCRIPT" in + parse_mode ~origin ~fallback:"-wp-script" (Sys.getenv origin) + with Not_found -> + try + let mode = Wp_parameters.ScriptMode.get() in + parse_mode ~origin:"-wp-script" ~fallback:"batch" mode + with Not_found -> + let provers = Wp_parameters.Provers.get () in + if List.mem "tip" provers then Update else + if List.mem "script" provers then Batch else + Dry + end) + +let get_mode = MODE.get +let set_mode m = MODE.set () m + +let scratch_mode () = + match MODE.get () with + | Batch | Update -> false + | Dry | Init -> true + +let saving_mode () = + match MODE.get () with + | Update | Init -> true + | Batch | Dry -> false + let files : (string,script) Hashtbl.t = Hashtbl.create 32 let jsonfile (dir:Datatype.Filepath.t) = diff --git a/src/plugins/wp/ProofSession.mli b/src/plugins/wp/ProofSession.mli index a7dd99a46ca7810fd7a155c4883eb8ab856529d8..833cfea103855fca7dbd6d7feddc24a050b5dffb 100644 --- a/src/plugins/wp/ProofSession.mli +++ b/src/plugins/wp/ProofSession.mli @@ -25,6 +25,18 @@ type script = | Script of string | Deprecated of string +type mode = + | Batch + | Update + | Dry + | Init + +val get_mode : unit -> mode +val set_mode : mode -> unit + +val scratch_mode : unit -> bool +val saving_mode : unit -> bool + val pp_file : Format.formatter -> string -> unit val pp_script_for : Format.formatter -> Wpo.t -> unit diff --git a/src/plugins/wp/ProofStrategy.ml b/src/plugins/wp/ProofStrategy.ml new file mode 100644 index 0000000000000000000000000000000000000000..4440b768d7be65fc0ac0278face838658303715e --- /dev/null +++ b/src/plugins/wp/ProofStrategy.ml @@ -0,0 +1,600 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* 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 Cil_datatype +open Logic_typing +open Logic_ptree +open Pattern +module D = Datatype + +(* -------------------------------------------------------------------------- *) +(* --- Proof Strategy Engine --- *) +(* -------------------------------------------------------------------------- *) + +type 'a loc = { loc : location ; value : 'a } + +(* Abstract Syntax Tree: must be stdlib-marshallable *) +type strategy = { + name: string loc ; + alternatives: alternative list ; +} + +and alternative = + | Default + | Strategy of string loc + | Provers of string loc list * float option (* timeout *) + | Auto of string loc (* deprecated -wp-auto *) + | Tactic of { + tactic : string loc ; + lookup : lookup list ; + select : value list ; + params : (string loc * value) list ; + children : (string loc * string loc) list ; (* name prefix and strategy *) + default: string loc option; (* None is default *) + } + +type hint = string * string list (* strategy name, targets *) + +(* -------------------------------------------------------------------------- *) +(* --- Registry --- *) +(* -------------------------------------------------------------------------- *) + +(* Strategies applies to all projects *) + +let kid = ref 0 +let hid : (int,hint) Hashtbl.t = Hashtbl.create 0 +let sid : (int,strategy) Hashtbl.t = Hashtbl.create 0 +let strategies : (string,strategy) Hashtbl.t = Hashtbl.create 0 +let revhints : hint list ref = ref [] + +(* -------------------------------------------------------------------------- *) +(* --- Printers --- *) +(* -------------------------------------------------------------------------- *) + +let pp_name fmt { value = s } = Format.pp_print_string fmt s +let pp_quoted fmt { value = s } = Format.fprintf fmt "%S" s + +let pp_lookup fmt = function + | { head = true ; goal = true ; hyps = false ; pattern } -> + Format.fprintf fmt "\\goal(%a)" Pattern.pp_pattern pattern + | { head = true ; goal = false ; pattern } -> + Format.fprintf fmt "\\when(%a)" Pattern.pp_pattern pattern + | { head = false ; goal = true ; hyps = false ; pattern } -> + Format.fprintf fmt "\\ingoal(%a)" Pattern.pp_pattern pattern + | { head = false ; goal = false ; pattern } -> + Format.fprintf fmt "\\incontext(%a)" Pattern.pp_pattern pattern + | { goal = true ; hyps = true ; pattern } -> + Format.fprintf fmt "\\pattern(%a)" Pattern.pp_pattern pattern + +let pp_select fmt s = + Format.fprintf fmt "\\select(%a)" Pattern.pp_value s + +let pp_param fmt (p,v) = + Format.fprintf fmt "\\param(%a,%a)" pp_quoted p Pattern.pp_value v + +let pp_child fmt (p,s) = + Format.fprintf fmt "\\child(%a,%a)" pp_quoted p pp_name s + +let pp_children fmt s = + Format.fprintf fmt "\\children(%a)" pp_name s + +let pp_alternative fmt = function + | Default -> Format.fprintf fmt "\\default" + | Strategy s -> pp_name fmt s + | Auto { value = s } -> Format.fprintf fmt "\\auto(%S)" s + | Provers([],None) -> Format.fprintf fmt "\\prover()" + | Provers([],Some tm) -> Format.fprintf fmt "\\prover(%.1f)" tm + | Provers(p::ps,None) -> + Format.fprintf fmt "@[<hov 2>\\prover(%a" pp_quoted p ; + List.iter (Format.fprintf fmt ",@,%a" pp_quoted) ps ; + Format.fprintf fmt ")@]" ; + | Provers(ps,Some tm) -> + Format.fprintf fmt "@[<hov 2>\\prover(" ; + List.iter (Format.fprintf fmt "%a,@," pp_quoted) ps ; + Format.fprintf fmt "%.1f)@]" tm ; + | Tactic { tactic ; lookup ; select ; params ; children ; default } -> + Format.fprintf fmt "@[<hv 2>\\tactic(%a" pp_quoted tactic ; + List.iter (Format.fprintf fmt ",@ %a" pp_lookup) lookup ; + List.iter (Format.fprintf fmt ",@ %a" pp_select) select ; + List.iter (Format.fprintf fmt ",@ %a" pp_param) params ; + List.iter (Format.fprintf fmt ",@ %a" pp_child) children ; + Option.iter (Format.fprintf fmt ",@ %a" pp_children) default ; + Format.fprintf fmt "@,)@]" + +let pp_strategy fmt s = + Format.fprintf fmt "%s:@ " s.name.value ; + Pretty_utils.pp_list ~sep:",@ " pp_alternative fmt s.alternatives + +let re_ident = Str.regexp "[_a-zA-Z][_a-zA-Z0-9]*$" + +let pp_option fmt s = + if Str.string_match re_ident s 0 then + Format.pp_print_string fmt s + else + Format.fprintf fmt "%S" s + +let pp_hint fmt ((s,ps): hint) = + Format.fprintf fmt "%s:@ " s ; + Pretty_utils.pp_list ~sep:",@ " pp_option fmt ps + +(* -------------------------------------------------------------------------- *) +(* --- Alternative Parser --- *) +(* -------------------------------------------------------------------------- *) + +let debug fmt p = + Format.fprintf fmt "@[<hov 2>at: %a@]" Logic_print.print_lexpr p + +let rec parse_provers ctxt provers timeout = function + | [] -> List.rev provers,timeout + | p::ps -> + let loc = p.lexpr_loc in + match p.lexpr_node with + | PLconstant (IntConstant t) -> + let time = try int_of_string t with Invalid_argument _ -> + ctxt.error loc "Invalid timeout" in + if time < 0 then ctxt.error loc "Invalid timeout" ; + if timeout <> None then ctxt.error loc "Duplicate timeout" ; + parse_provers ctxt provers (Some (float time)) ps + | PLconstant (FloatConstant t) -> + let time = try float_of_string t with Invalid_argument _ -> + ctxt.error loc "Invalid timeout" in + if time < 0.0 then ctxt.error loc "Invalid timeout" ; + if timeout <> None then ctxt.error loc "Duplicate timeout" ; + parse_provers ctxt provers (Some time) ps + | PLconstant (StringConstant value) -> + parse_provers ctxt ( { loc ; value } :: provers ) timeout ps + | _ -> ctxt.error loc "Invalid prover specification (%a)" debug p + +let parse_name ctxt ~kind ?check p = + let loc = p.lexpr_loc in + match p.lexpr_node with + | PLvar value + | PLapp(value,[],[]) + | PLconstant(StringConstant value) + -> + Option.iter (fun f -> f loc value) check ; + { loc ; value } + | _ -> ctxt.error loc "%s name expected (%a)" kind debug p + +let parse_lookup penv ?(head=true) ?(goal=false) ?(hyps=false) p = + { goal ; hyps ; head ; pattern = Pattern.pa_pattern penv p } + +let autoselect select lookup = + match select , lookup with + | [] , p::ps -> + let q,v = Pattern.self p.pattern in + [v] , { p with pattern = q }::ps + | _ -> select, lookup + +let rec parse_tactic_params ctxt penv + ~tactic ~select ~lookup ~params ~children ~default ps = + match ps with + | [] -> + let select = List.rev select in + let lookup = List.rev lookup in + let select,lookup = autoselect select lookup in + Tactic { + tactic ; select ; lookup ; + params = List.rev params ; + children = List.rev children ; + default ; + } + | p::ps -> + let loc = p.lexpr_loc in + let cc = parse_tactic_params ctxt penv ~tactic in + match p.lexpr_node with + | PLapp("\\goal",[],qs) -> + let qs = List.map (parse_lookup ~goal:true penv) qs in + let lookup = List.rev_append qs lookup in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\when",[],qs) -> + let qs = List.map (parse_lookup ~hyps:true penv) qs in + let lookup = List.rev_append qs lookup in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\ingoal",[],qs) -> + let qs = List.map (parse_lookup ~head:false ~goal:true penv) qs in + let lookup = List.rev_append qs lookup in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\incontext",[],qs) -> + let qs = List.map (parse_lookup ~head:false ~hyps:true penv) qs in + let lookup = List.rev_append qs lookup in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\pattern",[],qs) -> + let qs = List.map + (parse_lookup ~head:false ~goal:true ~hyps:true penv) qs in + let lookup = List.rev_append qs lookup in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\select",[],vs) -> + let vs = List.map (Pattern.pa_value penv) vs in + let select = List.rev_append vs select in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\param",[],[param;value]) -> + let param = parse_name ctxt ~kind:"Parameter" param in + let value = Pattern.pa_value penv value in + let params = (param,value)::params in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\child",[],[prefix;strategy]) -> + let subgoal = parse_name ctxt ~kind:"Subgoal" prefix in + let strategy = parse_name ctxt ~kind:"Strategy" strategy in + let children = (subgoal,strategy)::children in + cc ~select ~lookup ~params ~children ~default ps + | PLapp("\\children",[],[strategy]) -> + if default <> None then ctxt.error loc "Duplicate \\children parameter" ; + let default = Some (parse_name ctxt ~kind:"Strategy" strategy) in + cc ~select ~lookup ~params ~children ~default ps + | _ -> ctxt.error loc "Tactic parameter expected (%a)" debug p + +let parse_alternatives ctxt p = + let loc = p.lexpr_loc in + match p.lexpr_node with + | PLvar("\\default") -> [ Default ] + | PLapp("\\prover",[],ps) -> + let prvs,timeout = parse_provers ctxt [] None ps in + [ Provers(prvs,timeout) ] + | PLapp("\\tactic",[],p::ps) -> + let tactic = parse_name ctxt ~kind:"tactic" p in + [ parse_tactic_params ctxt (Pattern.context ctxt) ~tactic + ~select:[] ~lookup:[] ~params:[] ~children:[] ~default:None ps ] + | PLapp("\\auto",[],ps) -> + List.map (fun p -> Auto (parse_name ctxt ~kind:"auto" p)) ps + | PLvar value | PLapp(value,[],[]) -> [ Strategy { loc ; value } ] + | _ -> ctxt.error loc "Strategy definition expected (%a)" debug p + +(* -------------------------------------------------------------------------- *) +(* --- Strategy Parser --- *) +(* -------------------------------------------------------------------------- *) + +let parse_strategy_name ctxt loc = function + | [] -> ctxt.error loc "Empty strategy" + | p::ps -> + match p.lexpr_node with + | PLnamed(value,p) -> { loc ; value }, p::ps + | _ -> ctxt.error loc "Missing strategy name (%a)" debug p + +let parse_strategy ctxt loc ps = + let name,ps = parse_strategy_name ctxt loc ps in + try + let old = Hashtbl.find strategies name.value in + ctxt.error loc "Duplicate strategy definition ('%s', at %a)" + name.value Location.pretty old.name.loc + with Not_found -> + let alternatives = List.concat @@ List.map (parse_alternatives ctxt) ps in + let strategy = { name ; alternatives } in + let id = incr kid ; !kid in + Hashtbl.add strategies name.value strategy ; + Hashtbl.add sid id strategy ; Ext_id id + +(* -------------------------------------------------------------------------- *) +(* --- Proof Parser --- *) +(* -------------------------------------------------------------------------- *) + +let parse_hints ctxt p = + let loc = p.lexpr_loc in + match p.lexpr_node with + | PLvar x -> [x] + | PLconstant(StringConstant x) -> String.split_on_char ',' x + | _ -> ctxt.error loc "Proof hint expected (see -wp-prop) (%a)" debug p + +let parse_proofs ctxt loc ps = + let name , ps = parse_strategy_name ctxt loc ps in + let strategy = name.value in + if not (Hashtbl.mem strategies strategy) then + ctxt.error name.loc "Unknown strategy '%s'" strategy ; + let props = List.concat @@ List.map (parse_hints ctxt) ps in + let hint = (strategy, props) in + revhints := hint :: !revhints ; + let id = incr kid ; !kid in + Hashtbl.add hid id hint ; Ext_id id + +(* -------------------------------------------------------------------------- *) +(* --- Strategy ACSL Extensions --- *) +(* -------------------------------------------------------------------------- *) + +let registered = ref false +let register () = + if not !registered && Wp_parameters.StrategyEngine.get () then + begin + registered := true ; + let printer hmap pp _ fmt = function + | Ext_id id -> Option.iter (pp fmt) (Hashtbl.find_opt hmap id) + | _ -> () in + Acsl_extension.register_global "strategy" + ~printer:(printer sid pp_strategy) parse_strategy false ; + Acsl_extension.register_global "proof" + ~printer:(printer hid pp_hint) parse_proofs false ; + end + +let () = Cmdline.run_after_configuring_stage register + +(* -------------------------------------------------------------------------- *) +(* --- Strategy Resolution --- *) +(* -------------------------------------------------------------------------- *) + +let name s = s.name.value +let loc s = s.name.loc +let find = Hashtbl.find_opt strategies +let resolve name = + try Some (Hashtbl.find strategies name.value) + with Not_found -> + Wp_parameters.error ~source:(fst name.loc) ~once:true + "Strategy '%s' undefined (skipped)." name.value ; + None + +let resolve_auto name = + try Some (Strategy.lookup ~id:name.value) + with Not_found -> + Wp_parameters.error ~source:(fst name.loc) ~once:true + "Auto-Strategy '%s' not found (skipped)." name.value ; + None + +let resolve_prover name = + let result = VCS.parse_prover name.value in + if result = None then + Wp_parameters.error ~source:(fst name.loc) ~once:true + "Prover '%s' not found (skipped)." name.value ; + result + +let resolve_tactic name = + try Some (Tactical.lookup ~id:name.value) + with Not_found -> + Wp_parameters.error ~source:(fst name.loc) ~once:true + "Tactical '%s' not found (skipped alternative)." name.value ; + None + +(* -------------------------------------------------------------------------- *) +(* --- Strategy Checking --- *) +(* -------------------------------------------------------------------------- *) + +let check_prover p = ignore @@ resolve_prover p +let check_strategy s = ignore @@ resolve s + +let check_parameter env (t : Tactical.tactical) (p,v) = + try + let prm = List.find (fun q -> Tactical.pident q = p.value) t#params in + match prm with + | Checkbox _ -> Pattern.typecheck_value env ~tau:Qed.Logic.Bool v + | _ -> () + with Not_found -> + Wp_parameters.error ~source:(fst p.loc) ~once:true + "Parameter '%s' not found in tactic '%s'" + p.value t#id + +let check_alternative = function + | Default -> () + | Strategy s -> ignore @@ resolve s + | Auto s -> ignore @@ resolve_auto s + | Provers(pvs,_) -> List.iter check_prover pvs + | Tactic { tactic ; lookup ; params ; children ; default } -> + begin + let env = Pattern.env () in + List.iter (Pattern.typecheck_lookup env) lookup ; + Option.iter + (fun tactical -> + List.iter (check_parameter env tactical) params ; + ) (resolve_tactic tactic) ; + List.iter (fun (_,s) -> check_strategy s) children ; + Option.iter check_strategy default ; + end + +let typecheck () = + Hashtbl.iter + (fun _ s -> List.iter check_alternative s.alternatives) strategies + +(* -------------------------------------------------------------------------- *) +(* --- Strategy Hints --- *) +(* -------------------------------------------------------------------------- *) + +let iter f = + let module M = Map.Make(String) in + let pool = ref M.empty in + Hashtbl.iter (fun a s -> pool := M.add a s !pool) strategies ; + M.iter (fun _ s -> f s) !pool + +let default () = + List.filter_map + (fun s -> + try Some (Hashtbl.find strategies s) + with Not_found -> + Wp_parameters.warning ~current:false ~once:true + "Invalid -wp-strategy '%s' (undefined strategy name)" s ; + None + ) @@ + Wp_parameters.DefaultStrategies.get () + +let hints ?node goal = + let pool = ref [] in + let add s = if not @@ List.memq s !pool then pool := s :: !pool in + let addname name = Option.iter add @@ Hashtbl.find_opt strategies name in + Option.iter addname (Option.bind node ProofEngine.get_hint) ; + let pid = goal.Wpo.po_pid in + List.iter + (fun (name,ps) -> + if WpPropId.select_by_name ps pid then addname name + ) !revhints ; + List.iter add @@ List.rev @@ default () ; + List.rev !pool + +let has_hint goal = + let pid = goal.Wpo.po_pid in + List.exists (fun (_,ps) -> WpPropId.select_by_name ps pid) !revhints + +(* -------------------------------------------------------------------------- *) +(* --- Strategy Forward Step --- *) +(* -------------------------------------------------------------------------- *) + +let alternatives s = s.alternatives + +let timeout = function + | Some tm -> tm | None -> float @@ Wp_parameters.Timeout.get () + +let provers ?(default=[]) = function + | Provers([],tm) -> default, timeout tm + | Provers(ps,tm) -> List.filter_map resolve_prover ps, timeout tm + | Default | Strategy _ | Tactic _ | Auto _ -> [],0.0 + +let fallback = function + | Strategy s -> resolve s + | Tactic _ | Auto _ | Provers _ -> None + | Default -> Some { + name = { value = "\\default" ; loc = Position.(unknown,unknown) } ; + alternatives = List.map (fun s -> Strategy s.name) @@ default () ; + } + +let auto = function + | Default | Strategy _ | Tactic _ | Provers _ -> None + | Auto s -> resolve_auto s + +(* -------------------------------------------------------------------------- *) +(* --- Strategy Tactical Step --- *) +(* -------------------------------------------------------------------------- *) + +let tactical a = + match resolve_tactic a with None -> raise Not_found | Some t -> t + +let parameter (t : Tactical.tactical) a = + try List.find (fun p -> Tactical.pident p = a.value) t#params + with Not_found -> + Wp_parameters.error ~source:(fst a.loc) ~once:true + "Parameter '%s' not found (skipped alternative)." a.value ; + raise Not_found + +let rec bind sigma sequent = function + | [] -> sigma + | lookup::binders -> + match Pattern.psequent lookup sigma sequent with + | None -> raise Not_found + | Some sigma -> bind sigma sequent binders + +let select sigma ?goal = function + | [] -> + begin + match goal with + | None -> Tactical.Empty + | Some p -> Tactical.(Clause (Goal p)) + end + | [v] -> Pattern.select sigma v + | vs -> Tactical.Multi (List.map (Pattern.select sigma) vs) + +let configure tactic sigma (a,v) = + match parameter tactic a with + | Checkbox fd -> + begin + try tactic#set_field fd (Pattern.bool v) + with Not_found -> + Wp_parameters.error ~source:(fst a.loc) + "Expected boolean for parameter '%s' (%a)" a.value + Pattern.pp_value v ; + raise Not_found + end + | Spinner(fd,_) -> + begin + let value = Pattern.select sigma v in + match Tactical.get_int value with + | Some v -> tactic#set_field fd v + | None -> + Wp_parameters.error ~source:(fst a.loc) + "Expected integer for parameter '%s'@ (%a)" a.value + Tactical.pp_selection value ; + raise Not_found + end + | Composer(fd,_) -> tactic#set_field fd (Pattern.select sigma v) + | Selector(fd,vs,_) -> + begin + try + let id = Pattern.string v in + let v = List.find (fun v -> v.Tactical.vid = id) vs in + tactic#set_field fd v.value + with Not_found -> + Wp_parameters.error ~source:(fst a.loc) + "Expected string for parameter '%s'@ (%a)" a.value + Pattern.pp_value v ; + raise Not_found + end + | Search(fd,_,lookup) -> + begin + try + let id = Pattern.string v in + let v = lookup id in + tactic#set_field fd (Some v) + with Not_found -> + Wp_parameters.error ~source:(fst a.loc) + "Expected string for parameter '%s'@ (%a)" a.value + Pattern.pp_value v ; + raise Not_found + end + +let subgoal (children : (string loc * string loc) list) + (default : string loc option) (goal,node) = + let hint = List.find_map (fun (g,s) -> + if Extlib.string_prefix g.value goal then Some s else None + ) children in + begin + match hint, default with + | None, None -> () + | Some s , _ | None , Some s -> + if not @@ Hashtbl.mem strategies s.value then + Wp_parameters.error ~source:(fst s.loc) + "Unknown strategy '%s' (skipped)" s.value + else ProofEngine.set_hint node s.value + end ; node + +let tactic tree node strategy = function + | Default | Strategy _ | Auto _ | Provers _ -> None + | Tactic t -> + try + let tactic = tactical t.tactic in + let pool = ProofEngine.pool tree in + let title = tactic#title in + let ctxt = ProofEngine.node_context node in + let sequent = snd @@ Wpo.compute @@ ProofEngine.goal node in + let console = new ProofScript.console ~pool ~title in + let subgoals = WpContext.on_context ctxt + begin fun () -> + let sigma = bind Pattern.empty sequent t.lookup in + let goal = if t.lookup = [] then Some (snd sequent) else None in + let selection = select sigma ?goal t.select in + List.iter (configure tactic sigma) t.params ; + match Lang.local ~pool (tactic#select console) selection with + | exception (Not_found | Exit) -> raise Not_found + | Not_applicable -> + raise Not_found + | exception exn when Wp_parameters.protect exn -> + Wp_parameters.warning ~source:(fst t.tactic.loc) + "Tactical '%s' configuration error (%s)" + t.tactic.value (Printexc.to_string exn) ; + raise Not_found + | Not_configured -> + Wp_parameters.error ~source:(fst t.tactic.loc) + "Tactical '%s' configuration error" + t.tactic.value ; + raise Not_found + | Applicable process -> + let strategy = strategy.name.value in + let script = ProofScript.jtactic ~strategy tactic selection in + let fork = ProofEngine.fork tree ~anchor:node script process in + snd @@ ProofEngine.commit fork + end () in + Some (List.map (subgoal t.children t.default) subgoals) + with Not_found -> None + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/gui/dgraph_helper.mli b/src/plugins/wp/ProofStrategy.mli similarity index 56% rename from src/plugins/gui/dgraph_helper.mli rename to src/plugins/wp/ProofStrategy.mli index e75b9f204147b5906fc306204300568dafbe4f96..90c5995b1f8ba0022ada4f5756ea4c67069b732f 100644 --- a/src/plugins/gui/dgraph_helper.mli +++ b/src/plugins/wp/ProofStrategy.mli @@ -1,9 +1,9 @@ (**************************************************************************) (* *) -(* This file is part of Frama-C. *) +(* This file is part of WP plug-in of Frama-C. *) (* *) (* Copyright (C) 2007-2023 *) -(* CEA (Commissariat à l'énergie atomique et aux énergies *) +(* CEA (Commissariat a l'energie atomique et aux energies *) (* alternatives) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) @@ -20,23 +20,29 @@ (* *) (**************************************************************************) -(** Creation of windows for displaying graphs. Only available - for lablgtk2. In lablgtk3 mode, the window will only display a - text saying that the feature is not available. -*) +open ProofEngine -(** Create a new window displaying a graph. - @see <https://frama-c.com/download/frama-c-plugin-development-guide.pdf> Plug-in Development Guide *) -val graph_window: - parent: GWindow.window -> - title:string -> - (packing:(GObj.widget -> unit) -> unit -> - <adapt_zoom: unit -> unit; ..>) -> - unit +(* -------------------------------------------------------------------------- *) +(* --- Proof Strategy Engine --- *) +(* -------------------------------------------------------------------------- *) -(** Create a new window displaying a graph, by printing dot commands. *) -val graph_window_through_dot: - parent: GWindow.window -> - title:string -> - (Format.formatter -> unit) -> - unit +type strategy +type alternative + +val typecheck : unit -> unit + +val name : strategy -> string +val loc : strategy -> Cil_types.location +val find : string -> strategy option +val hints : ?node:ProofEngine.node -> Wpo.t -> strategy list +val has_hint : Wpo.t -> bool + +val iter : (strategy -> unit) -> unit +val default : unit -> strategy list +val alternatives : strategy -> alternative list +val provers : ?default:VCS.prover list -> alternative -> VCS.prover list * float +val auto : alternative -> Strategy.heuristic option +val fallback : alternative -> strategy option +val tactic : tree -> node -> strategy -> alternative -> node list option + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/ProverScript.ml b/src/plugins/wp/ProverScript.ml index 91eeaf02adc04b93508a1185c15b2c42fc73a8f5..feb73306307eecf2e682563f7ed1735cbeefe5c5 100644 --- a/src/plugins/wp/ProverScript.ml +++ b/src/plugins/wp/ProverScript.ml @@ -23,8 +23,7 @@ open Tactical open ProofScript -let dkey_pp_allgoals = - Wp_parameters.register_category "script:allgoals" +let dkey_pp_allgoals = Wp_parameters.register_category "script:allgoals" (* -------------------------------------------------------------------------- *) (* --- Alternatives Ordering --- *) @@ -73,8 +72,8 @@ let jconfigure (console : #Tactical.feedback) jtactic goal = begin match verdict with | Applicable process when not console#has_error -> - let title = tactical#title in - let script = ProofScript.jtactic ~title tactical selection in + let strategy = jtactic.strategy in + let script = ProofScript.jtactic ?strategy tactical selection in Some (script , process) | _ -> None end @@ -85,6 +84,7 @@ let jfork tree ?node jtactic = ~title:jtactic.header in try let anchor = ProofEngine.anchor tree ?node () in + Option.iter (ProofEngine.set_hint anchor) jtactic.strategy ; let goal = ProofEngine.goal anchor in let ctxt = ProofEngine.node_context anchor in match WpContext.on_context ctxt (jconfigure console jtactic) goal with @@ -117,7 +117,8 @@ struct success : Wpo.t -> VCS.prover option -> unit ; depth : int ; width : int ; - auto : Strategy.heuristic list ; + auto : Strategy.heuristic list ; (* DEPRECATED *) + strategies : bool ; mutable signaled : bool ; backtrack : int ; mutable backtracking : backtracking option ; @@ -219,11 +220,11 @@ struct let provers env = env.provers let make tree - ~valid ~failed ~provers + ~valid ~failed ~provers ~strategies ~depth ~width ~backtrack ~auto ~progress ~result ~success = { tree ; valid ; failed ; provers ; - depth ; width ; backtrack ; auto ; + depth ; width ; backtrack ; auto ; strategies ; progress ; result ; success ; backtracking = None ; signaled = false } @@ -277,7 +278,7 @@ let prove_node env node prv = else Task.return false (* -------------------------------------------------------------------------- *) -(* --- Auto & Seach Mode --- *) +(* --- Auto & Seach Mode (DEPRECATED) --- *) (* -------------------------------------------------------------------------- *) let rec auto env ?(depth=0) node : bool Task.task = @@ -314,6 +315,98 @@ and autofork env ~depth fork = else ( Env.validate env ; Task.return true ) +(* -------------------------------------------------------------------------- *) +(* --- Proof Strategy Alternatives --- *) +(* -------------------------------------------------------------------------- *) + +type solver = ProofEngine.node -> bool Task.task + +let success = Task.return true +let failed = Task.return false +let unknown : solver = fun _ -> failed + +let (+>>) (a : solver) (b : solver) : solver = + fun node -> a node >>= fun ok -> if ok then success else b node + +let rec sequence (f : 'a -> solver) = function + | [] -> unknown + | x::xs -> f x +>> sequence f xs + +let rec explore_strategy env process strategy : solver = + sequence + (explore_alternative env process strategy) + (ProofStrategy.alternatives strategy) + +and explore_alternative env process strategy alternative : solver = + explore_provers env alternative +>> + explore_tactic env process strategy alternative +>> + explore_auto env process alternative +>> + explore_fallback env process alternative + +and explore_provers env alternative : solver = + let provers,timeout = + ProofStrategy.provers ~default:env.Env.provers alternative in + sequence (explore_prover env timeout) provers + +and explore_prover env timeout prover node = + let wpo = ProofEngine.goal node in + let result = Cache.promote ~timeout @@ Wpo.get_result wpo prover in + if VCS.is_valid result then success else + if VCS.is_verdict result then failed else + let config = { VCS.default with timeout = Some timeout } in + Env.prove env wpo ~config prover + +and explore_tactic env process strategy alternative node = + match ProofStrategy.tactic env.tree node strategy alternative with + | None -> failed + | Some nodes -> List.iter process nodes ; success + +and explore_auto env process alternative node = + match ProofStrategy.auto alternative with + | None -> failed + | Some h -> + match ProverSearch.search env.tree ~anchor:node [h] with + | None -> failed + | Some fork -> + List.iter (fun (_,node) -> process node) @@ + snd @@ ProofEngine.commit fork ; success + +and explore_fallback env process alternative node = + match ProofStrategy.fallback alternative with + | None -> failed + | Some strategy -> explore_strategy env process strategy node + +let explore_local_hint env process node = + if ProofEngine.depth node > env.Env.depth then failed + else + match ProofEngine.get_hint node with + | None -> failed + | Some s -> + match ProofStrategy.find s with + | None -> failed + | Some s -> explore_strategy env process s node + +let explore_further env process strategy node = + let marked = + match ProofEngine.get_hint node with + | None -> false + | Some s -> ProofStrategy.name strategy = s + in if marked then failed else explore_strategy env process strategy node + +let explore_further_hints env process = + let wpo = ProofEngine.main env.Env.tree in + sequence (explore_further env process) (ProofStrategy.hints wpo) + +let explore_hints env process = + explore_local_hint env process +>> explore_further_hints env process + +(* -------------------------------------------------------------------------- *) +(* --- Automated Solving --- *) +(* -------------------------------------------------------------------------- *) + +let automated env process : solver = + auto env +>> if env.Env.strategies then explore_hints env process else unknown + (* -------------------------------------------------------------------------- *) (* --- Apply Script Tactic --- *) (* -------------------------------------------------------------------------- *) @@ -337,17 +430,17 @@ let rec crawl env on_child node = function | [] -> let node = ProofEngine.anchor (Env.tree env) ?node () in - auto env node >>= fun ok -> + automated env on_child node >>= fun ok -> if ok then Env.validate env else Env.stuck env ; Task.return () - | Error(msg,json) :: alternative -> + | Error(msg,json) :: alternatives -> Wp_parameters.warning "@[<hov 2>Script Error: on goal %a@\n%S: %a@]@." WpPropId.pretty (Env.goal env node).po_pid msg Json.pp json ; - crawl env on_child node alternative + crawl env on_child node alternatives - | Prover( prv , res ) :: alternative -> + | Prover( prv , res ) :: alternatives -> begin let task = if Env.play env prv res then @@ -358,12 +451,12 @@ let rec crawl env on_child node = function let continue ok = if ok then (Env.validate env ; Task.return ()) - else crawl env on_child node alternative + else crawl env on_child node alternatives in task >>= continue end - | Tactic( _ , jtactic , subscripts ) :: alternative -> + | Tactic( _ , jtactic , subscripts ) :: alternatives -> begin try let residual = apply env node jtactic subscripts in @@ -384,7 +477,7 @@ let rec crawl env on_child node = function (Printexc.to_string exn) Json.pp jtactic.params Json.pp jtactic.select ; - crawl env on_child node alternative + crawl env on_child node alternatives end (* -------------------------------------------------------------------------- *) @@ -412,7 +505,7 @@ let rec process env node = let task ~valid ~failed ~provers - ~depth ~width ~backtrack ~auto + ~depth ~width ~backtrack ~auto ~scratch ~strategies ~start ~progress ~result ~success wpo = begin fun () -> Wp_parameters.debug ~dkey:dkey_pp_allgoals "%a" Wpo.pp_goal_flow wpo ; @@ -421,12 +514,14 @@ let task then ( success wpo (Some VCS.Qed) ; Task.return ()) else - let json = ProofSession.load wpo in - let script = Priority.sort (ProofScript.decode json) in + let script = + if scratch then [] else + Priority.sort @@ ProofScript.decode @@ ProofSession.load wpo + in let tree = ProofEngine.proof ~main:wpo in let env = Env.make tree ~valid ~failed ~provers - ~depth ~width ~backtrack ~auto + ~depth ~width ~backtrack ~auto ~strategies ~progress ~result ~success in crawl env (process env) None script >>? (fun _ -> ProofEngine.forward tree) ; @@ -437,9 +532,10 @@ let task (* -------------------------------------------------------------------------- *) type 'a process = - ?valid:bool -> ?failed:bool -> ?provers:VCS.prover list -> + ?valid:bool -> ?failed:bool -> ?scratch:bool -> ?provers:VCS.prover list -> ?depth:int -> ?width:int -> ?backtrack:int -> ?auto:Strategy.heuristic list -> + ?strategies:bool -> ?start:(Wpo.t -> unit) -> ?progress:(Wpo.t -> string -> unit) -> ?result:(Wpo.t -> VCS.prover -> VCS.result -> unit) -> @@ -451,23 +547,25 @@ let skip2 _ _ = () let skip3 _ _ _ = () let prove - ?(valid = true) ?(failed = true) ?(provers = []) + ?(valid = true) ?(failed = true) ?(scratch = false) ?(provers = []) ?(depth = 0) ?(width = 0) ?(backtrack = 0) ?(auto = []) + ?(strategies = false) ?(start = skip1) ?(progress = skip2) ?(result = skip3) ?(success = skip2) wpo = Task.todo (task ~valid ~failed ~provers - ~depth ~width ~backtrack ~auto + ~depth ~width ~backtrack ~auto ~scratch ~strategies ~start ~progress ~result ~success wpo) let spawn - ?(valid = true) ?(failed = true) ?(provers = []) + ?(valid = true) ?(failed = true) ?(scratch = false) ?(provers = []) ?(depth = 0) ?(width = 0) ?(backtrack = 0) ?(auto = []) + ?(strategies = false) ?(start = skip1) ?(progress = skip2) ?(result = skip3) ?(success = skip2) wpo = schedule (task ~valid ~failed ~provers - ~depth ~width ~backtrack ~auto + ~depth ~width ~backtrack ~auto ~scratch ~strategies ~start ~progress ~result ~success wpo) let search @@ -477,7 +575,7 @@ let search begin let env = Env.make tree ~valid:false ~failed:false ~provers - ~depth ~width ~backtrack ~auto + ~depth ~width ~backtrack ~auto ~strategies:false ~progress ~result ~success in schedule begin fun () -> @@ -488,6 +586,28 @@ let search end end +let explore ?(depth=0) ?(strategy) + ?(progress = skip2) ?(result=skip3) ?(success = skip2) + tree node = + begin + let depth = ProofEngine.depth node + depth in + let env : Env.t = + Env.make tree ~valid:false ~failed:false + ~strategies:(strategy <> None) + ~provers:[] ~depth ~width:0 ~backtrack:0 ~auto:[] + ~progress ~result ~success in + schedule + begin fun () -> + let solver = + match strategy with + | None -> explore_hints env (process env) + | Some s -> explore_strategy env (fun _ -> ()) s + in solver node >>= fun ok -> + if ok then Env.validate ~finalize:true env else Env.stuck env ; + Task.return () + end + end + (* -------------------------------------------------------------------------- *) (* --- Save Session --- *) (* -------------------------------------------------------------------------- *) @@ -507,11 +627,6 @@ let has_proof wpo = (Hashtbl.add proofs wid ok ; ok) else false -let save ~stdout wpo = - let script = ProofEngine.script (ProofEngine.proof ~main:wpo) in - Hashtbl.remove proofs wpo.Wpo.po_gid ; - ProofSession.save ~stdout wpo (ProofScript.encode script) - let get wpo = match ProofEngine.get wpo with | `None -> `None diff --git a/src/plugins/wp/ProverScript.mli b/src/plugins/wp/ProverScript.mli index 90452f6f98a593fe6429aad6d40265075b069af3..022ffd6b573f9210ce481d0657eff67d0182e9fb 100644 --- a/src/plugins/wp/ProverScript.mli +++ b/src/plugins/wp/ProverScript.mli @@ -24,6 +24,7 @@ open VCS (** - [valid]: Play provers with valid result (default: true) - [failed]: Play provers with invalid result (default: true) + - [scratch]: Discard existing script (default: false) - [provers]: Additional list of provers to {i try} when stuck - [depth]: Strategy search depth (default: 0) - [width]: Strategy search width (default: 0) @@ -33,11 +34,13 @@ open VCS type 'a process = ?valid:bool -> ?failed:bool -> + ?scratch:bool -> ?provers:prover list -> ?depth:int -> ?width:int -> ?backtrack:int -> ?auto:Strategy.heuristic list -> + ?strategies:bool -> ?start:(Wpo.t -> unit) -> ?progress:(Wpo.t -> string -> unit) -> ?result:(Wpo.t -> prover -> result -> unit) -> @@ -60,5 +63,14 @@ val search : ProofEngine.node -> unit +val explore : + ?depth:int -> + ?strategy:ProofStrategy.strategy -> + ?progress:(Wpo.t -> string -> unit) -> + ?result:(Wpo.t -> prover -> result -> unit) -> + ?success:(Wpo.t -> prover option -> unit) -> + ProofEngine.tree -> + ProofEngine.node -> + unit + val get : Wpo.t -> [ `Script | `Proof | `Saved | `None ] -val save : stdout:bool -> Wpo.t -> unit diff --git a/src/plugins/wp/ProverSearch.ml b/src/plugins/wp/ProverSearch.ml index 697016c96e9f6857d9d80bffb11ef6987289c8b5..f2872d66e8c98261d90699a1a7f498b8f6bc7fcf 100644 --- a/src/plugins/wp/ProverSearch.ml +++ b/src/plugins/wp/ProverSearch.ml @@ -34,8 +34,7 @@ let configure (console : #Tactical.feedback) strategy = in match Lang.local ~pool:console#pool verdict () with | Applicable process when not console#has_error -> - let title = tactical#title in - let script = ProofScript.jtactic ~title tactical selection in + let script = ProofScript.jtactic tactical selection in Some (script , process) | _ -> None diff --git a/src/plugins/wp/ProverTask.ml b/src/plugins/wp/ProverTask.ml index 4746c8b00f0551b1b858876e32079de5c4e53f4f..76808660184319c903f6b9d4c49e64fdbaf88ad7 100644 --- a/src/plugins/wp/ProverTask.ml +++ b/src/plugins/wp/ProverTask.ml @@ -182,7 +182,7 @@ class command name = val mutable once = true val mutable cmd = name val mutable param : string list = [] - val mutable timeout = 0 + val mutable timeout = 0.0 val mutable validout = [] val mutable validerr = [] val mutable timers = [] diff --git a/src/plugins/wp/ProverTask.mli b/src/plugins/wp/ProverTask.mli index db6356dbe219ca14fbbf6551cd2fce6f81bb9ff1..a37c089fdbefc34b97ab1064128a91edfa59473d 100644 --- a/src/plugins/wp/ProverTask.mli +++ b/src/plugins/wp/ProverTask.mli @@ -77,7 +77,7 @@ class virtual command : string -> method add_float : name:string -> value:float -> unit method add_parameter : name:string -> (unit -> bool) -> unit method add_list : name:string -> string list -> unit - method timeout : int -> unit + method timeout : float -> unit method validate_time : (float -> unit) -> unit method validate_pattern : ?logs:logs -> ?repeat:bool -> Str.regexp -> (pattern -> unit) -> unit diff --git a/src/plugins/wp/ProverWhy3.ml b/src/plugins/wp/ProverWhy3.ml index 834e02cd47ed7a8e2c306e6782c4261e66fe1199..7a9bd2fa1a7006a27e8e8c29afa5de3a778f420a 100644 --- a/src/plugins/wp/ProverWhy3.ml +++ b/src/plugins/wp/ProverWhy3.ml @@ -144,9 +144,8 @@ let lfun_name (lfun:Lang.lfun) = match lfun with | ACSL f -> Qed.Engine.F_call (Lang.logic_id f) | CTOR c -> Qed.Engine.F_call (Lang.ctor_id c) - | Model({m_source=Generated(_,n)}) -> Qed.Engine.F_call n - | Model({m_source=Extern e}) -> e.Lang.ext_link - + | FUN({m_source=Generated(_,n)}) -> Qed.Engine.F_call n + | FUN({m_source=Extern e}) -> e.Lang.ext_link let coerce ~cnv sort expected r = match sort, expected with @@ -1152,7 +1151,7 @@ type prover_call = { prover : Why3Provers.t ; call : Why3.Call_provers.prover_call ; steps : int option ; - timeout : int ; + timeout : float ; mutable timeover : float option ; mutable interrupted : bool ; mutable killed : bool ; @@ -1163,11 +1162,11 @@ let ping_prover_call ~config p = | NoUpdates | ProverStarted -> let () = - if p.timeout > 0 then + if p.timeout > 0.0 then match p.timeover with | None -> let started = Unix.time () in - p.timeover <- Some (started +. 2.0 +. float p.timeout) + p.timeover <- Some (started +. 2.0 +. p.timeout) | Some timeout -> let time = Unix.time () in if time > timeout then @@ -1187,7 +1186,7 @@ let ping_prover_call ~config p = | ProverFinished pr -> let r = match pr.pr_answer with - | Timeout -> VCS.timeout (int_of_float pr.pr_time) + | Timeout -> VCS.timeout pr.pr_time | Valid -> VCS.result ~time:pr.pr_time ~steps:pr.pr_steps VCS.Valid | Invalid -> VCS.result ~time:pr.pr_time ~steps:pr.pr_steps VCS.Invalid | OutOfMemory -> VCS.failed "out of memory" @@ -1211,11 +1210,11 @@ let ping_prover_call ~config p = Task.Return (Task.Result r) let call_prover_task ~timeout ~steps ~config prover call = - Wp_parameters.debug ~dkey "Why3 run prover %a with timeout %d, steps %d@." + Wp_parameters.debug ~dkey "Why3 run prover %a with timeout %f, steps %d@." Why3.Whyconf.print_prover prover - (Why3.Opt.get_def (-1) timeout) - (Why3.Opt.get_def (-1) steps) ; - let timeout = match timeout with None -> 0 | Some tlimit -> tlimit in + (Why3.Opt.get_def (0.0) timeout) + (Why3.Opt.get_def 0 steps) ; + let timeout = match timeout with None -> 0.0 | Some tlimit -> tlimit in let pcall = { call ; prover ; killed = false ; @@ -1256,7 +1255,6 @@ let run_batch pconf driver ~config ?script ~timeout ~steplimit prover task = let steps = match steplimit with Some 0 -> None | _ -> steplimit in let limit = let config = Why3.Whyconf.get_main @@ Why3Provers.config () in - let timeout = Option.map float_of_int timeout in let memlimit = Why3.Whyconf.memlimit config in let def = Why3.Call_provers.empty_limit in { Why3.Call_provers.limit_time = Why3.Opt.get_def def.limit_time timeout; @@ -1266,7 +1264,11 @@ let run_batch pconf driver ~config ?script ~timeout ~steplimit prover task = let with_steps = match steps, pconf.Why3.Whyconf.command_steps with | None, _ -> false | Some _, Some _ -> true - | Some _, None -> false + | Some _, None -> + Wp_parameters.warning ~once:true ~current:false + "%a does not support steps limit (ignored option)" + Why3.Whyconf.print_prover prover ; + false in let steps = if with_steps then steps else None in let command = Why3.Whyconf.get_complete_command pconf ~with_steps in @@ -1343,7 +1345,7 @@ let prepare ~mode wpo driver task = let interactive ~mode wpo pconf ~config driver prover task = let time = Wp_parameters.InteractiveTimeout.get () in - let timeout = if time <= 0 then None else Some time in + let timeout = if time <= 0 then None else Some (float time) in match prepare ~mode wpo driver task with | None -> Wp_parameters.warning ~once:true ~current:false diff --git a/src/plugins/wp/ProverWhy3.mli b/src/plugins/wp/ProverWhy3.mli index 8f00f859dfa4a8b5200980a0ff053b2476e24efb..24aac04061dc75bf6f294910899857c8f49e2e4f 100644 --- a/src/plugins/wp/ProverWhy3.mli +++ b/src/plugins/wp/ProverWhy3.mli @@ -26,7 +26,7 @@ val add_specific_equality: unit (** Equality used in the goal, simpler to prove than polymorphic equality *) -val prove : ?mode:VCS.mode -> ?timeout:int -> ?steplimit:int -> +val prove : ?mode:VCS.mode -> ?timeout:float -> ?steplimit:int -> prover:Why3Provers.t -> Wpo.t -> VCS.result Task.task (** Return NoResult if it is already proved by Qed *) diff --git a/src/plugins/wp/RegionAnnot.ml b/src/plugins/wp/RegionAnnot.ml index b0ca2f6e741103fa301c20f993fcca8e2a10576f..d32aaf7a785c4fabd03713b406ff132861ab5a5a 100644 --- a/src/plugins/wp/RegionAnnot.ml +++ b/src/plugins/wp/RegionAnnot.ml @@ -489,12 +489,18 @@ let specified = ignore (Str.search_forward re model 0) ; true with Not_found -> false +let registered = ref false let register () = - if Wp.Region.get () || Wp.Region_annot.get () || - List.exists specified (Wp.Model.get ()) + if not !registered && ( + Wp.Region.get () || Wp.Region_annot.get () || + List.exists specified (Wp.Model.get ()) + ) then - Acsl_extension.register_behavior - "region" typecheck ~printer:pp_extension false + begin + registered := true ; + Acsl_extension.register_behavior "region" + typecheck ~printer:pp_extension false + end let () = Cmdline.run_after_configuring_stage register diff --git a/src/plugins/wp/Splitter.ml b/src/plugins/wp/Splitter.ml index 3f5fce9f93f2c8e3ace6ac0c84415a0d05a455b1..c2090c840991f5da2d4d15a84531bbe0b89cce27 100644 --- a/src/plugins/wp/Splitter.ml +++ b/src/plugins/wp/Splitter.ml @@ -157,12 +157,14 @@ and collect merge k vs = function let bytags (k,_) (k',_) = Tags.compare k k' -let group tag merge m = +let apply tag merge m = + (* compaction is only required when some split in m already has the tag *) let compaction = ref false in let m = List.sort bytags (List.map (fun (tgs,v) -> - if not !compaction && Tags.mem tag tgs then compaction := true ; + if not !compaction && Tags.mem tag tgs then + compaction := true ; Tags.add tag tgs , v) m) in if !compaction then compact merge m else m diff --git a/src/plugins/wp/Splitter.mli b/src/plugins/wp/Splitter.mli index 0e70bca587ec65ad7dac4d5b2731fc155adf5c12..4fc82dab9269d959dc20159b16cd7591e3fc4230 100644 --- a/src/plugins/wp/Splitter.mli +++ b/src/plugins/wp/Splitter.mli @@ -44,7 +44,7 @@ type 'a t val empty : 'a t val singleton : 'a -> 'a t -val group : tag -> ('a list -> 'a) -> 'a t -> 'a t +val apply : tag -> ('a list -> 'a) -> 'a t -> 'a t val union : ('a -> 'a -> 'a) -> 'a t -> 'a t -> 'a t val merge : diff --git a/src/plugins/wp/Stats.ml b/src/plugins/wp/Stats.ml index 60caa14eb5be10d93b07163d2f61dd2d31b3a182..50449ec8a3b466e59467fa38fc3610b3f368ae4f 100644 --- a/src/plugins/wp/Stats.ml +++ b/src/plugins/wp/Stats.ml @@ -86,9 +86,10 @@ let ptime t valid = { tmin = t ; tval = t ; tmax = t ; time = t ; tnbr = 1.0 ; success = if valid then 1.0 else 0.0 } -let pqed r = ptime r.solver_time (VCS.is_valid r) -let presult r = ptime r.prover_time (VCS.is_valid r) +let pqed r = if VCS.is_valid r then ptime r.solver_time true else pzero +let presult r = if VCS.is_valid r then ptime r.prover_time true else pzero let psolver r = ptime r.solver_time false +let psmoked = { pzero with success = 1.0 } (* -------------------------------------------------------------------------- *) (* --- Global Stats --- *) @@ -181,9 +182,7 @@ let results ~smoke prs = let cached = List.fold_left (fun c (_,r) -> if r.VCS.cached then succ c else c) 0 passed in - let stucked = List.map - (fun (p,r) -> p, ptime r.prover_time true) - passed in + let stucked = List.map (fun (p,_) -> p,psmoked) passed in let solver = List.fold_left (fun t (_,r) -> t +. r.solver_time) 0.0 passed in diff --git a/src/plugins/wp/TacChoice.ml b/src/plugins/wp/TacChoice.ml index ad538abb747f342cd3fc434edbb18064a9ef7713..27d558c7afbb2b0b75a12c6deec0a8b06c26c022 100644 --- a/src/plugins/wp/TacChoice.ml +++ b/src/plugins/wp/TacChoice.ml @@ -54,13 +54,21 @@ class absurd = inherit Tactical.make ~id:"Wp.absurd" ~title:"Absurd" - ~descr:"Contradict an Hypothesis" + ~descr:"Contradict the Goal or an Hypothesis" ~params:[] method select _feedback (s : Tactical.selection) = match s with - | Empty | Compose _ | Inside _ | Clause(Goal _) | Multi _ + | Empty | Compose _ | Inside _ | Multi _ -> Not_applicable + | Clause(Goal _) -> + let absurd (seq,goal) = + let goal = F.p_not goal in + let step = Conditions.step ~descr:"Absurd" (When goal) in + let hyps = Conditions.list seq in + let hyps = Conditions.sequence (hyps @ [step]) in + [ "Absurd", (hyps , F.p_false) ] + in Applicable absurd | Clause(Step s) -> begin match s.condition with diff --git a/src/plugins/wp/TacCompute.ml b/src/plugins/wp/TacCompute.ml new file mode 100644 index 0000000000000000000000000000000000000000..07cbeb1d70043b2755ce29dcf33438576fa958cf --- /dev/null +++ b/src/plugins/wp/TacCompute.ml @@ -0,0 +1,80 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* 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 Lang +open Tactical + +(* -------------------------------------------------------------------------- *) +(* --- Compute Term --- *) +(* -------------------------------------------------------------------------- *) + +exception Split of F.term * F.term * F.term +exception Unfold of F.term * Lang.lfun * F.term + +let head e = + if F.lc_closed e && not @@ F.is_primitive e then + match F.repr e with + | If(c,a,b) -> raise (Split(c,a,b)) + | Fun(f,es) -> raise (Unfold(e,f,TacUnfold.unfold f es)) + | _ -> () + +let process (fd : Tactical.feedback) ?at e = + try + let q = Queue.create () in + let m = ref F.Tset.empty in + let lookup e = + head e ; + m := F.Tset.add e !m ; + F.lc_iter (fun e -> Queue.push e q) e + in + lookup e ; + while not @@ Queue.is_empty q do + let e = Queue.pop q in + if not @@ F.Tset.mem e !m then lookup e ; + done ; + Not_applicable + with + | Split(a,b,c) -> + let p = F.p_bool c in + let q = F.p_not p in + fd#set_title "Compute (split)" ; + fd#set_descr "Split on if-then-else condition" ; + Applicable (Tactical.rewrite ?at ["If-Then",p,e,a;"If-Else",q,e,b]) + | Unfold(e,f,d) -> + fd#set_title "Compute (def)" ; + fd#set_descr "Unfold definition of '%s'" (Lang.name_of_lfun f) ; + Applicable (Tactical.rewrite ?at ["Definition",F.p_true,e,d]) + +class compute : Tactical.tactical = + object + inherit Tactical.make ~id:"Wp.compute" + ~title:"Compute" + ~descr:"Unfold definitions and split on conditions" + ~params:[] + method select feedback (s : Tactical.selection) = + process feedback ?at:(Tactical.at s) (Tactical.selected s) + end + +let tactical = Tactical.export (new compute) +let strategy = Strategy.make tactical ~arguments:[] + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/TacCompute.mli b/src/plugins/wp/TacCompute.mli new file mode 100644 index 0000000000000000000000000000000000000000..40e616729898b7aba4ab65ce386e7c6f81ed8f19 --- /dev/null +++ b/src/plugins/wp/TacCompute.mli @@ -0,0 +1,31 @@ +(**************************************************************************) +(* *) +(* This file is part of WP plug-in of Frama-C. *) +(* *) +(* Copyright (C) 2007-2023 *) +(* CEA (Commissariat a l'energie atomique et aux energies *) +(* 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). *) +(* *) +(**************************************************************************) + +(** Built-in Compute Tactical (auto-registered) *) + +open Tactical +open Strategy + +val tactical : tactical +val strategy : ?priority:float -> selection -> strategy + +(**************************************************************************) diff --git a/src/plugins/wp/TacUnfold.ml b/src/plugins/wp/TacUnfold.ml index dc09597c76a7ef1d1f61257fd306548e112aded8..588d32aaa93d789c2a6f5de7e8619fd75b485378 100644 --- a/src/plugins/wp/TacUnfold.ml +++ b/src/plugins/wp/TacUnfold.ml @@ -49,6 +49,9 @@ let range f es = (F.p_leq e (F.e_zint b)) in F.e_prop (F.p_all range es) +let unfold f es = + try definition f es with Not_found -> range f es + (* Used only for non Multi selection *) let rec applicable ?at e f es = function diff --git a/src/plugins/wp/TacUnfold.mli b/src/plugins/wp/TacUnfold.mli index 10e556d6405aa1680b2216975e8443a57b170631..ac7a5aefe7ffafddc3a45245e9a4ea40daf2cf99 100644 --- a/src/plugins/wp/TacUnfold.mli +++ b/src/plugins/wp/TacUnfold.mli @@ -25,6 +25,9 @@ open Tactical open Strategy +(** @raises Not_found *) +val unfold : Lang.lfun -> Lang.F.term list -> Lang.F.term + val tactical : tactical val strategy : ?priority:float -> selection -> strategy diff --git a/src/plugins/wp/Tactical.ml b/src/plugins/wp/Tactical.ml index 4d064d09b693fe222efa45e5ac0281c0946b59cf..08cb1f3e2270b19ba36166ddb4bccbc5b00eeb7d 100644 --- a/src/plugins/wp/Tactical.ml +++ b/src/plugins/wp/Tactical.ml @@ -24,13 +24,13 @@ open Conditions open Lang.F module Tmap = Map.Make(String) -let composers = ref Tmap.empty -let groups = ref [] (* -------------------------------------------------------------------------- *) (* --- Composer Factory --- *) (* -------------------------------------------------------------------------- *) +type computer = term list -> term + class type composer = object method id : string @@ -42,6 +42,10 @@ class type composer = method compute : term list -> term end +let computers : computer Tmap.t ref = ref Tmap.empty +let composers : composer Tmap.t ref = ref Tmap.empty +let groups = ref [] + let rec insert_group cc = function | [] -> [cc#group , [cc]] | (( gid , ccs ) as group ):: others -> @@ -50,12 +54,17 @@ let rec insert_group cc = function else group :: insert_group cc others +let add_computer id cc = + if not (Tmap.mem id !computers) then + computers := Tmap.add id cc !computers + let add_composer (c : #composer) = let id = c#id in - if Tmap.mem id !composers then + if Tmap.mem id !composers || Tmap.mem id !computers then Wp_parameters.error "Composer #%s already registered (skipped)" id else begin + computers := Tmap.add id (c#compute :> computer) !computers ; composers := Tmap.add id (c :> composer) !composers ; groups := insert_group (c :> composer) !groups ; end @@ -143,7 +152,15 @@ let get_int = function | Compose(Cint a) -> get_int_z a | s -> match Lang.F.repr (selected s) with - | Qed.Logic.Kint z -> get_int_z z + | Kint z -> get_int_z z + | _ -> None + +let get_bool = function + | Empty -> None + | s -> + match Lang.F.repr (selected s) with + | True -> Some true + | False -> Some false | _ -> None let subclause clause p = @@ -187,8 +204,8 @@ let cint a = Compose(Cint a) let range a b = Compose(Range(a,b)) let compose id es = try - let cc = Tmap.find id !composers in - let e = cc#compute (List.map selected es) in + let cc = Tmap.find id !computers in + let e = cc (List.map selected es) in match Lang.F.repr e with | Qed.Logic.Kint n -> cint n | _ -> Compose(Code(e,id,es)) @@ -308,14 +325,6 @@ type parameter = | Selector : 'a field * 'a named list * ('a -> 'a -> bool) -> parameter | Search : 'a named option field * 'a browser * 'a finder -> parameter -let param = function - | Checkbox{ vid } - | Spinner({vid},_) - | Composer({vid},_) - | Selector({vid},_,_) - | Search({vid},_,_) - -> vid - let checkbox ~id ~title ~descr ?(default=false) () = let fd = field ~id ~title ~descr ~default in fd , Checkbox fd @@ -353,6 +362,13 @@ let search ~id ~title ~descr ~browse ~find () = let fd = field ~id ~title ~descr ~default:None in fd , Search(fd,browse,find) +let pident = function + | Checkbox fd -> ident fd + | Spinner(fd,_) -> ident fd + | Composer(fd,_) -> ident fd + | Selector(fd,_,_) -> ident fd + | Search(fd,_,_) -> ident fd + (* -------------------------------------------------------------------------- *) (* --- Feedback --- *) (* -------------------------------------------------------------------------- *) @@ -426,8 +442,11 @@ let rewrite ?at patterns sequent = Conditions.subst (fun e -> if e == src then tgt else raise Not_found) sequent in - let step = Conditions.(step ~descr (When guard)) in - descr , Conditions.insert ?at step sequent + let sequent = + if Lang.F.eqp Lang.F.p_true guard then sequent else + let step = Conditions.(step ~descr (When guard)) in + Conditions.insert ?at step sequent + in descr , sequent ) patterns let condition name guard process seq = @@ -485,7 +504,7 @@ let export t = register t ; (t :> t) let iter f = Tmap.iter (fun _id t -> f t) !tacticals let lookup ~id = Tmap.find id !tacticals let lookup_param tactic ~id = - List.find (fun p -> param p = id) tactic#params + List.find (fun p -> pident p = id) tactic#params (* -------------------------------------------------------------------------- *) (* --- Default Composers --- *) @@ -493,6 +512,13 @@ let lookup_param tactic ~id = open Lang +let () = add_computer "wp:true" (fun _ -> e_true) +let () = add_computer "wp:false" (fun _ -> e_false) +let () = add_computer "wp:list" Vlist.list +let () = add_computer "wp:concat" Vlist.concat +let () = add_computer "wp:repeat" + (function [a;n] -> Vlist.repeat a n | _ -> raise Not_found) + let () = for i = 0 to 9 do add_composer @@ -525,6 +551,24 @@ let () = add_composer method compute = function [a;b] -> F.e_eq a b | _ -> F.e_true end) +let () = add_composer + (object + method id = "wp:neq" + method group = "logic" + method title = "A != B" + method descr = "" + method arity = 2 + method filter = function + | [a;b] -> + (try + let ta = F.typeof a in + let tb = F.typeof b in + F.Tau.equal ta tb + with Not_found -> false) + | _ -> false + method compute = function [a;b] -> F.e_neq a b | _ -> F.e_false + end) + let () = add_composer (object method id = "wp:leq" diff --git a/src/plugins/wp/Tactical.mli b/src/plugins/wp/Tactical.mli index 57b517083452d50d3b6cb8815eeffe23c81ed919..f313adde10789845b814992fcbdcc7cbc1d70e86 100644 --- a/src/plugins/wp/Tactical.mli +++ b/src/plugins/wp/Tactical.mli @@ -54,6 +54,7 @@ val range : int -> int -> selection val compose : string -> selection list -> selection val multi : selection list -> selection val get_int : selection -> int option +val get_bool : selection -> bool option val destruct : selection -> selection list val head : clause -> pred @@ -101,7 +102,7 @@ type parameter = val ident : 'a field -> string val default : 'a field -> 'a val signature : 'a field -> 'a named -val param : parameter -> string +val pident : parameter -> string val checkbox : id:string -> title:string -> descr:string -> @@ -261,5 +262,7 @@ val iter : (tactical -> unit) -> unit val lookup : id:string -> tactical val lookup_param : tactical -> id:string -> parameter +type computer = term list -> term +val add_computer : string -> computer -> unit val add_composer : #composer -> unit val iter_composer : (composer -> unit) -> unit diff --git a/src/plugins/wp/VCS.ml b/src/plugins/wp/VCS.ml index ca000ced16280f15aba38e639191a32204a575b0..e4b0d5f91ee8baa7568ceed61c3eb824b57ce482 100644 --- a/src/plugins/wp/VCS.ml +++ b/src/plugins/wp/VCS.ml @@ -140,6 +140,11 @@ let cmp_prover p q = let pp_prover fmt p = Format.pp_print_string fmt (title_of_prover p) let pp_mode fmt m = Format.pp_print_string fmt (title_of_mode m) +let provers () = + List.map (fun p -> Why3 p) @@ + List.filter Why3Provers.is_mainstream @@ + Why3Provers.provers () + module P = struct type t = prover let compare = cmp_prover end module Pset = Set.Make(P) module Pmap = Map.Make(P) @@ -150,28 +155,31 @@ module Pmap = Map.Make(P) type config = { valid : bool ; - timeout : int option ; + timeout : float option ; stepout : int option ; } -let param f = let v = f() in if v>0 then Some v else None - -let current () = { - valid = false ; - timeout = param Wp_parameters.Timeout.get ; - stepout = param Wp_parameters.Steps.get ; -} +let current () = + let t = Wp_parameters.Timeout.get () in + let s = Wp_parameters.Steps.get () in + { + valid = false ; + timeout = if t > 0 then Some (float t) else None ; + stepout = if s > 0 then Some s else None ; + } let default = { valid = false ; timeout = None ; stepout = None } let get_timeout ?kf ~smoke = function | { timeout = None } -> if smoke - then Wp_parameters.SmokeTimeout.get () - else begin match Option.map Wp_parameters.FctTimeout.find kf with - | exception Not_found | None -> Wp_parameters.Timeout.get () - | Some timeout -> timeout - end + then float @@ Wp_parameters.SmokeTimeout.get () + else + let t = + match Option.map Wp_parameters.FctTimeout.find kf with + | None | exception Not_found -> Wp_parameters.Timeout.get () + | Some timeout -> timeout + in float t | { timeout = Some t } -> t let get_stepout = function @@ -226,14 +234,14 @@ let configure r = let timeout = let t = r.prover_time in if t > 0.0 then - let timeout = Wp_parameters.Timeout.get() in - let margin = Wp_parameters.TimeExtra.get() + int_of_float (t +. 0.5) in - Some(max timeout margin) + let timeout = float @@ max 0 @@ Wp_parameters.Timeout.get() in + let margin = float @@ max 0 @@ Wp_parameters.TimeExtra.get () in + Some(timeout +. margin) else None in let stepout = if r.prover_steps > 0 && r.prover_time <= 0.0 then - let stepout = Wp_parameters.Steps.get () in + let stepout = max 0 @@ Wp_parameters.Steps.get () in let margin = 1000 in Some(max stepout margin) else None in @@ -274,7 +282,7 @@ let no_result = result NoResult let valid = result Valid let invalid = result Invalid let unknown = result Unknown -let timeout t = result ~time:(float t) Timeout +let timeout t = result ~time:t Timeout let stepout n = result ~steps:n Stepout let computing kill = result (Computing kill) let failed ?pos msg = { diff --git a/src/plugins/wp/VCS.mli b/src/plugins/wp/VCS.mli index 29098111ebd50b50a89f9a8723d8d4440768b5de..f5ecae0ad98af6fd9801480d86414028ac29c025 100644 --- a/src/plugins/wp/VCS.mli +++ b/src/plugins/wp/VCS.mli @@ -41,6 +41,9 @@ type mode = module Pset : Set.S with type elt = prover module Pmap : Map.S with type key = prover +(** Mainstream installed provers *) +val provers : unit -> prover list + val name_of_prover : prover -> string val title_of_prover : ?version:bool -> prover -> string val filename_for_prover : prover -> string @@ -62,7 +65,7 @@ val cmp_prover : prover -> prover -> int type config = { valid : bool ; - timeout : int option ; + timeout : float option ; stepout : int option ; } @@ -70,8 +73,8 @@ val current : unit -> config (** Current parameters *) val default : config (** all None *) -val get_timeout : ?kf:Kernel_function.t -> smoke:bool -> config -> int -(** 0 means no-timeout *) +val get_timeout : ?kf:Kernel_function.t -> smoke:bool -> config -> float +(** 0.0 means no-timeout *) val get_stepout : config -> int (** 0 means no-stepout *) @@ -102,7 +105,7 @@ val valid : result val invalid : result val unknown : result val stepout : int -> result -val timeout : int -> result +val timeout : float -> result val computing : (unit -> unit) -> result val failed : ?pos:Lexing.position -> string -> result val kfailed : ?pos:Lexing.position -> ('a,Format.formatter,unit,result) format4 -> 'a diff --git a/src/plugins/wp/Vlist.ml b/src/plugins/wp/Vlist.ml index 0673d24fb816bef8a16b0768963a7e7579fe7579..05f905cc0cde2cfbed4389c36ca1782a9a4a648a 100644 --- a/src/plugins/wp/Vlist.ml +++ b/src/plugins/wp/Vlist.ml @@ -51,6 +51,8 @@ let l_repeat = E.(F_call "repeat") let () = LogicBuiltins.add_type t_list ~library ~link:l_list () let a_list = Lang.get_builtin_type ~name:t_list +let alist e = L.Data(a_list,[e]) + let vlist_get_tau = function | None -> invalid_arg "a list operator without result type" | Some t -> t @@ -63,11 +65,11 @@ let ty_listelt = function let ty_cons = function | [ _ ; Some l ] -> l - | [ Some e ; _ ] -> L.Data(a_list,[e]) + | [ Some e ; _ ] -> alist e | _ -> raise Not_found let ty_elt = function - | [ Some e ] -> L.Data(a_list,[e]) + | [ Some e ] -> alist e | _ -> raise Not_found let ty_nth = function @@ -149,6 +151,14 @@ let v_concat es tau = F.e_fun f_concat es ~result:tau let v_length l = F.e_fun f_length [l] let v_repeat s n tau = F.e_fun f_repeat [s;n] ~result:tau +let concat vs = + let tl = Lang.F.typeof (List.hd vs) in + v_concat vs tl + +let list es = concat (List.map v_elt es) + +let repeat s n = v_repeat s n (Lang.F.typeof s) + (* -------------------------------------------------------------------------- *) (* --- Rewriters --- *) (* -------------------------------------------------------------------------- *) @@ -480,6 +490,10 @@ let check_term e = | _ -> false with Not_found -> false +let elist (t : tau) = + match t with + | L.Data(_,[e]) when check_tau t -> Some e + | _ -> None let f_vlist_eq = Lang.extern_f ~library ~sort:L.Sprop "vlist_eq" @@ -545,10 +559,10 @@ let rec collect xs = function | _ -> List.rev xs , w end -let list engine fmt xs = Qed.Plib.pp_listsep ~sep:"," engine#pp_flow fmt xs +let pplist engine fmt xs = Qed.Plib.pp_listsep ~sep:"," engine#pp_flow fmt xs let elements (engine : #engine) fmt xs = - Format.fprintf fmt "@[<hov 2>[ %a ]@]" (list engine) xs + Format.fprintf fmt "@[<hov 2>[ %a ]@]" (pplist engine) xs let rec pp_concat (engine : #engine) fmt es = let xs , es = collect [] es in @@ -569,7 +583,7 @@ let pretty (engine : #engine) fmt es = let pprepeat (engine : #engine) fmt = function | [l;n] -> Format.fprintf fmt "@[<hov 2>(%a *^@ %a)@]" engine#pp_flow l engine#pp_flow n - | es -> Format.fprintf fmt "@[<hov 2>repeat(%a)@]" (list engine) es + | es -> Format.fprintf fmt "@[<hov 2>repeat(%a)@]" (pplist engine) es let shareable e = match F.repr e with diff --git a/src/plugins/wp/Vlist.mli b/src/plugins/wp/Vlist.mli index 85106e3192f96fbd29c0bcb81e6d56d58daa2c2f..2074985d3459982939348331ac881a72d7ed6599 100644 --- a/src/plugins/wp/Vlist.mli +++ b/src/plugins/wp/Vlist.mli @@ -28,6 +28,8 @@ open Lang val check_tau : tau -> bool val check_term : F.term -> bool +val alist : tau -> tau (* element -> list of element *) +val elist : tau -> tau option (* list -> element *) class type engine = object @@ -43,6 +45,10 @@ val f_cons : Fun.t val f_concat : Fun.t val f_repeat : Fun.t +val list : F.term list -> F.term +val concat : F.term list -> F.term +val repeat : F.term -> F.term -> F.term + val export : #engine -> Format.formatter -> F.term list -> unit val pretty : #engine -> Format.formatter -> F.term list -> unit val elements : #engine -> Format.formatter -> F.term list -> unit diff --git a/src/plugins/wp/WpTac.ml b/src/plugins/wp/WpTac.ml index 65ac410e6444673719c15da7799f3d4c0486f2fb..6c33b85936cae84d7e39772c6532bd3f4489a7b8 100644 --- a/src/plugins/wp/WpTac.ml +++ b/src/plugins/wp/WpTac.ml @@ -371,7 +371,7 @@ let e_dnf = cnf_dnf ~pol:false (* feature at Conditions.closure and also for debugging purposes *) let () = Conditions.at_closure (fun ((step,goal) as sequent) -> - match Wp_parameters.SplitDepth.get () with + match Wp_parameters.SplitCNF.get () with | 0 -> sequent | depth when depth < -1 -> (* Unspecified debug mode checking the correctness of CNF algo: diff --git a/src/plugins/wp/cfgAnnot.ml b/src/plugins/wp/cfgAnnot.ml index b06baf97c1cfac7aeb5ab70538446143bdfa1ca7..5eb9442a2b603221781c6716b14af5620a0c5355 100644 --- a/src/plugins/wp/cfgAnnot.ml +++ b/src/plugins/wp/cfgAnnot.ml @@ -59,8 +59,7 @@ type behavior = { let normalize_assumes h = let module L = NormAtLabels in - let labels = L.labels_fct_pre in - L.preproc_annot labels h + L.preproc_annot L.labels_fct_pre h let implies ?assumes p = match assumes with None -> p | Some h -> Logic_const.pimplies (h,p) @@ -77,7 +76,8 @@ let normalize_pre ~goal kf bhv ?assumes ip = let id = WpPropId.mk_pre_id kf Kglobal bhv ip in let pre = ip.ip_content.tp_statement in let assumes = Option.map normalize_assumes assumes in - Some (id, L.preproc_annot labels @@ implies ?assumes pre) + let precond = L.preproc_annot labels pre in + Some (id, implies ?assumes precond) else None let normalize_post ~goal kf bhv tk ?assumes (itk,ip) = @@ -87,8 +87,8 @@ let normalize_post ~goal kf bhv tk ?assumes (itk,ip) = let assumes = Option.map (fun p -> normalize_assumes @@ at_pre p) assumes in let labels = L.labels_fct_post ~exit:(tk=Exits) in let id = WpPropId.mk_post_id kf Kglobal bhv (tk,ip) in - let p = L.preproc_annot labels ip.ip_content.tp_statement in - Some (id , implies ?assumes p) + let post = L.preproc_annot labels ip.ip_content.tp_statement in + Some (id , implies ?assumes post) else None let normalize_decreases (d, li) = @@ -464,7 +464,7 @@ module CodeAssertions = WpContext.StaticGenerator(CodeKey) let get_code_assertions ?(smoking=false) kf stmt = let ca = CodeAssertions.get (kf,stmt) in - (* Make sur that smoke tests are in the end so that it can see surely false + (* Make sure that smoke tests are in the end so that it can see surely false assertions associated to this statement, in particular RTE assertions. *) List.rev @@ if smoking then @@ -607,20 +607,22 @@ module LoopContract = WpContext.StaticGenerator(CodeKey) end) let get_loop_contract ?(smoking=false) ?terminates kf stmt = + (* Loop Contract *) let lc = LoopContract.get (kf,stmt) in - let lc_smoke = if smoking && not (WpReached.is_dead_code stmt) then + (* Loop Smoking *) + let lc = + if smoking && not (WpReached.is_dead_code stmt) then let g = smoke kf ~id:"dead_loop" ~unreachable:stmt () in { lc with loop_smoke = g :: lc.loop_smoke } else lc in - match lc_smoke.loop_terminates, terminates with - | None, _ -> - lc_smoke - | Some _, None -> - { lc_smoke with loop_terminates = None } + (* Loop Termination *) + match lc.loop_terminates, terminates with + | None, _ -> lc + | Some _, None -> { lc with loop_terminates = None } | Some loop_terminates, Some terminates -> let prop = Logic_const.pimplies(terminates, loop_terminates) in - { lc_smoke with loop_terminates = Some prop } + { lc with loop_terminates = Some prop } (* -------------------------------------------------------------------------- *) (* --- Clear Tablesnts --- *) diff --git a/src/plugins/wp/cfgCalculus.ml b/src/plugins/wp/cfgCalculus.ml index a57a8c1c06971d053fa9d0b4ed8c192644f50d51..d5c81fc3a8f8cc73ac000dc3f387b87a496ed1f3 100644 --- a/src/plugins/wp/cfgCalculus.ml +++ b/src/plugins/wp/cfgCalculus.ml @@ -219,8 +219,7 @@ struct let kl = Cil.CurrentLoc.get () in try Cil.CurrentLoc.set (Stmt.loc s) ; - let smoking = - is_default_bhv env.mode && env.dead s in + let smoking = is_default_bhv env.mode && env.dead s in let cas = CfgAnnot.get_code_assertions ~smoking env.mode.kf s in let opt_fold f = Option.fold ~none:Fun.id ~some:f in let do_assert env CfgAnnot.{ code_admitted ; code_verified } w = diff --git a/src/plugins/wp/cfgInfos.ml b/src/plugins/wp/cfgInfos.ml index a24e5e48c2ec87eec13edb2ab073939f1efea6cd..b2da833c128c9d7f53688d0c0988cb167a440607 100644 --- a/src/plugins/wp/cfgInfos.ml +++ b/src/plugins/wp/cfgInfos.ml @@ -52,10 +52,11 @@ let calls infos = infos.calls let annots infos = infos.annots let doomed infos = infos.doomed -let wpreached s = function +let wp_reached_smoking s = function | None -> false | Some reachability -> WpReached.smoking reachability s -let smoking infos s = wpreached s infos.reachability + +let smoking infos s = wp_reached_smoking s infos.reachability let unreachable infos v = match infos.body, infos.checkpath with @@ -457,7 +458,7 @@ let compile Key.{ kf ; smoking ; bhv ; prop } = let loop_pids = loop_contract_pids kf stmt in if dead then begin - if wpreached stmt reachability then + if wp_reached_smoking stmt reachability then (let p = CfgAnnot.get_unreachable kf stmt in infos.doomed <- Bag.append infos.doomed p) ; infos.doomed <- Bag.concat infos.doomed (Bag.list ca_pids) ; diff --git a/src/plugins/wp/cfgWP.ml b/src/plugins/wp/cfgWP.ml index 096f49bb1336ec56d905cf2d770d86560b59b690..2e20c87f609994abbe5ea888efda2b9009527081 100644 --- a/src/plugins/wp/cfgWP.ml +++ b/src/plugins/wp/cfgWP.ml @@ -859,9 +859,9 @@ struct let condition ~descr ?stmt ?warn pa h vc = passify_vc pa (assume_vc ?stmt ?warn ~descr h vc) - let mark ?(smoke=false) m = function + let split_branch ~smoke tag = function | None -> Splitter.empty - | Some s -> if smoke then s else Splitter.group m merge_vcs s + | Some s -> if smoke then s else Splitter.apply tag merge_vcs s let random () = let v = Lang.freshvar ~basename:"cond" Logic.Bool in @@ -883,7 +883,7 @@ struct in let effects = Eset.union wp1.effects wp2.effects in let dosplit = - Wp_parameters.Split.get () && + Wp_parameters.SplitBranch.get () && let n1 = weight wp1.vcs in let n2 = weight wp2.vcs in let nm = Wp_parameters.SplitMax.get () in @@ -898,8 +898,8 @@ struct Gmap.merge (fun g w1 w2 -> let smoke = TARGET.is_smoke_test g in - let s1 = mark ~smoke (Splitter.if_then stmt) w1 in - let s2 = mark ~smoke (Splitter.if_else stmt) w2 in + let s1 = split_branch ~smoke (Splitter.if_then stmt) w1 in + let s2 = split_branch ~smoke (Splitter.if_else stmt) w2 in Some (Splitter.union (merge_vc) s1 s2) ) vcs1 vcs2 else @@ -918,7 +918,7 @@ struct (* -------------------------------------------------------------------------- *) let rec cc_case_values ks vs sigma = function - | [] -> ks , vs + | [] -> List.rev ks , List.rev vs | e::es -> match Ctypes.get_int64 e with | Some k -> @@ -927,11 +927,16 @@ struct cc_case_values ks (C.val_of_exp sigma e::vs) sigma es let cc_group_case stmt warn descr tag pa cond vcs : vc Splitter.t Gmap.t = - Gmap.map - (fun s -> + let split = + Wp_parameters.SplitSwitch.get () && + weight vcs < Wp_parameters.SplitMax.get () + in + Gmap.mapi + (fun g s -> + let smoke = TARGET.is_smoke_test g in Splitter.map (condition ~descr ~warn ~stmt pa cond) - (Splitter.group tag merge_vcs s) + (if smoke || not split then s else Splitter.apply tag merge_vcs s) ) vcs let cc_case stmt warn sigma v (es,wp) = @@ -971,7 +976,7 @@ struct let vcs_cases = List.map (cc_case stmt warn sigma value) cases in let neq = List.map (fun (vs,_) -> p_all (p_neq value) vs) vcs_cases in let vcs_default = cc_default stmt sigma neq default in - let vcs = merge_all_vcs ( vcs_default :: List.map snd vcs_cases ) in + let vcs = merge_all_vcs ( vcs_default :: List.rev_map snd vcs_cases ) in let effects = List.fold_left (fun es (_,wp) -> Eset.union es wp.effects) default.effects cases in @@ -1041,7 +1046,7 @@ struct (fun s -> Splitter.map (fun vc -> passify_vc pa (instance_of vc)) - (Splitter.group tag merge_vcs s) + (Splitter.apply tag merge_vcs s) ) wp.vcs let call_dynamic wenv stmt gpid fct calls = L.in_frame wenv.frame @@ -1525,7 +1530,7 @@ struct let hyps = Conditions.bundle vc.hyps in let goal g = { vcq with VC_Annot.goal = GOAL.make (hyps,g) } in match F.p_expr vc.goal with - | Logic.And gs when Wp_parameters.Split.get () -> Bag.list (List.map goal gs) + | Logic.And gs when Wp_parameters.SplitConj.get () -> Bag.list (List.map goal gs) | _ -> Bag.elt (goal vc.goal) let make_trivial vc = diff --git a/src/plugins/wp/doc/manual/wp_plugin.tex b/src/plugins/wp/doc/manual/wp_plugin.tex index 14c71ecce55c800cae91fe75fe0c123d0d9a3b1d..4f31910e4a20419e5b56ef1609ab009ea5b3bcb9 100644 --- a/src/plugins/wp/doc/manual/wp_plugin.tex +++ b/src/plugins/wp/doc/manual/wp_plugin.tex @@ -272,7 +272,10 @@ for marking, the option \verb+-wp-finalize-scripts+ can be used to remove all orphan scripts and the marking directory. The option \verb+-wp-dry-finalize-scripts+ can be used to log the remove actions instead of actually doing them. -\subsection{Strategies} +\subsection{Strategies (DEPRECATED)} + +\paragraph[Warning:] Strategies described below are \emph{deprecated} since Frama-C 27.0 (Cobalt). +Please use ``Proof Strategies'' instead (Section~\ref{wp-proof-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 \textsf{WP} plug-in ; however, the user can extends the proof editor with @@ -304,8 +307,12 @@ The name of registered strategies is printed on console by using \texttt{-wp-aut \subsection{General Tactics} -\paragraph{Absurd} Contradict a Hypothesis\\ -The user can select a hypothesis $H$, and change the goal to $\neg H$: +\paragraph{Absurd} Contradict the Goal or an Hypothesis\\ +The user can prove the goal by contradiction: + +$$ \TACTIC{\Delta\models\,G}{\Delta,\neg G\models\,\mathtt{false}} $$ + +Or the user can select a hypothesis $H$, and change the goal to $\neg H$: $$ \TACTIC{\Delta,H\models\,G}{\Delta\models\,\neg H} $$ @@ -865,12 +872,16 @@ interface of the programmatic API. \texttt{@decreases}, \texttt{\mbox{@complete\_behaviors}}, \texttt{\mbox{@disjoint\_behaviors}}. \\ - Properties can be prefixed with a minus sign to \emph{skip} the associated annotations. + Tags and categories can be prefixed with a minus sign to \emph{skip} + the associated annotations. For example \texttt{-wp-prop="-@assigns"} removes all \texttt{assigns} 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 \textsf{WP}. + Tag names also include the name of the function or + lemma associated with the property. + \\ + \textbf{Remark:} properties with tag name \verb+no_wp:+ are always and automatically + filtered out 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 @@ -1014,14 +1025,16 @@ weakest precondition calculus. 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 +\item[\tt -wp-(no)-split] Splits conditional statements into separated goals (default is: \texttt{no}). +\item[\tt -wp-(no)-split-switch] Splits switch statements into sepeared goals (default is: \texttt{yes}). +\item[\tt -wp-split-max <{\it n}>] + limits the number of sub-goals generated by \verb|-wp-split| and \verb|-wp-split-switch| + (defaults to \verb+1000+). +\item[\tt -wp-(no)-split-conj] 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 <{\it d}>] sets the depth of exploration for the - \texttt{-wp-split} option. ``-1'' stands for unlimited depth. Default is 0. -\item[\tt -wp-split-max <{\it n}>] When \verb+-wp-split+ is active, - limit the number of generated sub-goals to \textit{n} parts on each conditional statement. - (defaults to \verb+1000+). +\item[\tt -wp-split-cnf <{\it d}>] transforms all goals with in conjunctive normal form (CNF) at depth {\tt\it d}. + Value \verb|-1| stands for unlimited depth. Default is 0, which means no CNF transformation. \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}). @@ -1301,6 +1314,21 @@ See \texttt{-wp-interactive <mode>} option for details. 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. + + You may also select provers \verb|"tip"| to use proof strategies and \verb|"script"| to use + proof scripts (without applying new proof strategies), + see option \verb|"-wp-script"| below for more details. +\item[\tt -wp-script <mode>] selects how to manage proof strategies and proof + scripts session. Several modes are available: + \begin{itemize} + \item \texttt{"batch"} use existing scripts, but do not store new scripts. + This is the default mode for prover \verb|"script"|. + \item \texttt{"update"} use existing scripts and store new or updated scripts in proof session. + This is the default mode for prover \verb|tip|. + \item \texttt{"init"} don't use existing scripts and store the newly generated + scripts in proof session. + \item \texttt{"dry"} don't use existing script and don't store any new scripts in proof session. + \end{itemize} \item[\tt -wp-interactive <mode>] selects the interaction mode with interactive provers such as Coq (while it could work for other interactive provers, it has not been tested so far). Five modes are available: @@ -1313,6 +1341,8 @@ See \texttt{-wp-interactive <mode>} option for details. \end{itemize} New scripts are created in the \texttt{interactive} directory of \textsf{WP} session (see option \texttt{-wp-session <dir>}). + In case option \verb|-wp-cache-env| is set, the script mode is taken from environment + variable \verb|FRAMAC_WP_SCRIPT| instead. \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}. @@ -1321,6 +1351,8 @@ See \texttt{-wp-interactive <mode>} option for details. \item[\tt -wp-(no)-run-all-provers] Run all specified provers on each goal not proved by Qed. When a prover succeeds in proving the goal, the others are not stopped. (default is: no). +\item[\tt -wp-strategy s,...] specifies the default + ones to be used, see Section~\ref{wp-proof-strategies} for details. \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 @@ -1335,12 +1367,10 @@ See \texttt{-wp-interactive <mode>} option for details. \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-timeout <n>] sets the timeout (in seconds) for the calls - to the decision prover (defaults to 10 seconds). + to the decision prover (defaults to 2 seconds). \item[\tt -wp-fct-timeout <f1:t1,f2:t2,...>] customize the timeout for each specified function (\texttt{t1} for \texttt{f1}, \texttt{t2} for \texttt{f2}, etc). -\item[\tt -wp-smoke-timeout <n>] sets the timeout (in seconds) for smoke tests - (see \verb+-wp-smoke-tests+, defaults to 5 seconds). \item[\tt -wp-interactive-timeout <n>] sets the timeout (in seconds) for checking edited scripts with interactive provers (defaults to 30 seconds). \item[\tt -wp-(no)-script-on-stdout] displays generated proof scripts on stdout @@ -1420,9 +1450,12 @@ removed when \textsf{Frama-C} exits. Other options controlling the output of generated proof obligations are: \begin{description} -\item[\tt -wp-(no)-print] pretty-prints the generated proof obligations on +\item[\tt -wp-print] pretty-prints the generated proof obligations on the standard output. Results obtained by provers are reported as - well (default is: \texttt{no}). + well. +\item[\tt -wp-status] pretty-prints only proof obligations that are not (yet) + proved on the standard output. In case of script, prints all the non-proved + sub-goals of the script. \item[\tt -wp-out <dir>] sets the user directory where proof obligations are saved. The directory is created if it does not exist yet. Its content is not cleaned up automatically. @@ -1593,15 +1626,13 @@ The main option to control cache usage is \verb+-wp-cache+, documented below: \begin{description} \item[\tt -wp-cache <mode>] selects the cache mode to use with \textsf{Why-3} provers. The default mode is \verb'update' if there is \textsf{WP} session - available, and \verb+none+ otherwise. You can also use the environment - variable \texttt{FRAMAC\_WP\_CACHE} instead. + available, and \verb+none+ otherwise. \item[\tt -wp-cache-dir <dir>] select the directory where cached results are stored. By default, the cache is store in the \textsf{WP} session directory, when available. - You can also use the environment variable - \texttt{FRAMAC\_WP\_CACHEDIR} instead. -\item[\tt -wp-cache-env] gives environment variables the precedence over command line options. - By default, the command line options take precedence, as usual. +\item[\tt -wp-cache-env] makes environment variables + \verb|FRAMAC_WP_CACHE|, \verb|FRAMAC_WP_CACHEDIR| and \verb|FRAMAC_WP_SCRIPT| + override command line options \verb|-wp-cache|, \verb|-wp-cachedir| and \verb|-wp-script|, respectively. \end{description} The available cache modes are described below: @@ -1616,16 +1647,7 @@ The available cache modes are described below: When using cache with a non-\verb+offline+ mode, time and steps limits recorded in the cache are compared to the command line settings to produce meaningful and consistent results. Hence, if you provide more time or more steps from the command line than before, the prover would be run again. If you provide less or equal limits, the cache entries are reused, but \textsf{WP} still report the cached time and step limits to inform you of your previous attempts. For instance, if you have in the cache a « Valid » entry with time 12.4s and re-run it with a timeout of 5s, you will have a « Timeout » result with time 12.4s printed on the console. -\section{Plug-in Developer Interface} -\label{wp-api} - -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. - -\section{Proof Obligation Reports} +\subsection{Proof Obligation Reports} The \textsf{WP} plug-in can export statistics on generated proof obligations. These statistics are called \textit{WP reports} and are @@ -1640,17 +1662,395 @@ Reports are generated with the following command-line options: \begin{description} \item[\tt -wp-report <Rspec$_1$,...,Rspec$_n$>] specifies the list of reports to export. - Each value \texttt{Rspec$_i$} is a \textit{WP report} specification file - (described below). + Each value \texttt{Rspec$_i$} is a report template specification file. + See Section~\ref{wp-template-reports} for details on their structure. \item[\tt -wp-report-basename <name>] set the basename for exported reports (described below). \item[\tt -wp-report-json <file>.json] output the proof report in JSON format. + See Section~\ref{wp-json-reports} for details on the JSON report format. \end{description} -See sections below for details on the generated report formats. +\subsection{Persistent Options} +\label{wp-persistent} -\clearpage -\subsection{JSON Reports} +As a general observation, almost \emph{none} of the internal +\textsf{WP} data is kept in memory after each execution. Most of the +generated proof-obligation data is stored on disk before being sent to +provers, and they are stored in a temporary directory that is removed +upon \textsf{Frama-C} exit (see also \texttt{-wp-out} option). + +The only information which is added to the \textsf{Frama-C} kernel +consists in a new status for those properties proved by \textsf{WP} plug-in with +their dependencies. + +Thus, when combining \textsf{WP} +options with \texttt{-then}, \texttt{-save} and \texttt{-load} +options, the user should be aware of the following precisions: +\begin{description} +\item[\tt -wp, -wp-prop, -wp-fct, -wp-bhv.] These options make the + \textsf{WP} plug-in generate proof-obligations for the selected + properties. The values of these options are never saved and they are + cleared by \texttt{-then}. Hence, running \texttt{-wp-prop A} + \texttt{-then} \texttt{-wp-fct F} does what you expect: + properties tagged by \texttt{A} are proved only once. +\item[\tt -wp-print, -wp-status, -wp-prover, -wp-gen, -wp-detect.] + These options do not + generate new proof-obligations, but run other actions on all + previously generated ones. For the same reasons, they are not saved + and cleared by \texttt{-then}. +\item[\tt -wp-xxx.] All other options are tunings that can be easily + turned on and off or set to the desired value. + They are saved and kept across \texttt{-then} commands. +\end{description} + +\section{Proof Strategies} +\label{wp-proof-strategies} + +\emph{Introduced since Frama-C 28.0 (Nickel)} + +Proof obligations generated by \textsf{WP} are usually discharged by an +\textsf{SMT} solver specified by the user through command line option +\verb$-wp-prover$. As described in previous sections, complex proof obligations +may also be split into simpler sub-goals by applying \emph{Tactics} from the +\textsf{TIP} user interface. + +Proof strategies provide user-defined heuristics to automatically try various +combinations of provers, timeouts and tactics, depending on the proof +context. This is a much more effective technique than relying on manually edited +scripts through the \textsf{TIP} user interface. Here are some benefits of using +proof strategies: +\begin{itemize} +\item Proof strategies are automatic: there is no need for entering GUI session. +\item Proof strategies can be associated to individual functions, lemmas or properties, + or tried globally. +\item Tactics are applied following patterns: depending on your case study, you can + define fine-tuned strategies to solve your common issues. +\item Proof strategies are compatible with TIP-based scripts: you can use + strategies to complete scripts and conversely. +\item Scripts are easier to replay and to update: each proof node now records + which strategy was involved in the past, so that incomplete or broken proofs + can be recovered easily. +\end{itemize} + +Proof Strategies are defined thanks to dedicated ACSL extensions and controlled +by specific command-line options. Note that those extensions are only available +when command-line option \verb+-wp-strategy+ is specified. The syntax of ACSL +extensions for proof strategies is defined below: + +\newcommand{\pdots}{\,,\,\ldots,\,} + +\begin{center} + \begin{tabular}{l} + \verb+@strategy+ \textit{name}\,: \\ + \quad\quad\textit{alternative}\,, \\ + \quad\quad\ldots, \\ + \quad\quad\textit{alternative}\,; \\ + \\ + \verb+@proof+ \textit{name}\,: \textit{target}\pdots\textit{target}\,; + \end{tabular} +\end{center} + +A \emph{strategy} must be defined by a unique name and consists of a list of +\emph{alternatives} that will be tried in order until proof completion. + +Proof hints can be specified to associate strategies to lemma, function or +property names. Hints consists of a strategy name to be used for one or many +proof targets. Targets follow the same conventions than \verb$-wp-prop$ +command-line option, although quotes might be necessary, +e.g. \verb$"@requires"$. A proof hint specification applies for all properties +matching the property filter. Many proof hints might apply, in which +case, proof hints will be tried in order. + +Strategies shall be defined \emph{before} being used as proof hints. It is +recommended to write strategies in separated \verb$*.c$ or \verb$*.i$ files and +to write proof hints right after their target definition. + +Strategy consists of list of alternatives with the following syntax: + +\begin{center} + \begin{tabular}{l} + \textit{alternative} $::=$ \\ + \quad$|$\quad\verb+\prover+(\verb+"p"+\pdots\verb+"p"+, \textit{timeout}) \\ + \quad$|$\quad\verb+\tactic+(\verb+"id"+, \textit{param}\pdots\textit{param}) \\ + \quad$|$\quad\verb+\auto+(\verb+"id"+\pdots\verb+"id"+) \\ + \quad$|$\quad\verb+\default+ \\ + \quad$|$\quad\textit{strategy} + \end{tabular} +\end{center} + +Each form \emph{alternative} consists of one possible solution to discharge a proof obligation: +\begin{itemize} +\item \verb+\provers(p,...,p,time)+ will try the specified provers in sequence + with a specified timeout. Provers and/or timeout can be omitted, in such a case the + command-line options \verb+-wp-prover+ and \verb+-wp-timeout+ are used instead. + Sub-second timeout can also be specified, eg. \verb+0.2+ for 200 milliseconds. Prover + names must be individually quoted, with the same syntax as \verb+-wp-prover+ + command line option. +\item \verb+\tactic(id,prm...)+ will try to apply the specified tactic with the + associated parameters. Tactic parameters allow to select the target of the tactic, + and the strategy to be used on generated sub-goals. +\item \verb+\auto(id,...)+ will try to apply the (deprecated) auto-strategies + available in \textsf{WP} versions prior to Cobalt. +\item \textit{name} or \verb$\default$ tries the specified strategy. +\end{itemize} + +The default strategy consists in applying the strategies specified through the +command-line option \verb+-wp-strategy s,...+, in order. + +Tactic parameters are specified using the following syntax: + +\begin{center} + \begin{tabular}{l} + \textit{param} $::=$ \\ + \quad$|$\quad\verb+\goal+(\textit{pattern},\ldots) \\ + \quad$|$\quad\verb+\when+(\textit{pattern},\ldots) \\ + \quad$|$\quad\verb+\ingoal+(\textit{pattern},\ldots) \\ + \quad$|$\quad\verb+\incontext+(\textit{pattern},\ldots) \\ + \quad$|$\quad\verb+\pattern+(\textit{pattern},\ldots) \\ + \quad$|$\quad\verb+\select+(\textit{pattern}) \\ + \quad$|$\quad\verb+\param+(\textit{id},\textit{value}) \\ + \quad$|$\quad\verb+\child+(\textit{id},\textit{strategy}) \\ + \quad$|$\quad\verb+\children+(\textit{strategy}) \\ + \end{tabular} +\end{center} + +Tactic parameters are interpreted as follows: +\begin{itemize} +\item \verb+\goal(ps)+, \verb+\when(ps)+ and other patterns are used to + match parts of the current proof node. The form \verb+\when(ps)+ looks + for top-level hypotheses patterns, \verb+\goal(ps)+ for top-level goal patterns. + Form \verb+\ingoal(ps)+ and \verb+\incontext(ps)+ respectectively matches patterns + deeper inside the goal or the hypotheses, and finally + \verb+\pattern(ps)+ searches in the entire proof obligation. + When several patterns are given, all must apply and agree on common pattern variables. + Pattern syntax is specified below. +\item \verb+\select(v)+ defines the main target of the selected tactic. The + value \verb+v+ uses the same syntax as patterns, with pattern variables + replaced with their matched values. Few tactics support multiple selection, + in which case, multiple values can be provided. + When no selection is specified, the first + specified pattern is used as an implicit target. When no selection nor pattern + is selected, the default selection is the proof goal. +\item \verb+\param(p,v)+ configures the parameter value \verb+p+ of the selected + tactic with the associated value. +\item \verb+\child(a,s)+ applies strategy \verb+s+ to prove the sub-goal named + \verb+a+ of the tactic. +\item \verb+\children(s)+ applies strategy \verb+s+ on (other) sub-goals of the + tactic. If unspecified, the strategy used for the current node is applied. +\end{itemize} + +Tactics identifiers and their parameters can be obtained from the command line: +\begin{itemize} +\item \verb|frama-c -wp-tactic ?| lists all the registered tactic identifiers; +\item \verb|frama-c -wp-tactic id,...| prints detailed infos for the selected tactics. +\end{itemize} + +Patterns and values are a closed to raw proof obligation formulae, with the +following restrictions and meaning: +\begin{itemize} +\item variables are pattern variables; +\item pattern \verb+_+ matches any value; +\item pattern \verb+x:p+ matches pattern \verb+p+ and bind its value to variable \verb+x+; +\item pattern \verb+a..b+ matches integer constants in the specified (constant) range. +\item pattern \verb+\any(p,...)+ matches any of the specified patterns. +\item patterns \verb+p[k]+ and \verb+p[k->v]+ matches array operations, e.g. for memory models; +\item ACSL operators have their usual meaning; +\item ACSL list operators \verb+[|...|]+, \verb+^+ and \verb+*^+ are also recognized; +\item function calls must use their printed name, as they appear in proof nodes; +\item for function patterns, trailing dots can be used to match any number of + arguments, like in \verb+f(x,y,(..))+ for instance. +\end{itemize} + +It is highly recommended using the graphical user interface or \verb+-wp-print+ +to build patterns expression and values. + +\section{Structure of JSON Scripts} +\label{wp-json-scripts} + +The proof scripts generated by using the Interactive Proof Editor (Section~\ref{wp-proof-editor}) +are saved in the \textsf{Frama-C/WP} session as \textsf{JSON} files. This section defines +the format of session scripts precisely. + +\textsf{JSON} scripts files are located in the \texttt{<session>/wp/scripts} sub-directory +of the \textsf{Frama-C} session directory (set with command line option \texttt{-session}) +or in the \texttt{<wpsession>/scripts} sub-directory of the \textsf{Frama-C/WP} session +directory (set with command line option \texttt{-wp-session}). + +The proof scripts for goal named \texttt{<goal>} is stored in a single file \texttt{<goal>.json} ; the +format of the \texttt{<goal>} name is identical to the one used by the \textsf{Frama-C/Report} plug-in +for its \textsf{JSON} output. + +The content of each script file is an array of alternatives, each alternative being a record with +two possible structures, that might represent a \textit{prover} attempt or the application of a +\textit{tactic}: + +\begin{align*} + \mathit{wp.script} &::= \mathtt{[} \mathit{wp.alternative} , \ldots \mathtt{]} \\ + \mathit{wp.alternative} &::= \mathit{wp.prover} \;|\; \mathit{wp.tactic} +\end{align*} + +\paragraph{Prover Attempts} The proof script records previous attempts to discharge a proof obligation +with external provers (also called decision procedures). +Each attempt is represented by a \textsf{JSON} record with the following fields: + +\begin{align*} + \mathit{wp.prover} &::= + \left\{ + \begin{array}{rl} + \mathtt{"prover"} :& \mathit{string}, \\ + \mathtt{"verdict"} :& \mathit{wp.verdict}, \\ + \mathtt{"time"} :& \mathit{number}? \\ + \mathtt{"steps"} :& \mathit{number}? \\ + \mathtt{"depth"} :& \mathit{number}? \\ + \end{array} + \right\} \\ + \mathit{wp.verdict} &::= + \begin{array}[t]{l} + \mathtt{"none"} ~|~ + \mathtt{"valid"} ~|~ + \mathtt{"unknown"} ~|~ \\ + \mathtt{"timeout"} ~|~ + \mathtt{"stepout"} ~|~ + \mathtt{"invalid"} ~|~ + \mathtt{"failed"} + \end{array} +\end{align*} + +Remark that, since the proof scripts do not record the proof obligation that was exercised, there is no +guarantee that replaying the script on a (potentially new) proof obligation would issue the same result. +Hence, prover attempts \emph{must} not be used as a cache, but can serve as a hint for choosing among +several alternatives. + +\paragraph{Proof Tactic} Applying a tactic is represented by a \textsf{JSON} record with the following +fields: + +\begin{align*} + \mathit{wp.tactic} &::= + \left\{ + \begin{array}{rl} + \mathtt{"tactic"} :& \mathit{string}, \\ + \mathtt{"header"} :& \mathit{string} ? \\ + \mathtt{"select"} :& \mathit{wp.selection}, \\ + \mathtt{"params"} :& \mathtt{\{}\; \mathit{string}:\mathit{wp.param} ,\ldots \;\mathtt{\}} ? \\ + \mathtt{"children"} :& \mathtt{\{}\; \mathit{string}:\mathit{wp.script}, \ldots \;\mathtt{\}} ? \\ + \mathtt{"strategy"} :& \mathit{string} ? \\ + \end{array} + \right\} +\end{align*} + +The \verb"header" field is just a descriptive title and has no special +meaning. The \verb"tactic" identifies the tactic, as it has been registered in +the \textsf{Frama-C/WP} internal API. The \verb"selection" is an opaque +encoding of the target of the tactic inside the proof obligation structure. The +\verb"params" array stores the value of tactic parameters, if any. The +\verb"children" stores the proof scripts associated with each sub-goal generated +by applying the specified tactic on a proof obligation. Finally, the +\verb"strategy" fields is used to recall which user-defined proof strategy was +used to trigger the tactic (See Section~\ref{wp-proof-strategies}). + +\paragraph{Tactic Parameters} Values of tactical parameters are encoded with the +following \textsf{JSON} format, depending on the internal type of the parameter +value: + +\begin{align*} + \mathit{wp.param} ::=\;& + \mathit{bool} ~|~ \mathit{number} ~|~ \mathit{string} \\ + |\;&\mathit{wp.named} ~|~ \mathit{wp.selection} \\ + \mathit{wp.named} ::= &\mathtt{null} ~|~ + \left\{ + \begin{array}{rl} + \mathtt{"id"} :& \mathit{string}, \\ + \mathtt{"title"} :& \mathit{string}? \\ + \mathtt{"description"} :& \mathit{string}? + \end{array} + \right\} +\end{align*} + +Named items (\textit{wp.named}) corresponds, for instance, to searched lemmas. +Selections corresponds to terms or expressions selected by the user \emph{via} +the graphical user interface, like the target of the tactic, as described below. + +\paragraph{Tactic Selection} The target of the tactic +is identified by a complex structure +encoding on which part of the proof obligation it shall be applied. Since the +exact structure of the proof obligation may vary from time to time, this structure +allows for searching in the proof obligation a \emph{pattern} that ressemble the +original target that was originally selected by the user during an interactive +session with the \textsf{Frama-C/WP} graphical user interface. + +Such \emph{patterns} are encoded as follows: + +\newcommand{\dash}{\rule[0.5ex]{1ex}{1pt}} + +\begin{align*} + \mathit{wp.selection} + ::=\;& \mathtt{null} \\ + |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}goal"},\; + \mathit{wp.pattern} \;\mathtt{\}} \\ + |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}goal"},\; + \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\ + |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}step"},\; + \mathit{wp.at},\; \mathit{wp.kind},\; + \mathit{wp.pattern} \;\mathtt{\}} \\ + |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}step"},\; + \mathit{wp.at},\; \mathit{wp.kind},\; + \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\ + |\;\;& \mathtt{\{}\; \mathtt{"select":"range"},\; + \mathtt{"min"}:\mathit{number},\; + \mathtt{"max"}:\mathit{number} \;\mathtt{\}} \\ + |\;\;& \mathtt{\{}\; \mathtt{"select":"kint"},\; + \mathtt{"val"}:\mathit{number} \;\mathtt{\}} \\ + |\;\;& \mathtt{\{}\; \mathtt{"select":"compose"},\; + \mathtt{"id"}:\mathit{string},\; + \mathtt{"args"}:[\mathit{wp.selection},\ldots] + \;\mathtt{\}} \\ +% -- + \mathit{wp.pattern} ::=\;& \mathtt{"pattern"} : \mathit{string} \\ + \mathit{wp.occur} ::=\;& \mathtt{"occur"} : \mathit{number} \\ + \mathit{wp.at} ::=\;& \mathtt{"at"} : \mathit{number} \\ + \mathit{wp.kind} ::=\;& \mathtt{"kind"} : \mathtt{"have"|"type"|"init"|"branch"|"either"|"state"} \\ +\end{align*} + +The various components of selection patterns have the following meaning: \textit{wp.pattern} encodes +a term or predicate pattern; \textit{wp.occur} designates which occurrence of the pattern to select, +in case of there is many of them inside the selected goal or hypothesis; \textit{wp.at} designates the +order of the selected hypothesis inside the proof obligation (the pattern is searched around this value), +and \textit{wp.kind} its kind. + +The \textit{wp.pattern} is a simple string that encodes the head of the structure of the +selected term or formulæ inside the designated goal or hypothesis. It is the concatenation of +the first 32 head nodes of width-first traversal of the selected term, each node being represented by +the following string: +\begin{itemize} + \item constant are represented by their value, + \item free variables by their base-name prefixed with \verb'$', + \item bound variables by their de-Bruijn index prefixed with \verb'#', + \item true and false by \verb"T" and \verb"F", and quantifiers by \verb"\F" and \verb"\E", + \item operators by \verb"&,|,!,~,+,-,*,/,%<,>,=,>=,/,?" + \item array operations by \verb"[]", \verb"[.]" and \verb"[=]" + \item record operations by \verb".fd" and \verb"{fd,...}" + \item function calls by their name +\end{itemize} + +For instance, the term $(x_1 \leq x_2+1)$ will be represented by the pattern \verb|"<=$x+$x1"|. + +\paragraph{Script Priority} When several alternatives are available for +discharging a proof obligation, the \texttt{script} and \texttt{tip} provers +of \textsf{Frama-C/WP} choose which one to apply first according to the +following heuristic: +\begin{enumerate} + \item try internal prover \texttt{"Qed"} with a \texttt{"valid"} verdict; + \item try any SMT prover with a \texttt{"valid"} verdict; + \item try the \texttt{"Coq"} proof assistant with a \texttt{"valid"} verdict; + \item try any Tactic alternative; + \item finally try the remaining Prover alternatives. +\end{enumerate} + +Inside the same level of priority, alternatives are kept in their original +order. + +\section{Structure of JSON Reports} +\label{wp-json-reports} The generated JSON report format consists of an array of JSON records, one for each generated toplevel goal. Each record consists of the following fields, @@ -1700,7 +2100,8 @@ some of them being optional when indicated: Notice that the JSON report file is printed in compact form without extra space nor indentation, unless verbose level is greater than 2 or debug level is greater than 1. -\subsection{Template-based Reports} +\section{Structure of Report Templates} +\label{wp-template-reports} Reports are created from user defined wp-report specification files. The general format of a wp-report file is as follows: @@ -1836,39 +2237,6 @@ current names: \end{center} \clearpage -%----------------------------------------------------------------------------- -\section{Plug-in Persistent Data} -\label{wp-persistent} - -As a general observation, almost \emph{none} of the internal -\textsf{WP} data is kept in memory after each execution. Most of the -generated proof-obligation data is stored on disk before being sent to -provers, and they are stored in a temporary directory that is removed -upon \textsf{Frama-C} exit (see also \texttt{-wp-out} option). - -The only information which is added to the \textsf{Frama-C} kernel -consists in a new status for those properties proved by \textsf{WP} plug-in with -their dependencies. - -Thus, when combining \textsf{WP} -options with \texttt{-then}, \texttt{-save} and \texttt{-load} -options, the user should be aware of the following precisions: -\begin{description} -\item[\tt -wp, -wp-prop, -wp-fct, -wp-bhv.] These options make the - \textsf{WP} plug-in generate proof-obligations for the selected - properties. The values of theses options are never saved and they are - cleared by \texttt{-then}. Hence, running \texttt{-wp-prop A} - \texttt{-then} \texttt{-wp-fct F} does what you expect: - properties tagged by \texttt{A} are proved only once. -\item[\tt -wp-print, -wp-prover, -wp-gen, -wp-detect.] These options do not - generate new proof-obligations, but run other actions on all - previously generated ones. For the same reasons, they are not saved - and cleared by \texttt{-then}. -\item[\tt -wp-xxx.] All other options are tunings that can be easily - turned on and off or set to the desired value. - They are saved and kept across \texttt{-then} commands. -\end{description} - %----------------------------------------------------------------------------- % vim: spell spelllang=en diff --git a/src/plugins/wp/doc/manual/wp_simplifier.tex b/src/plugins/wp/doc/manual/wp_simplifier.tex index 2e3e82551aa4e94a1ab36ac54e667b9e3ff97d0c..83548a9f1a0d19e5e58999c020fa87d94d075d87 100644 --- a/src/plugins/wp/doc/manual/wp_simplifier.tex +++ b/src/plugins/wp/doc/manual/wp_simplifier.tex @@ -73,7 +73,7 @@ Adding a new fact $H$ to $\Gamma$ is denoted by $\Gamma\oplus H$ ; rewriting a term of predicate $e$ into $e'$ with respect to $\Gamma$ is denoted by $\Gamma\models e\triangleright e'$. -\paragraph{Inference Law.} +\paragraph{Inference Law.} A hypothesis is simplified and added to the knowledge base to simplify the goal. \[\LAW% @@ -164,183 +164,3 @@ conditional is: This form actually factorizes the common postcondition to $A$ and $B$, which makes the \emph{weakest precondition} calculus linear in the number of program statements. - -\section{Structure of JSON Scripts} - -The proof scripts generated by using the Interactive Proof Editor (Section~\ref{wp-proof-editor}) -are saved in the \textsf{Frama-C/WP} session as \textsf{JSON} files. This section defines -the format of session scripts precisely. - -\textsf{JSON} scripts files are located in the \texttt{<session>/wp/scripts} sub-directory -of the \textsf{Frama-C} session directory (set with command line option \texttt{-session}) -or in the \texttt{<wpsession>/scripts} sub-directory of the \textsf{Frama-C/WP} session -directory (set with command line option \texttt{-wp-session}). - -The proof scripts for goal named \texttt{<goal>} is stored in a single file \texttt{<goal>.json} ; the -format of the \texttt{<goal>} name is identical to the one used by the \textsf{Frama-C/Report} plug-in -for its \textsf{JSON} output. - -The content of each script file is an array ofs alternatives, each alternative being a record with -two possible structures, that might represent a \textit{prover} attempt or the application of a -\textit{tactic}: - -\begin{align*} - \mathit{wp.script} &::= \mathtt{[} \mathit{wp.alternative} , \ldots \mathtt{]} \\ - \mathit{wp.alternative} &::= \mathit{wp.prover} \;|\; \mathit{wp.tactic} -\end{align*} - -\paragraph{Prover Attempts} The proof script records previous attempts to discharge a proof obligation -with external provers (also called decision procedures). -Each attempt is represented by a \textsf{JSON} record with the following fields: - -\begin{align*} - \mathit{wp.prover} &::= - \left\{ - \begin{array}{rl} - \mathtt{"prover"} :& \mathit{string}, \\ - \mathtt{"verdict"} :& \mathit{wp.verdict}, \\ - \mathtt{"time"} :& \mathit{number}? \\ - \mathtt{"steps"} :& \mathit{number}? \\ - \mathtt{"depth"} :& \mathit{number}? \\ - \end{array} - \right\} \\ - \mathit{wp.verdict} &::= - \begin{array}[t]{l} - \mathtt{"none"} ~|~ - \mathtt{"valid"} ~|~ - \mathtt{"unknown"} ~|~ \\ - \mathtt{"timeout"} ~|~ - \mathtt{"stepout"} ~|~ - \mathtt{"invalid"} ~|~ - \mathtt{"failed"} - \end{array} -\end{align*} - -Remark that, since the proof scripts do not record the proof obligation that was exercised, there is no -guarantee that replying the script on a (potentially new) proof obligation would issue the same result. -Hence, prover attempts \emph{must} not be used as a cache, but can serve as a hint for choosing among -several alternatives. - -\paragraph{Proof Tactic} Applying a tactic is represented by a \textsf{JSON} record with the following -fields: - -\begin{align*} - \mathit{wp.tactic} &::= - \left\{ - \begin{array}{rl} - \mathtt{"tactic"} :& \mathit{string}, \\ - \mathtt{"header"} :& \mathit{string} ? \\ - \mathtt{"select"} :& \mathit{wp.selection}, \\ - \mathtt{"params"} :& \mathtt{\{}\; \mathit{string}:\mathit{wp.param} ,\ldots \;\mathtt{\}} ? \\ - \mathtt{"children"} :& \mathtt{\{}\; \mathit{string}:\mathit{wp.script}, \ldots \;\mathtt{\}} ? \\ - \end{array} - \right\} -\end{align*} - -The \verb"header" field is just a descriptive title and has no special meaning. The \verb"tactic" -identifies the tactic, as it has been registered in the \textsf{Frama-C/WP} internal API. -The \verb"selection" is an opaque encoding of the target of the tactic inside the proof obligation -structure. The \verb"params" array stores the value of tactic parameters, if any. -The \verb"children" stores the proof scripts associated with each sub-goal generated by applying -the specified tactic on a proof obligation. - -\paragraph{Tactic Parameters} Values of tactical parameters are encoded with the -following \textsf{JSON} format, depending on the internal type of the parameter -value: - -\begin{align*} - \mathit{wp.param} ::=\;& - \mathit{bool} ~|~ \mathit{number} ~|~ \mathit{string} \\ - |\;&\mathit{wp.named} ~|~ \mathit{wp.selection} \\ - \mathit{wp.named} ::= &\mathtt{null} ~|~ - \left\{ - \begin{array}{rl} - \mathtt{"id"} :& \mathit{string}, \\ - \mathtt{"title"} :& \mathit{string}? \\ - \mathtt{"description"} :& \mathit{string}? - \end{array} - \right\} -\end{align*} - -Named items (\textit{wp.named}) corresponds, for instance, to searched lemmas. -Selections corresponds to terms or expressions selected by the user \emph{via} -the graphical user interface, like the target of the tactic, as described below. - -\paragraph{Tactic Selection} The target of the tactic -is identified by a complex structure -encoding on which part of the proof obligation it shall be applied. Since the -exact structure of the proof obligation may vary from time to time, this structure -allows for searching in the proof obligation a \emph{pattern} that ressemble the -original target that was originally selected by the user during an interactive -session with the \textsf{Frama-C/WP} graphical user interface. - -Such \emph{patterns} are encoded as follows: - -\newcommand{\dash}{\rule[0.5ex]{1ex}{1pt}} - -\begin{align*} - \mathit{wp.selection} - ::=\;& \mathtt{null} \\ - |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}goal"},\; - \mathit{wp.pattern} \;\mathtt{\}} \\ - |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}goal"},\; - \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\ - |\;\;& \mathtt{\{}\; \mathtt{"select":"clause\dash{}step"},\; - \mathit{wp.at},\; \mathit{wp.kind},\; - \mathit{wp.pattern} \;\mathtt{\}} \\ - |\;\;& \mathtt{\{}\; \mathtt{"select":"inside\dash{}step"},\; - \mathit{wp.at},\; \mathit{wp.kind},\; - \mathit{wp.occur},\; \mathit{wp.pattern} \;\mathtt{\}} \\ - |\;\;& \mathtt{\{}\; \mathtt{"select":"range"},\; - \mathtt{"min"}:\mathit{number},\; - \mathtt{"max"}:\mathit{number} \;\mathtt{\}} \\ - |\;\;& \mathtt{\{}\; \mathtt{"select":"kint"},\; - \mathtt{"val"}:\mathit{number} \;\mathtt{\}} \\ - |\;\;& \mathtt{\{}\; \mathtt{"select":"compose"},\; - \mathtt{"id"}:\mathit{string},\; - \mathtt{"args"}:[\mathit{wp.selection},\ldots] - \;\mathtt{\}} \\ -% -- - \mathit{wp.pattern} ::=\;& \mathtt{"pattern"} : \mathit{string} \\ - \mathit{wp.occur} ::=\;& \mathtt{"occur"} : \mathit{number} \\ - \mathit{wp.at} ::=\;& \mathtt{"at"} : \mathit{number} \\ - \mathit{wp.kind} ::=\;& \mathtt{"kind"} : \mathtt{"have"|"type"|"init"|"branch"|"either"|"state"} \\ -\end{align*} - -The various components of selection patterns have the following meaning: \textit{wp.pattern} encodes -a term or predicate pattern; \textit{wp.occur} designates which occurrence of the pattern to select, -in case of there is many of them inside the selected goal or hypothesis; \textit{wp.at} designates the -order of the selected hypothesis inside the proof obligation (the pattern is searched around this value), -and \textit{wp.kind} its kind. - -The \textit{wp.pattern} is an simple string that encodes the head of the structure of the -selected term or formulæ inside the designated goal or hypothesis. It is the concatenation of -the first 32 head nodes of width-first traversal of the selected term, each node being represented by -the following string: -\begin{itemize} - \item constant are represented by their value, - \item free variables by their base-name prefixed with \verb'$', - \item bound variables by their de-Bruijn index prefixed with \verb'#', - \item true and false by \verb"T" and \verb"F", and quantifiers by \verb"\F" and \verb"\E", - \item operators by \verb"&,|,!,~,+,-,*,/,%<,>,=,>=,/,?" - \item array operations by \verb"[]", \verb"[.]" and \verb"[=]" - \item record operations by \verb".fd" and \verb"{fd,...}" - \item function calls by their name -\end{itemize} - -For instance, the term $(x_1 \leq x_2+1)$ will be represented by the pattern \verb|"<=$x+$x1"|. - -\paragraph{Alternative Ordering} When several alternatives are available for -discharging a proof obligation, the \texttt{script} and \texttt{tip} provers -of \textsf{Frama-C/WP} choose which one to apply first according to the -following heuristic: -\begin{enumerate} - \item try internal prover \texttt{"Qed"} with a \texttt{"valid"} verdict; - \item try any SMT prover with a \texttt{"valid"} verdict; - \item try the \texttt{"Coq"} proof assistant with a \texttt{"valid"} verdict; - \item try any Tactic alternative; - \item finally try the remaining Prover alternatives. -\end{enumerate} - -Inside the same level of priority, alternatives are kept in their original -order. diff --git a/src/plugins/wp/gui/GuiGoal.ml b/src/plugins/wp/gui/GuiGoal.ml index a5571312675d6543c5885461963918e77ce24ea0..d16760abc2e6427d6fe042034b0ceb232dcf9d8c 100644 --- a/src/plugins/wp/gui/GuiGoal.ml +++ b/src/plugins/wp/gui/GuiGoal.ml @@ -117,6 +117,7 @@ class pane (gprovers : GuiConfig.provers) = let autofocus = new autofocus in let iformat = new iformat in let rformat = new rformat in + let autosearch = new GuiTactic.autosearch () in let strategies = new GuiTactic.strategies () in object(self) @@ -145,8 +146,10 @@ class pane (gprovers : GuiConfig.provers) = (Why3.Whyconf.Sprover.elements gprovers#get) in provers <- why3_provers ; List.iter (fun p -> palette#add_tool p#tool) provers ; + palette#add_tool autosearch#tool ; palette#add_tool strategies#tool ; - Strategy.iter strategies#register ; + Strategy.iter autosearch#register ; + ProofStrategy.iter strategies#register ; Tactical.iter (fun tac -> let gtac = new GuiTactic.tactic tac printer#pp_selection in @@ -380,23 +383,29 @@ class pane (gprovers : GuiConfig.provers) = method private update_tactics = function | None -> printer#set_target Tactical.Empty ; + autosearch#connect None ; strategies#connect None ; List.iter (fun tactic -> tactic#clear) tactics | Some(tree,sequent,sel) -> on_proof_context tree begin fun () -> - strategies#connect (Some (self#strategies sequent)) ; - let select (tactic : GuiTactic.tactic) = - let process = self#apply in - let composer = self#compose in - let browser = self#browse in - tactic#select ~process ~composer ~browser ~tree sel - in - List.iter select tactics ; - let tgt = - if List.exists (fun tactics -> tactics#targeted) tactics - then sel else Tactical.Empty in - printer#set_target tgt + (* configure strategies *) + let node = ProofEngine.head tree in + let wpo = ProofEngine.head_goal tree in + let hints = ProofStrategy.hints ?node wpo in + autosearch#connect (Some (self#autosearch sequent)); + strategies#connect ~hints (Some self#strategies); + (* configure tactics *) + List.iter (fun (tactic : GuiTactic.tactic) -> + let process = self#apply in + let composer = self#compose in + let browser = self#browse in + tactic#select ~process ~composer ~browser ~tree sel + ) tactics ; + (* target selection feedback *) + printer#set_target + (if List.exists (fun tactics -> tactics#targeted) tactics + then sel else Tactical.Empty) end () method private update_scriptbar = @@ -508,9 +517,8 @@ class pane (gprovers : GuiConfig.provers) = self#update_provers None ; self#update_tactics None ; | Proof proof -> - let wpo = ProofEngine.head proof in begin - self#update_provers (Some wpo) ; + self#update_provers (Some (ProofEngine.head_goal proof)) ; let sequent = printer#sequent in let select = printer#selection in self#update_tactics (Some(proof,sequent,select)) ; @@ -553,7 +561,7 @@ class pane (gprovers : GuiConfig.provers) = text#hrule ; scripter#tree proof ; text#hrule ; - text#printf "%a@." printer#pp_goal (ProofEngine.head proof) ; + text#printf "%a@." printer#pp_goal (ProofEngine.head_goal proof) ; text#printf "@{<bf>Goal id:@} %s@." main.po_gid ; text#printf "@{<bf>Short id:@} %s@." main.po_sid ; text#hrule ; @@ -569,7 +577,7 @@ class pane (gprovers : GuiConfig.provers) = self#update in text#printf "%t@." (composer#print cc ~quit) ; text#hrule ; - text#printf "%a@." printer#pp_goal (ProofEngine.head proof) ; + text#printf "%a@." printer#pp_goal (ProofEngine.head_goal proof) ; end () | Browser(proof,cc,tgt) -> on_proof_context proof @@ -581,7 +589,7 @@ class pane (gprovers : GuiConfig.provers) = self#update in text#printf "%t@." (browser#print cc ~quit) ; text#hrule ; - text#printf "%a@." printer#pp_goal (ProofEngine.head proof) ; + text#printf "%a@." printer#pp_goal (ProofEngine.head_goal proof) ; end () | Forking _ -> () @@ -648,20 +656,19 @@ class pane (gprovers : GuiConfig.provers) = | Proof proof -> Wutil.later begin fun () -> - let title = tactic#title in try - let tactic = ProofScript.jtactic ~title tactic selection in + let tactic = ProofScript.jtactic tactic selection in let anchor = ProofEngine.anchor proof () in self#fork proof (ProofEngine.fork proof ~anchor tactic process) with Exit | Not_found | Invalid_argument _ -> - text#printf "Application of tactic '%s' failed." title + text#printf "Application of tactic '%s' failed." tactic#title end method private search proof = function | None -> text#printf "No tactic found.@\n" | Some fork -> self#fork proof fork - method private strategies sequent ~depth ~width auto = + method private autosearch sequent ~depth ~width auto = match state with | Empty | Forking _ | Composer _ | Browser _ -> () | Proof proof -> @@ -693,6 +700,30 @@ class pane (gprovers : GuiConfig.provers) = end end + method private strategies ~depth strategy = + match state with + | Empty | Forking _ | Composer _ | Browser _ -> () + | Proof proof -> + Wutil.later + begin fun () -> + ProverScript.explore + ~depth ?strategy + ~result: + (fun wpo prv res -> + text#printf "[%a] %a : %a@." + VCS.pp_prover prv + Wpo.pp_title wpo + VCS.pp_result res) + ~success: + (fun _ _ -> + ProofEngine.forward proof ; + self#update ; + text#printf "Strategie(s) Explored." ) + proof (ProofEngine.anchor proof ()) ; + let server = ProverTask.server () in + Task.launch server + end + method private backtrack node = match state with | Empty | Forking _ | Composer _ | Browser _ -> () diff --git a/src/plugins/wp/gui/GuiProver.ml b/src/plugins/wp/gui/GuiProver.ml index 4e32d9956206c0d5fa3211aa9d359c9507a3221f..7f02b9f6fa7f86d59e6cc41cfde465b8d68df89b 100644 --- a/src/plugins/wp/gui/GuiProver.ml +++ b/src/plugins/wp/gui/GuiProver.ml @@ -89,7 +89,7 @@ class prover ~(console:Wtext.text) ~prover = let spinner = function None -> None | Some s -> Some s#get in let config = { VCS.valid = false ; - VCS.timeout = spinner timeout ; + VCS.timeout = Option.map float @@ spinner timeout ; VCS.stepout = spinner stepout ; } in let result wpo _prv _res = self#update wpo in diff --git a/src/plugins/wp/gui/GuiTactic.ml b/src/plugins/wp/gui/GuiTactic.ml index ddfe30c345fbece00e09028f186f990658649ba2..079a0c6b3bf9f27865801e5fad218c0e6cd321f6 100644 --- a/src/plugins/wp/gui/GuiTactic.ml +++ b/src/plugins/wp/gui/GuiTactic.ml @@ -496,7 +496,7 @@ type hform = { widget : Widget.checkbox ; } -let compare f g = String.compare f.search#title g.search#title +let hcompare f g = String.compare f.search#title g.search#title let spinner ~(form:Wpane.form) ~default ~label ~tooltip = let config = "wp.strategies." ^ label in @@ -506,9 +506,18 @@ let spinner ~(form:Wpane.form) ~default ~label ~tooltip = form#add_field ~label spinner#coerce ; spinner -type callback = depth:int -> width:int -> Strategy.heuristic list -> unit +let checkbox ~(form:Wpane.form) ~default ~label ~tooltip = + let config = "wp.strategies." ^ label in + let value = User.find_bool ~default config in + let checkbox = new Widget.checkbox ~label ~tooltip () in + checkbox#set value ; + checkbox#connect (User.set_bool config) ; + form#add_field ~label checkbox#coerce ; + checkbox -class strategies () = +type auto_callback = depth:int -> width:int -> Strategy.heuristic list -> unit + +class autosearch () = let form = new Wpane.form () in let depth = spinner ~form ~default:1 ~label:"Depth" ~tooltip:"Limit the number of nested strategies" in @@ -517,10 +526,10 @@ class strategies () = object(self) inherit Wpalette.tool ~content:form#widget - ~label:"Strategies" - ~tooltip:"Apply Custom Strategies" () + ~label:"Auto" + ~tooltip:"Automated proof search (-wp-auto)" () val mutable hforms : hform list = [] - val mutable demon : callback option = None + val mutable demon : auto_callback option = None method register (search : Strategy.heuristic) = begin @@ -533,7 +542,7 @@ class strategies () = widget#on_event self#update ; form#add_row widget#coerce ; let hform = { search ; widget } in - hforms <- List.merge compare [hform] hforms + hforms <- List.merge hcompare [hform] hforms end method private update () = @@ -567,3 +576,90 @@ class strategies () = end (* -------------------------------------------------------------------------- *) +(* --- Proof Strategies --- *) +(* -------------------------------------------------------------------------- *) + +type callback = (depth:int -> ProofStrategy.strategy option -> unit) + +type strategy = { + strategy : ProofStrategy.strategy ; + button : Widget.button ; +} + +class strategies () = + let form = new Wpane.form () in + let depth = spinner ~form ~default:1 ~label:"Auto depth" + ~tooltip:"Depth of exploration" in + let hints = checkbox ~form ~default:true ~label:"Hints only" + ~tooltip:"Display hints for the current goal" in + object(self) + inherit Wpalette.tool + ~content:form#widget + ~label:"Strategies" + ~tooltip:"Run the full Proof Strategy Engine (-wp-strategy)" () + + val mutable registered = false + val mutable proofhints : ProofStrategy.strategy list = [] + val mutable strategies : strategy list = [] + val mutable callback : callback option = None + + initializer hints#connect (fun _ -> self#update) + + method register (s : ProofStrategy.strategy) = + begin + registered <- true ; + let label = ProofStrategy.name s in + let tooltip = Format.asprintf "%a: strategy %s (single step)" + Filepath.pp_pos (fst @@ ProofStrategy.loc s) label in + let button = new Widget.button ~icon:`MEDIA_PLAY ~label ~tooltip () in + button#set_visible false ; + button#connect (self#strategy s) ; + end + + method connect ?(hints=[]) (cb : callback option) = + callback <- cb ; + proofhints <- hints ; + self#update + + method private strategy (s : ProofStrategy.strategy) () = + Option.iter (fun fn -> fn ~depth:depth#get (Some s)) callback + + method private explore () = + Option.iter (fun fn -> fn ~depth:depth#get None) callback + + method private setvisible ?(filter=false) ?(rank=0) (s: strategy) = + let show = not filter || rank > 0 in + s.button#set_visible show ; + if show then + let name = ProofStrategy.name s.strategy in + if rank = 0 then + s.button#set_label name + else + Pretty_utils.ksfprintf s.button#set_label "%s (#%d)" name rank + + method private setrank (s: strategy) = + let filter = hints#get in + let rec apply (s:strategy) rank = function + | [] -> self#setvisible s ~filter + | h::hs -> + if s.strategy == h then + self#setvisible s ~rank + else + self#setvisible s ~filter ; + apply s (succ rank) hs + in apply s 1 proofhints + + method private update = + if callback = None || not registered then + self#set_visible false + else + begin + self#set_visible true ; + self#set_status `APPLY ; + self#set_action ~callback:self#explore () ; + List.iter self#setrank strategies + end + + end + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/gui/GuiTactic.mli b/src/plugins/wp/gui/GuiTactic.mli index 868b6445837b6473227671f7996f275e55fba45e..716d4620b65d0e4e0804fa1f2fa6af3ed59893d8 100644 --- a/src/plugins/wp/gui/GuiTactic.mli +++ b/src/plugins/wp/gui/GuiTactic.mli @@ -68,11 +68,31 @@ class tactic : Tactical.t -> (Format.formatter -> Tactical.selection -> unit) -> selection -> unit end -type callback = depth:int -> width:int -> Strategy.heuristic list -> unit +(* -------------------------------------------------------------------------- *) +(* --- Auto Dongle --- *) +(* -------------------------------------------------------------------------- *) -class strategies : unit -> +type auto_callback = depth:int -> width:int -> Strategy.heuristic list -> unit + +class autosearch : unit -> object inherit Wpalette.tool method register : Strategy.heuristic -> unit - method connect : callback option -> unit + method connect : auto_callback option -> unit end + +(* -------------------------------------------------------------------------- *) +(* --- Strategies Dongle --- *) +(* -------------------------------------------------------------------------- *) + +type callback = (depth:int -> ProofStrategy.strategy option -> unit) + +class strategies : unit -> + object + inherit Wpalette.tool + method register : ProofStrategy.strategy -> unit + method connect : ?hints:ProofStrategy.strategy list -> + callback option -> unit + end + +(* -------------------------------------------------------------------------- *) diff --git a/src/plugins/wp/register.ml b/src/plugins/wp/register.ml index bd21d8b17014286f93ab87d0ad8ab1ea3509af64..3b5f932999ac3233b3e619b243c2da003ecfe92b 100644 --- a/src/plugins/wp/register.ml +++ b/src/plugins/wp/register.ml @@ -62,8 +62,59 @@ let wp_insert_memory_context model = (* --- Printing informations --- *) (* ------------------------------------------------------------------------ *) +let do_print_index fmt = function + | Wpo.Axiomatic ax -> Wpo.pp_axiomatics fmt ax + | Wpo.Function(kf,bhv) -> Wpo.pp_function fmt kf bhv + +let rec do_print_parents fmt (node : ProofEngine.node) = + Option.iter (do_print_parents fmt) (ProofEngine.parent node) ; + Format.fprintf fmt " - %s@\n" (ProofEngine.title node) + +let do_print_current fmt tree = + match ProofEngine.current tree with + | `Main -> () + | `Internal node | `Leaf(_,node) -> do_print_parents fmt node + +let do_print_goal_status fmt (g : Wpo.t) = + if not (Wpo.is_valid g || Wpo.is_smoke_test g) then + begin + do_print_index fmt g.po_idx ; + Wpo.pp_goal fmt g ; + if ProofSession.exists g then + Format.fprintf fmt "Script %a@\n" ProofSession.pp_file + (ProofSession.filename ~force:false g) ; + begin + match ProofEngine.get g with + | `None | `Script -> () + | `Proof | `Saved -> + let tree = ProofEngine.proof ~main:g in + match ProofEngine.status tree with + | `Unproved | `Invalid | `Proved | `Passed -> + Wpo.pp_goal fmt g + | `Pending n | `StillResist n -> + for i = 0 to n-1 do + Format.fprintf fmt "%tSubgoal %d/%d:@\n" Wpo.pp_flow (succ i) n ; + ProofEngine.goto tree (`Leaf i) ; + do_print_current fmt tree ; + Wpo.pp_goal fmt @@ ProofEngine.head_goal tree + done + end ; + Wpo.pp_flow fmt ; + end + +let do_wp_print_status () = + begin + Log.print_on_output + (fun fmt -> + Wpo.iter + ~on_goal:(do_print_goal_status fmt) ()) ; + end + let do_wp_print () = (* Printing *) + if Wp_parameters.Status.get () then + do_wp_print_status () + else if Wp_parameters.Print.get () then try Wpo.iter ~on_goal:(fun _ -> raise Exit) () ; @@ -77,6 +128,9 @@ let do_wp_print () = ~on_goal:(Wpo.pp_goal_flow fmt) ()) let do_wp_print_for goals = + if Wp_parameters.Status.get () then + do_wp_print_status () + else if Wp_parameters.Print.get () then if Bag.is_empty goals then Wp_parameters.result "No proof obligations" @@ -426,9 +480,11 @@ let do_list_scheduled_result () = (* ------------------------------------------------------------------------ *) type script = { - mutable tactical : bool ; + mutable proverscript : bool ; + mutable strategies : bool ; + mutable scratch : bool ; mutable update : bool ; - mutable on_stdout : bool ; + mutable stdout : bool ; mutable depth : int ; mutable width : int ; mutable backtrack : int ; @@ -437,7 +493,7 @@ type script = { } let spawn_wp_proofs ~script goals = - if script.tactical || script.provers<>[] then + if script.proverscript || script.provers<>[] then begin let server = ProverTask.server () in ignore (Wp_parameters.Share.get_dir "."); (* To prevent further errors *) @@ -445,12 +501,18 @@ let spawn_wp_proofs ~script goals = let cache = Cache.get_mode () in Bag.iter (fun goal -> - if script.tactical + if script.proverscript && not (Wpo.is_trivial goal) - && (script.auto <> [] || ProofSession.exists goal) + && (script.auto <> [] || + script.strategies || + ProofSession.exists goal || + Wp_parameters.DefaultStrategies.get () <> [] || + ProofStrategy.hints goal <> []) then ProverScript.spawn ~failed:false + ~scratch:script.scratch + ~strategies:script.strategies ~auto:script.auto ~depth:script.depth ~width:script.width @@ -475,11 +537,8 @@ let spawn_wp_proofs ~script goals = end let get_prover_names () = - match Wp_parameters.Provers.get () with [] -> [ "alt-ergo" ] | pnames -> pnames - -let env_script_update () = - try Sys.getenv "FRAMAC_WP_SCRIPT" = "update" - with Not_found -> false + match Wp_parameters.Provers.get () with + | [] -> [ "alt-ergo" ] | pnames -> pnames let compute_provers ~mode ~script = script.provers <- List.fold_right @@ -487,9 +546,8 @@ let compute_provers ~mode ~script = match VCS.parse_prover pname with | None -> prvs | Some VCS.Tactical -> - script.tactical <- true ; - if pname = "tip" || env_script_update () then - script.update <- true ; + script.proverscript <- true ; + if pname = "tip" then script.strategies <- true ; prvs | Some prover -> let pmode = if VCS.is_auto prover then VCS.Batch else mode in @@ -508,8 +566,13 @@ let dump_strategies = ))) let default_script_mode () = { - tactical = false ; update=false ; on_stdout = false ; provers = [] ; - depth=0 ; width = 0 ; auto=[] ; backtrack = 0 ; + provers = [] ; + proverscript = false ; + strategies = false ; + update = ProofSession.saving_mode () ; + scratch = ProofSession.scratch_mode () ; + stdout = Wp_parameters.ScriptOnStdout.get (); + depth=0 ; width = 0 ; backtrack = 0 ; auto=[] ; } let compute_auto ~script = @@ -534,7 +597,7 @@ let compute_auto ~script = "Strategy -wp-auto '%s' unknown (ignored)." id ) auto ; script.auto <- List.rev script.auto ; - if script.auto <> [] then script.tactical <- true ; + if script.auto <> [] then script.proverscript <- true ; end type session_scripts = { @@ -572,17 +635,15 @@ let do_collect_session goals = | ProofScript.Prover(p,r) -> VCS.is_auto p && VCS.is_valid r | ProofScript.Tactic(n,_,_) -> n=0 | ProofScript.Error _ -> false in - let strategy = List.filter keep scripts in - if strategy <> [] then + let winning = List.filter keep scripts in + let file = file goal in + if winning <> [] then begin - let file = file goal in - let json = ProofScript.encode strategy in + let json = ProofScript.encode winning in updated := (goal, file, json) :: !updated end else - if not (ProofSession.exists goal) then begin - let file = file goal in let json = ProofScript.encode scripts in incomplete := (goal, file, json) :: !incomplete end @@ -593,7 +654,7 @@ let do_collect_session goals = removed = !removed ; } let do_update_session script session = - let stdout = script.on_stdout in + let stdout = script.stdout in List.iter begin fun (g, _, s) -> (* we always mark existing scripts *) @@ -669,17 +730,15 @@ let do_wp_proofs ?provers ?tip (goals : Wpo.t Bag.t) = let mode = VCS.parse_mode (Wp_parameters.Interactive.get ()) in compute_provers ~mode ~script ; compute_auto ~script ; + ProofStrategy.typecheck () ; begin match provers with None -> () | Some prvs -> script.provers <- List.map (fun dp -> VCS.Batch , VCS.Why3 dp) prvs end ; - begin match tip with None -> () | Some tip -> - script.tactical <- tip ; - script.update <- tip ; - end ; - begin - script.on_stdout <- Wp_parameters.ScriptOnStdout.get (); + begin match tip with None -> () | Some strategies -> + script.proverscript <- true ; + script.strategies <- strategies ; end ; - let spawned = script.tactical || script.provers <> [] in + let spawned = script.proverscript || script.provers <> [] in begin if spawned then do_list_scheduled goals ; spawn_wp_proofs ~script goals ; @@ -688,7 +747,9 @@ let do_wp_proofs ?provers ?tip (goals : Wpo.t Bag.t) = do_list_scheduled_result () ; do_session ~script goals ; end - else if not (Wp_parameters.Print.get ()) then + else + if not (Wp_parameters.Print.get () || Wp_parameters.Status.get ()) + then Bag.iter do_wpo_display goals end @@ -771,13 +832,9 @@ let pp_wp_parameters fmt = if spec <> [] && spec <> ["Typed"] then ( let descr = Factory.descr (Factory.parse spec) in Format.fprintf fmt " -wp-model '%s'" descr ) ; - if not (Wp_parameters.Let.get ()) then Format.pp_print_string fmt - " -wp-no-let" ; - if Wp_parameters.Let.get () && not (Wp_parameters.Prune.get ()) - then Format.pp_print_string fmt " -wp-no-prune" ; - if Wp_parameters.Split.get () then Format.pp_print_string fmt " -wp-split" ; + let dt = Wp_parameters.Timeout.get_default () in let tm = Wp_parameters.Timeout.get () in - if tm <> 10 then Format.fprintf fmt " -wp-timeout %d" tm ; + if tm <> dt then Format.fprintf fmt " -wp-timeout %d" tm ; let st = Wp_parameters.Steps.get () in if st > 0 then Format.fprintf fmt " -wp-steps %d" st ; if not (Kernel.SignedOverflow.get ()) then @@ -826,6 +883,71 @@ let do_prover_detect () = (Why3Provers.ident_wp p) ) provers +(* ------------------------------------------------------------------------ *) +(* --- Tactic Searching --- *) +(* ------------------------------------------------------------------------ *) + +let pp_field fmt pp (fd : 'a Tactical.field) = + let s = Tactical.signature fd in + Format.fprintf fmt "@\nParameter %S:" s.vid ; + if s.title <> "" then Format.fprintf fmt "@\n Title: %s" s.title ; + if s.descr <> "" then Format.fprintf fmt "@\n Descr: %s" s.descr ; + Format.fprintf fmt "@\n Default: %a" pp (Tactical.default fd) + +let pp_parameter fmt (p : Tactical.parameter) = + match p with + | Checkbox fd -> + pp_field fmt Format.pp_print_bool fd + | Spinner(fd,rg) -> + pp_field fmt Format.pp_print_int fd ; + begin match rg.vmin , rg.vmax with + | None,None -> () + | Some a,None -> Format.fprintf fmt "@\n Range: %d.." a + | None,Some b -> Format.fprintf fmt "@\n Range: ..%d" b + | Some a,Some b -> Format.fprintf fmt "@\n Range: %d..%d" a b + end + | Composer(fd,_) -> + pp_field fmt Tactical.pp_selection fd + | Selector(fd,items,eq) -> + pp_field fmt + (fun fmt v -> + List.iter + (fun (item : _ Tactical.named) -> + if eq v item.value then Format.fprintf fmt "%S" item.vid + ) items + ) fd ; + List.iter + (fun (item : _ Tactical.named) -> + Format.fprintf fmt "@\n Value %S: %s" item.vid item.title ; + if item.descr <> "" then Format.fprintf fmt " (%s)" item.descr ; + ) items + | Search(fd,_,_) -> + pp_field fmt + (fun fmt s -> + match s with + | None -> Format.pp_print_string fmt "-" + | Some v -> Format.fprintf fmt "%S" v.Tactical.title + ) fd + +let do_search_tactics () = + let ts = Wp_parameters.Tactics.get () in + if List.mem "?" ts then + Wp_parameters.result "@[<hov 2>Registered tactics:%t@]" + begin fun fmt -> + Tactical.iter (fun t -> Format.fprintf fmt "@ %s" t#id) ; + end ; + if ts <> [] then + Tactical.iter + begin fun t -> + if List.mem t#id ts then + Wp_parameters.result + "Tactic %S:@\n\ + Title: @[<h>%s@]@\n\ + Descr: @[<h>%s@]%t" + t#id t#title t#descr + (fun fmt -> List.iter (pp_parameter fmt) t#params) + end + (* ------------------------------------------------------------------------ *) (* --- Main Entry Points --- *) (* ------------------------------------------------------------------------ *) @@ -871,6 +993,7 @@ let tracelog () = let main = sequence [ (fun () -> Wp_parameters.debug ~dkey:dkey_main "Start WP plugin...@.") ; do_prover_detect ; + do_search_tactics ; prepare_scripts ; cmdline_run ; tracelog ; diff --git a/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw b/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw index 838aa45061449c66db8dd2d6ec2a567ee2ce883b..90dd0399e3cdf498d95a0e8fc2d56d4f8ae02fcb 100644 --- a/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw +++ b/src/plugins/wp/share/why3/frama_c_wp/vlist.mlw @@ -28,61 +28,132 @@ theory Vlist use int.Int use int.ComputerDivision + use list.Append + use list.HdTl + use list.Nth + use option.Option + + use export list.List + use export list.Length (* -------------------------------------------------------------------- *) (* --- Classical Lists for Alt-Ergo --- *) (* -------------------------------------------------------------------- *) - type list 'a + function nil : list 'a = Nil + + function cons (x: 'a) (xs: list 'a) : list 'a = Cons x xs + + let function head (l: list 'a) : 'a + requires { l <> Nil } + ensures { hd l = Some result } + = match l with Nil -> absurd | Cons h _ -> h end + + let function tail (l: list 'a) : list 'a + requires { l <> Nil } + ensures { tl l = Some result } + = match l with Nil -> absurd | Cons _ t -> t end - function nil : list 'a - function cons 'a (list 'a) : list 'a - function concat (list 'a) (list 'a) : list 'a - function repeat (list 'a) int : list 'a - function length (list 'a) : int - function nth (list 'a) int : 'a + function concat (xs: list 'a) (ys: list 'a) : list 'a = xs ++ ys function elt (x:'a) : list 'a = cons x nil + (* repeat *) + (* Here we are forced to use axiomatic definition to conform to ACSL *) + + function repeat (xs: list 'a) (n: int) : list 'a + + axiom repeat_empty: + forall xs : list 'a. + repeat xs 0 = Nil + + axiom repeat_pos: + forall xs : list 'a, n. n > 0 -> + repeat xs n = xs ++ repeat xs (n - 1) + + (* nth *) + (* Here we are forced to use axiomatic definition to conform to ACSL *) + + function nth (l: list 'a) (n: int): 'a + + axiom nth_zero: + forall l : list 'a, x. + nth (Cons x l) 0 = x + + axiom nth_pos: + forall l : list 'a, n. + l <> Nil -> 0 < n < length l -> nth l n = nth (tail l) (n-1) + + (* -------------------------------------------------------------------- *) + (* --- concat --- *) + (* -------------------------------------------------------------------- *) + + lemma concat_cons: forall u v: list 'a, x: 'a. + concat (cons x u) v = cons x (concat u v) + + let lemma head_concat (u v: list 'a) + requires { u <> Nil } + ensures { head (concat u v) = head u } + = match u with Nil -> absurd | Cons _ _ -> () end + + lemma concat_tail: + forall u v: list 'a. u <> Nil -> concat (tail u) v = tail (concat u v) + (* -------------------------------------------------------------------- *) (* --- length --- *) (* -------------------------------------------------------------------- *) - axiom length_pos : forall w:list 'a. (Int.(<=) 0 (length w)) + lemma length_pos : forall w:list 'a. (Int.(<=) 0 (length w)) + + lemma length_nil : length (nil: list 'a) = 0 - axiom length_nil : length (nil: list 'a) = 0 + lemma length_nil_bis : forall w:list 'a. length w = 0 -> w = nil - axiom length_nil_bis : forall w:list 'a. length w = 0 -> w = nil + lemma length_not_nil : forall w:list 'a. w <> Nil -> 0 < length w - axiom length_cons : + lemma length_cons : forall x:'a, w:list 'a [length (cons x w)]. length (cons x w) = (Int.(+) 1 (length w)) - axiom length_concat : + lemma length_tail: + forall w: list 'a. + w <> Nil -> length (tail w) = length w - 1 + + lemma singleton_tail: forall w: list 'a. length w = 1 -> tail w = Nil + + lemma length_concat : forall u,v:list 'a [length (concat u v)]. length (concat u v) = (Int.(+) (length u) (length v)) - axiom length_repeat : - forall w:list 'a, n:int [length (repeat w n)]. - (Int.(<=) 0 n) -> length (repeat w n) = (Int.( * ) n (length w)) + let rec lemma length_repeat (w: list 'a) (n: int) + requires { 0 <= n } + ensures { length (repeat w n) = (Int.( * ) n (length w)) } + variant { n } + = if 0 < n then length_repeat w (n - 1) (* -------------------------------------------------------------------- *) (* --- nth --- *) (* -------------------------------------------------------------------- *) - axiom nth_cons: + lemma nth_cons: forall k:int, x:'a, w:list 'a [nth (cons x w) k]. - nth (cons x w) k = if k = 0 then x else nth w (k-1) + 0 <= k <= length w -> nth (cons x w) k = if k = 0 then x else nth w (k-1) + + let lemma nth_head (w: list 'a) + requires { w <> Nil } + ensures { nth w 0 = head w } + = match w with Nil -> absurd | Cons _ _ -> () end - axiom nth_concat: - forall u,v:list 'a, k:int [nth (concat u v) k]. - nth (concat u v) k = if k < length u then nth u k - else nth v (Int.(-) k (length u)) + lemma nth_tail: + forall k: int, w: list 'a. + 0 < k < length w - 1 -> nth (tail w) (k - 1) = nth w k - axiom nth_repeat: - forall n,k:int, w:list 'a [nth (repeat w n) k]. - 0 <= k < (Int.( * ) n (length w)) -> (Int.(<) 0 (length w)) -> - nth (repeat w n) k = nth w (mod k (length w)) + let rec lemma nth_concat (u v: list 'a) (k: int) + requires { 0 <= k < length u + length v } + ensures { nth (concat u v) k = + if k < length u then nth u k else nth v (k - length u) } + variant { k } + = if 0 < k && 0 < length u then nth_concat (tail u) v (k - 1) (* -------------------------------------------------------------------- *) (* --- equality of Lists --- *) @@ -92,8 +163,13 @@ theory Vlist length u = length v && forall i:int. 0 <= i < length u -> nth u i = nth v i - axiom extensionality: - forall u,v:list 'a. vlist_eq u v -> u = v + let rec lemma extensionality (u v: list 'a) + requires { vlist_eq u v } + ensures { u = v } + variant { length u } + = assert { forall x: 'a, r: list 'a. head (cons x r) = x } ; + assert { forall x: 'a, r: list 'a. tail (cons x r) = r } ; + match u, v with Cons _ x, Cons _ y -> extensionality x y | _ -> () end (* -------------------------------------------------------------------- *) (* --- neutral elements --- *) @@ -101,7 +177,6 @@ theory Vlist lemma eq_nil_concat: forall w:list 'a. vlist_eq (concat nil w) w /\ vlist_eq (concat w nil) w - meta "remove_for_" lemma eq_nil_concat lemma rw_nil_concat_left: forall w:list 'a [concat nil w]. concat nil w = w @@ -114,28 +189,24 @@ theory Vlist (* -------------------------------------------------------------------- *) lemma eq_cons_concat: - forall x:'a, v,w:list 'a [concat (cons x v) w]. + forall x:'a, v,w:list 'a [concat (cons x v) w]. vlist_eq (concat (cons x v) w) (cons x (concat v w)) - meta "remove_for_" lemma eq_cons_concat lemma rw_cons_concat: forall x:'a, v,w:list 'a [concat (cons x v) w]. (concat (cons x v) w) = (cons x (concat v w)) - meta "remove_for_" lemma rw_cons_concat lemma rw_nil_cons_concat: forall x:'a, w:list 'a [concat (cons x nil) w]. (concat (cons x nil) w) = (cons x w) - meta "remove_for_" lemma rw_nil_cons_concat (* -------------------------------------------------------------------- *) (* --- associativity --- *) (* -------------------------------------------------------------------- *) - lemma eq_assoc_concat: + lemma eq_assoc_concat: forall u,v,w:list 'a. vlist_eq (concat (concat u v) w) (concat u (concat v w)) - meta "remove_for_" lemma eq_assoc_concat (* -------------------------------------------------------------------- *) (* --- repeat --- *) @@ -149,53 +220,76 @@ theory Vlist forall w:list 'a [repeat w 0]. repeat w 0 = nil - lemma eq_repeat_one: - forall w:list 'a. vlist_eq (repeat w 1) w - meta "remove_for_" lemma eq_repeat_one + let lemma eq_repeat_one (w: list 'a) + ensures { vlist_eq (repeat w 1) w } + = assert { repeat w 1 = repeat w 0 ++ w } lemma rw_repeat_one: forall w:list 'a [repeat w 1]. repeat w 1 = w + let rec lemma repeat_more (w: list 'a) (n: int) + requires { 0 <= n } + ensures { repeat w (n + 1) = concat (repeat w n) w } + variant { n } + = if 0 < n then repeat_more w (n - 1) + + let rec lemma rw_repeat_concat (p q: int) (w: list 'a) + requires { 0 <= p } + requires { 0 <= q } + ensures { repeat w (Int.(+) p q) = concat (repeat w p) (repeat w q) } + variant { p } + = if 0 < p then rw_repeat_concat (p - 1) q w + lemma eq_repeat_concat: forall p,q:int, w:list 'a. 0 <= p -> 0 <= q -> vlist_eq (repeat w (Int.(+) p q)) (concat (repeat w p) (repeat w q)) - meta "remove_for_" lemma eq_repeat_concat - - lemma rw_repeat_concat: - forall p,q:int, w:list 'a. - 0 <= p -> 0 <= q -> - repeat w (Int.(+) p q) = concat (repeat w p) (repeat w q) - meta "remove_for_" lemma rw_repeat_concat lemma rw_repeat_after: forall p:int, w:list 'a. 0 <= p -> concat (repeat w p) w = repeat w (Int.(+) p 1) - meta "remove_for_" lemma rw_repeat_after lemma rw_repeat_before: forall p:int, w:list 'a. 0 <= p -> concat w (repeat w p) = repeat w (Int.(+) p 1) - meta "remove_for_" lemma rw_repeat_before + + let rec lemma nth_repeat (w: list 'a) (n k: int) + requires { 0 <= k < n * length w } + ensures { nth (repeat w n) k = nth w (mod k (length w)) } + variant { n } + = + if n <= 0 then absurd + else if n = 1 then () + else + if k < length w + then begin + assert { (n - 1) * length w >= 1 * length w }; + nth_repeat w (n - 1) k + end + else begin + let lw = length w in + nth_repeat w (n - 1) (k - lw); + assert { mod (lw * 1 + (k - lw)) lw = mod (k - lw) lw }; + end (*--- To avoid exponential blowup of use of repeat_after by alt-ergo ---*) -function repeat_box (list 'a) int : (list 'a) (* repeat *) + function repeat_box (list 'a) int : (list 'a) (* repeat *) -axiom rw_repeat_box_unfold: - forall w:list 'a, n:int [ repeat_box w n ]. - repeat_box w n = repeat w n + axiom rw_repeat_box_unfold: + forall w:list 'a, n:int [ repeat_box w n ]. + repeat_box w n = repeat w n -axiom rw_repeat_plus_box_unfold: - forall w:list 'a, a,b: int [ repeat_box w (Int.(+) a b) ]. - (Int.(<=) 0 a) - -> (Int.(<=) 0 b) - -> repeat_box w (Int.(+) a b) = concat (repeat w a) + axiom rw_repeat_plus_box_unfold: + forall w:list 'a, a,b: int [ repeat_box w (Int.(+) a b) ]. + (Int.(<=) 0 a) + -> (Int.(<=) 0 b) + -> repeat_box w (Int.(+) a b) = concat (repeat w a) (repeat w b) -axiom rw_repeat_plus_one_box_unfold: - forall w:list 'a, n:int [ repeat_box w n ]. - (Int.(<) 0 n) - -> (repeat_box w n = (concat (repeat w (Int.(-) n 1)) w) - && (repeat_box w (Int.(+) n 1) = concat (repeat w n) w)) + axiom rw_repeat_plus_one_box_unfold: + forall w:list 'a, n:int [ repeat_box w n ]. + (Int.(<) 0 n) + -> (repeat_box w n = (concat (repeat w (Int.(-) n 1)) w) + && (repeat_box w (Int.(+) n 1) = concat (repeat w n) w)) end diff --git a/src/plugins/wp/tests/wp_acsl/cnf.i b/src/plugins/wp/tests/wp_acsl/cnf.i index bffa1773809b5473a14aaab76464a070d5a5f858..b9ba47933cf1f8f70b6e2f5e2ec6531364d5c46b 100644 --- a/src/plugins/wp/tests/wp_acsl/cnf.i +++ b/src/plugins/wp/tests/wp_acsl/cnf.i @@ -3,9 +3,9 @@ */ /* run.config_qualif - OPT: -wp -wp-split-depth -2 -wp-par 1 -wp-msg-key cnf -wp-debug 1 + OPT: -wp -wp-split-cnf -2 -wp-par 1 -wp-msg-key cnf -wp-debug 1 -// -wp-split-depth -2 -> replace the Goal by Goal<==>CNF(Goal) +// -wp-split-cnf -2 debug mode that replaces the Goal by Goal<==>CNF(Goal) */ diff --git a/src/plugins/wp/tests/wp_acsl/label.i b/src/plugins/wp/tests/wp_acsl/label.i new file mode 100644 index 0000000000000000000000000000000000000000..8e1d2dcfffc7116cadc1eebd04c19237e5afed63 --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/label.i @@ -0,0 +1,29 @@ +/* run.config_qualif + DONTRUN: +*/ + +int *p; + +/*@ + axiomatic Observer { + predicate H{S}(int x) reads *p; + predicate P{S}(int x) reads *p; + predicate Q{S}(int x) reads *p; + predicate W{S}(int x) reads *p; + } +*/ + +/*@ + assigns *s,*p; + behavior A: + assumes H(*s); + requires P(*s); + ensures Q(*s); +*/ +int f(int *s); + +int g(int *s) { + int r = f(s); + /*@ assert W(*s); */ + return r; +} diff --git a/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle index 5c44d6289ed42523daac49a6eff9c7d7982e3573..cbdaaf5b2b7be277b720039c917f78cfc8b2e51c 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle/init_value.0.res.oracle @@ -1,7 +1,13 @@ -# frama-c -wp -wp-no-let [...] +# frama-c -wp [...] [kernel] Parsing init_value.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards +[wp:union] init_value.i:61: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] init_value.i:40: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. ------------------------------------------------------------ Function fa1 ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle index 821291b40ccce48898653fb99fb582b4c1811661..50f2495c6a01090bc6531f526007a7beb512f303 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle/init_value.1.res.oracle @@ -1,7 +1,16 @@ -# frama-c -wp -wp-no-let [...] +# frama-c -wp [...] [kernel] Parsing init_value.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards +[wp:union] init_value.i:73: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] init_value.i:72: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] init_value.i:40: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. ------------------------------------------------------------ Function fa1 ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_acsl/oracle/label.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/label.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..427d93afec44d7f58627b2d7bb0d13dac5c7f865 --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle/label.res.oracle @@ -0,0 +1,47 @@ +# frama-c -wp [...] +[kernel] Parsing label.i (no preprocessing) +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +------------------------------------------------------------ + Function g +------------------------------------------------------------ + +Goal Assertion (file label.i, line 27): +Let x = Mint_0[s]. +Let m = Mint_0[p <- v][s <- v_1]. +Assume { + Type: is_sint32(v_1) /\ is_sint32(x). + (* Heap *) + Type: (region(p.base) <= 0) /\ (region(s.base) <= 0). + (* Call 'f' *) + Have: ((P_H(Mint_0, p, x) -> P_P(Mint_0, p, x))) /\ + ((P_H(Mint_0, p, x) -> P_Q(m, p, v_1))). +} +Prove: P_W(m, p, v_1). + +------------------------------------------------------------ + +Goal Instance of 'Pre-condition for 'A' (file label.i, line 20) in 'f'' in 'g' at initialization of 'r' (file label.i, line 26) +: +Let x = Mint_0[s]. +Assume { + Type: is_sint32(x). + (* Heap *) + Type: (region(p.base) <= 0) /\ (region(s.base) <= 0). + (* Goal *) + When: P_H(Mint_0, p, x). +} +Prove: P_P(Mint_0, p, x). + +------------------------------------------------------------ +[wp] label.i:23: Warning: + Memory model hypotheses for function 'f': + /*@ behavior wp_typed: + requires \separated(p, &p); + requires \separated(s, &p); */ + int f(int *s); +[wp] label.i:25: Warning: + Memory model hypotheses for function 'g': + /*@ behavior wp_typed: + requires \separated(s, &p); */ + int g(int *s); diff --git a/src/plugins/wp/tests/wp_acsl/oracle/poly.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/poly.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..4c53a07ae903fe25075c2748defee28369a187bd --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle/poly.res.oracle @@ -0,0 +1,60 @@ +# frama-c -wp [...] +[kernel] Parsing poly.c (with preprocessing) +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +------------------------------------------------------------ + Global +------------------------------------------------------------ + +Lemma test2_ko: +Prove: (L_x_bar i_0 s_0)!=(concat (elt i_0) s_0) + +------------------------------------------------------------ + +Lemma test2_ok: +Prove: (L_x_bar i_0 s_0)=(concat (elt i_0) s_0) + +------------------------------------------------------------ + +Lemma test_ko: +Prove: (L_bar i_0 s_0)!=(concat (elt i_0) s_0) + +------------------------------------------------------------ + +Lemma test_ok: +Prove: (L_bar i_0 s_0)=(concat (elt i_0) s_0) + +------------------------------------------------------------ + +Lemma testp2_ko: +Prove: (L_x_foo a_0 s_0)!=(concat (elt a_0) s_0) + +------------------------------------------------------------ + +Lemma testp2_ok: +Prove: (L_x_foo a_0 s_0)=(concat (elt a_0) s_0) + +------------------------------------------------------------ + +Lemma testp_ko: +Prove: (L_foo a_0 s_0)!=(concat (elt a_0) s_0) + +------------------------------------------------------------ + +Lemma testp_ok: +Prove: (L_foo a_0 s_0)=(concat (elt a_0) s_0) + +------------------------------------------------------------ +------------------------------------------------------------ + Function main +------------------------------------------------------------ + +Goal Check 'NotP_ok' (file poly.c, line 57): +Prove: !P_P(1, [ 1 ]). + +------------------------------------------------------------ + +Goal Check 'Y_ko' (file poly.c, line 58): +Prove: P_Y(1, [ 1 ]). + +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle index 2aa95174028d023e0f7831b5cb8d8e0656e045f2..4a295addbe1c7f429f1a591003431cd4f65f7e09 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle/struct_fields.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-rte -wp-no-let [...] +# frama-c -wp -wp-rte [...] [kernel] Parsing struct_fields.i (no preprocessing) [wp] Running WP plugin... [rte:annot] annotating function foo diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle index 587c090f8284138bd0a5aa71eb6be18c01c8ca00..dacc5c6bc9bf9488e22eceb94ca77ba10b4bb5db 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/assigned_initialized_memvar.res.oracle @@ -23,16 +23,16 @@ [wp] [Valid] typed_descr_loop_invariant_CHECK_established (Alt-Ergo) (Cached) [wp] [Valid] typed_descr_check_CHECK (Qed) [wp] [Valid] typed_descr_loop_assigns_part1 (Qed) -[wp] [Valid] typed_descr_loop_assigns_part2 (Alt-Ergo) (Cached) +[wp] [Unsuccess] typed_descr_loop_assigns_part2 (Alt-Ergo) (Cached) [wp] [Valid] typed_descr_loop_assigns_part3 (Qed) [wp] [Valid] typed_descr_loop_assigns_part4 (Qed) [wp] [Valid] typed_descr_loop_assigns_part5 (Qed) [wp] [Unsuccess] typed_comp_check_FAILS (Alt-Ergo) (Cached) [wp] [Valid] typed_comp_loop_assigns (Qed) -[wp] Proved goals: 22 / 26 +[wp] Proved goals: 21 / 26 Qed: 15 - Alt-Ergo: 7 - Unsuccess: 4 + Alt-Ergo: 6 + Unsuccess: 5 ------------------------------------------------------------ Functions WP Alt-Ergo Total Success initialize 2 2 4 100% @@ -40,6 +40,6 @@ field 1 - 2 50.0% array 1 - 2 50.0% index 2 - 3 66.7% - descr 5 3 8 100% + descr 5 2 8 87.5% comp 1 - 2 50.0% ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle index e7b468f7aee0e722570ffd9fe0f74c3a2a093fef..63575b9739f22b3ecee9973c5fa0acf9fcbcf694 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.0.res.oracle @@ -2,6 +2,12 @@ [kernel] Parsing init_value.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards +[wp:union] init_value.i:61: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] init_value.i:40: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] 24 goals scheduled [wp] [Valid] typed_main_requires_qed_ok_Struct_Simple_a (Qed) [wp] [Valid] typed_main_requires_qed_ok_Struct_Simple_b (Qed) diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle index d10bff93b408b63526b401315b429d83248c495f..11b2e62f8964957835ca65dc89bf4cadd819b43c 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/init_value.1.res.oracle @@ -2,6 +2,15 @@ [kernel] Parsing init_value.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards +[wp:union] init_value.i:73: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] init_value.i:72: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] init_value.i:40: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] 18 goals scheduled [wp] [Unsuccess] typed_main_ko_requires_qed_ko_Sc_eq_ko (Alt-Ergo) (Cached) [wp] [Unsuccess] typed_main_ko_requires_qed_ko_Sc_t (Alt-Ergo) (Cached) diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle index 16d71d9dd45c9a62045735bcb2c47c7a779d5b8f..3ef66a3ca21b36268cc80de2cdd8f523f750f659 100644 --- a/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/initialized_memvar.res.oracle @@ -75,15 +75,14 @@ [wp] [Valid] typed_complex_struct_check_qed_ok_16 (Qed) [wp] [Valid] typed_complex_struct_check_qed_ok_17 (Qed) [wp] [Valid] typed_complex_struct_check_qed_ok_18 (Qed) -[wp] [Valid] typed_complex_struct_check_provable (Tactic) (Qed 2/2) +[wp] [Valid] typed_complex_struct_check_provable (Alt-Ergo) (Cached) [wp] Proved goals: 62 / 73 Qed: 52 - Script: 1 (Tactic) (Qed 2/2) - Alt-Ergo: 9 + Alt-Ergo: 10 Unsuccess: 11 ------------------------------------------------------------ Functions WP Alt-Ergo Total Success globals 13 7 31 64.5% locals 21 2 23 100% - complex_struct 18 - 19 100% + complex_struct 18 1 19 100% ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_acsl/oracle_qualif/poly.res.oracle b/src/plugins/wp/tests/wp_acsl/oracle_qualif/poly.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ee9a03a210dc77c43054b1c3c8b54f0b1ba13b63 --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/oracle_qualif/poly.res.oracle @@ -0,0 +1,25 @@ +# frama-c -wp [...] +[kernel] Parsing poly.c (with preprocessing) +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +[wp] 10 goals scheduled +[wp] [Unsuccess] typed_check_lemma_test2_ko (Alt-Ergo) (Cached) +[wp] [Valid] typed_check_lemma_test2_ok (Alt-Ergo) (Cached) +[wp] [Unsuccess] typed_check_lemma_test_ko (Alt-Ergo) (Cached) +[wp] [Valid] typed_check_lemma_test_ok (Alt-Ergo) (Cached) +[wp] [Unsuccess] typed_check_lemma_testp2_ko (Alt-Ergo) (Cached) +[wp] [Valid] typed_check_lemma_testp2_ok (Alt-Ergo) (Cached) +[wp] [Unsuccess] typed_check_lemma_testp_ko (Alt-Ergo) (Cached) +[wp] [Valid] typed_check_lemma_testp_ok (Alt-Ergo) (Cached) +[wp] [Valid] typed_main_check_NotP_ok (Alt-Ergo) (Cached) +[wp] [Unsuccess] typed_main_check_Y_ko (Alt-Ergo) (Cached) +[wp] Proved goals: 5 / 10 + Alt-Ergo: 5 + Unsuccess: 5 +------------------------------------------------------------ + Axiomatics WP Alt-Ergo Total Success + Lemma - 4 8 50.0% +------------------------------------------------------------ + Functions WP Alt-Ergo Total Success + main - 1 2 50.0% +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_acsl/poly.c b/src/plugins/wp/tests/wp_acsl/poly.c new file mode 100644 index 0000000000000000000000000000000000000000..db1394fc2775303f2193a9a2b752c7347d29dc3e --- /dev/null +++ b/src/plugins/wp/tests/wp_acsl/poly.c @@ -0,0 +1,59 @@ +/*@ logic \list<A> foo<A> (A i, \list<A> s) = \Cons (i, s); + + logic \list<integer> bar (integer i, \list<integer> s) = + foo(i, s); + + check lemma test_ok: \forall integer i; \forall \list<integer> s; + bar (i, s) == \Cons (i, s); + + check lemma test_ko: \forall integer i; \forall \list<integer> s; + bar (i, s) != \Cons (i, s); + + check lemma testp_ok <A>: \forall A a; \forall \list<A> s; + foo (a, s) == \Cons (a, s); + + check lemma testp_ko <A>: \forall A a; \forall \list<A> s; + foo (a, s) != \Cons (a, s); +*/ + +/*@ axiomatic X { + logic \list<A> x_foo<A>(A i, \list<A> s) reads \nothing ; + logic \list<integer> x_bar (integer i, \list<integer> s) reads \nothing ; + + axiom x_foo_value<A>: + \forall A i, \list<A> s ; + x_foo(i, s) == \Cons(i, s) ; + + axiom x_bar_value: + \forall integer i, \list<integer> s ; + x_bar(i, s) == x_foo(i, s) ; + } + + check lemma test2_ok: \forall integer i; \forall \list<integer> s; + x_bar (i, s) == \Cons (i, s); + + check lemma test2_ko: \forall integer i; \forall \list<integer> s; + x_bar (i, s) != \Cons (i, s); + + check lemma testp2_ok <A>: \forall A a; \forall \list<A> s; + x_foo (a, s) == \Cons (a, s); + + check lemma testp2_ko <A>: \forall A a; \forall \list<A> s; + x_foo (a, s) != \Cons (a, s); +*/ + +/*@ inductive P<A>(A i, \list<A> s){ + case one<B>: + \forall B b, \list<B> s ; \Cons(b, s) == [| b |] ==> P(b, s); + } +*/ + +/*@ axiomatic Y { + predicate Y<A>(A i, \list<A> s); + } +*/ + +int main(void){ + //@ check NotP_ok: !P(1, [| 1 |]) ; + //@ check Y_ko: Y(1, [| 1 |]) ; +} diff --git a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle index f95573ce220c8600bf02ea59a7baaba4783fd77e..0d6c49e91c2fd640733d1b5215eed5091410931b 100644 --- a/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle +++ b/src/plugins/wp/tests/wp_bts/oracle_qualif/bts0843.res.oracle @@ -4,8 +4,8 @@ [wp] Warning: Missing RTE guards [wp] 4 goals scheduled [wp] [Valid] typed_f3_assigns (Qed) -[wp] [Valid] typed_g3_assigns_exit (Alt-Ergo) (Trivial) -[wp] [Valid] typed_g3_assigns_normal (Alt-Ergo) (Trivial) +[wp] [Valid] typed_g3_assigns_exit (Alt-Ergo) (Cached) +[wp] [Valid] typed_g3_assigns_normal (Alt-Ergo) (Cached) [wp] [Valid] typed_g3_call_f3_requires (Qed) [wp] Proved goals: 4 / 4 Qed: 2 diff --git a/src/plugins/wp/tests/wp_gallery/binary-multiplication.0.session_qualif/script/BinaryMultiplication_loop_invariant_inv1_ok_preserved.json b/src/plugins/wp/tests/wp_gallery/binary-multiplication.0.session_qualif/script/BinaryMultiplication_loop_invariant_inv1_ok_preserved.json deleted file mode 100644 index a9679b500c90b55ba77f83446cce7da4423edf0c..0000000000000000000000000000000000000000 --- a/src/plugins/wp/tests/wp_gallery/binary-multiplication.0.session_qualif/script/BinaryMultiplication_loop_invariant_inv1_ok_preserved.json +++ /dev/null @@ -1,61 +0,0 @@ -[ { "header": "Range", "tactic": "Wp.range", - "params": { "inf": 0, "sup": 1 }, - "select": { "select": "inside-step", "at": 18, "kind": "have", - "occur": 0, "target": "b_1 mod 2", "pattern": "%$b2" }, - "children": { "Lower 0": [ { "header": "Overflow", - "tactic": "Wp.overflow", "params": {}, - "select": { "select": "inside-goal", - "occur": 0, - "target": "(to_uint64 (2*x_1))", - "pattern": "to_uint64.2$x" }, - "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 5.0522, - "steps": 47 } ], - "Lower": [ { "prover": "qed", - "verdict": "valid" } ], - "Upper": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 4.8984, - "steps": 48 } ] } } ], - "Value 0": [ { "header": "Overflow", - "tactic": "Wp.overflow", "params": {}, - "select": { "select": "inside-step", - "at": 3, "kind": "have", - "occur": 0, - "target": "(to_uint64 (a_1*b_3))", - "pattern": "to_uint64*$a$b" }, - "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 5.0366, - "steps": 181 } ], - "Lower": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 4.9686, - "steps": 42 } ], - "Upper": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 4.9181, - "steps": 42 } ] } } ], - "Value 1": [ { "header": "Overflow", - "tactic": "Wp.overflow", "params": {}, - "select": { "select": "inside-step", - "at": 3, "kind": "have", - "occur": 0, - "target": "(to_uint64 (a_1*b_3))", - "pattern": "to_uint64*$a$b" }, - "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 5.0078, - "steps": 218 } ], - "Lower": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 4.7914, - "steps": 45 } ], - "Upper": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", - "time": 4.8087, - "steps": 45 } ] } } ], - "Upper 1": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 4.9897, - "steps": 48 } ] } } ] diff --git a/src/plugins/wp/tests/wp_gallery/binary-multiplication.c b/src/plugins/wp/tests/wp_gallery/binary-multiplication.c index 26c0459f04acd1eb51b56e24764c26360ba62f6d..a02aa8b163627540a577066678c4599c8f894fb1 100644 --- a/src/plugins/wp/tests/wp_gallery/binary-multiplication.c +++ b/src/plugins/wp/tests/wp_gallery/binary-multiplication.c @@ -3,7 +3,6 @@ */ /* run.config_qualif - DEPS: @PTEST_DEPS@ @WP_SESSION@/script/BinaryMultiplication_*.json OPT: -wp-rte -wp-prover=alt-ergo,script -wp-prop=-lack @USING_WP_SESSION@ */ @@ -15,7 +14,7 @@ typedef unsigned long long uint64_t ; /*@ axiomatic mult { @ lemma sizeof_ok: ok: sizeof(uint64_t) == 2*sizeof(uint32_t); - @ lemma ax1: lack: \forall integer x, y; 0<x && 0<y ==> 0 <= 2*x*(y/2) <= x*y; + @ lemma ax1: ok: \forall integer x, y; 0<x && 0<y ==> 0 <= 2*x*(y/2) <= x*y; @ lemma ax2: lack: \forall integer x, y; (uint64_t)(x * ((uint64_t)y)) == (uint64_t)(x*y) ; @ lemma ax3: lack: \forall integer x, y; (uint64_t)(x + ((uint64_t)y)) == (uint64_t)(x+y) ; @@ -44,7 +43,7 @@ uint64_t BinaryMultiplication (uint32_t a, uint32_t b) { //@ assert a4: ok: ((b%2) != 0) ==> 2*x*(b/2) + x == x*b; //@ assert a5: ok: ((b%2) == 0) ==> 2*x*(b/2) == x*b; if (b%2) r=r+x; - //@ assert a6: lack: ok_z3: r+2*x*(b/2) == \at(a*b, Pre); + //@ assert a6: ok: r+2*x*(b/2) == \at(a*b, Pre); b=b/2; if (b==0) break; x=x*2; diff --git a/src/plugins/wp/tests/wp_gallery/dune b/src/plugins/wp/tests/wp_gallery/dune deleted file mode 100644 index 4e2c8b817fd365d5ffb809779a7f6bc45886160d..0000000000000000000000000000000000000000 --- a/src/plugins/wp/tests/wp_gallery/dune +++ /dev/null @@ -1,3 +0,0 @@ -(subdir - result_qualif/binary-multiplication.0.session_qualif/script - (copy_files ../../../binary-multiplication.0.session_qualif/script/*)) diff --git a/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle index f1fdbe0b4cc752ffa0732f9e9ad4881d6e4b515c..ed79c05926d010358c98d1d852ec33c1f873823b 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle +++ b/src/plugins/wp/tests/wp_gallery/oracle/binary-multiplication.res.oracle @@ -2,7 +2,7 @@ [kernel] Parsing binary-multiplication.c (with preprocessing) [wp] Running WP plugin... [rte:annot] annotating function BinaryMultiplication -[wp] Goal typed_lemma_ax1_lack : not tried +[wp] Goal typed_lemma_ax1_ok : not tried [wp] Goal typed_lemma_ax2_lack : not tried [wp] Goal typed_lemma_ax3_lack : not tried [wp] Goal typed_lemma_ax4_ok : not tried @@ -19,7 +19,7 @@ [wp] Goal typed_BinaryMultiplication_assert_a3_ok : not tried [wp] Goal typed_BinaryMultiplication_assert_a4_ok : not tried [wp] Goal typed_BinaryMultiplication_assert_a5_ok : not tried -[wp] Goal typed_BinaryMultiplication_assert_a6_lack_ok_z3 : not tried +[wp] Goal typed_BinaryMultiplication_assert_a6_ok : not tried [wp] Goal typed_BinaryMultiplication_loop_assigns : trivial [wp] Goal typed_BinaryMultiplication_loop_variant_decrease : not tried [wp] Goal typed_BinaryMultiplication_loop_variant_positive : not tried diff --git a/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle b/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle index 7026644d5471d6f61f57894b18b79b080c99b6ce..366438d9c4439eabb1dbc454292844b6f823170a 100644 --- a/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle +++ b/src/plugins/wp/tests/wp_gallery/oracle_qualif/binary-multiplication.res.oracle @@ -2,13 +2,15 @@ [kernel] Parsing binary-multiplication.c (with preprocessing) [wp] Running WP plugin... [rte:annot] annotating function BinaryMultiplication -[wp] 17 goals scheduled +[wp] 19 goals scheduled +[wp] [Valid] typed_lemma_ax1_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_lemma_ax4_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_lemma_ax5_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_lemma_ax7_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_lemma_sizeof_ok_ok (Qed) [wp] [Valid] typed_BinaryMultiplication_ensures_product (Alt-Ergo) (Cached) [wp] [Valid] typed_BinaryMultiplication_assert_a1_ok_deductible (Alt-Ergo) (Cached) +[wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv1_ok_preserved (Alt-Ergo) (Cached) [wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv1_ok_established (Qed) [wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv2_ok_preserved (Alt-Ergo) (Cached) [wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv2_ok_established (Alt-Ergo) (Cached) @@ -16,18 +18,17 @@ [wp] [Valid] typed_BinaryMultiplication_assert_a3_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_BinaryMultiplication_assert_a4_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_BinaryMultiplication_assert_a5_ok (Alt-Ergo) (Cached) +[wp] [Valid] typed_BinaryMultiplication_assert_a6_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_BinaryMultiplication_loop_assigns (Qed) [wp] [Valid] typed_BinaryMultiplication_loop_variant_decrease (Alt-Ergo) (Cached) [wp] [Valid] typed_BinaryMultiplication_loop_variant_positive (Qed) -[wp] [Valid] typed_BinaryMultiplication_loop_invariant_inv1_ok_preserved (Tactics 4) (Qed 1/10) (Alt-Ergo 9/10) (Cached) -[wp] Proved goals: 17 / 17 +[wp] Proved goals: 19 / 19 Qed: 4 - Script: 1 (Tactics 4) (Qed 1/10) (Alt-Ergo 9/10) (Cached) - Alt-Ergo: 12 + Alt-Ergo: 15 ------------------------------------------------------------ Axiomatics WP Alt-Ergo Total Success - Axiomatic mult 1 3 4 100% + Axiomatic mult 1 4 5 100% ------------------------------------------------------------ Functions WP Alt-Ergo Total Success - BinaryMultiplication 3 9 13 100% + BinaryMultiplication 3 11 14 100% ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle index 4024b490fe730d706edd299a9b9b6c9e00510831..e8edfb10af666d6ddb4b08c1883440d4f0e540e9 100644 --- a/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle +++ b/src/plugins/wp/tests/wp_hoare/oracle/dispatch_var2.0.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-model 'Typed (Ref)' -wp-no-let [...] +# frama-c -wp -wp-model 'Typed (Ref)' [...] [kernel] Parsing dispatch_var2.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle b/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle index b4a4eb8afb2222372e930c8becc2af080a8488ef..63e7e9f7e76ac58aa09826b19ed706ed2b0520cf 100644 --- a/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle +++ b/src/plugins/wp/tests/wp_hoare/oracle_qualif/dispatch_var2.0.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-model 'Typed (Ref)' -wp-no-let [...] +# frama-c -wp -wp-model 'Typed (Ref)' [...] [kernel] Parsing dispatch_var2.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json index ce1db3baf849bcda6d5c7bc45ce2fad9d913cc87..7d837c3c45aefca935c29158827aa3c9cb926857 100644 --- a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json +++ b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_n.json @@ -1,8 +1,9 @@ -[ { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {}, +[ { "prover": "script", "verdict": "valid", "time": 0.0204 }, + { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {}, "select": { "select": "inside-step", "at": 1, "kind": "have", "occur": 0, "target": "not (bit_test off_0 15)", "pattern": "!bit_test$off15" }, "children": { "Bit #15 (inf)": [ { "prover": "qed", "verdict": "valid" } ], - "Bit #15 (sup)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0174, - "steps": 32 } ] } } ] + "Bit #15 (sup)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0204, + "steps": 52 } ] } } ] diff --git a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json index 6efc632858bf4117e91e9c9f8cb43ca24a57fcc7..85a816285388870ca9a5453014af405aae549ac5 100644 --- a/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json +++ b/src/plugins/wp/tests/wp_plugin/bitmask0x8000.0.session_qualif/script/lemma_res_y.json @@ -1,8 +1,9 @@ -[ { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {}, +[ { "prover": "script", "verdict": "valid", "time": 0.0194 }, + { "header": "Bit-Test Range", "tactic": "Wp.bittestrange", "params": {}, "select": { "select": "inside-step", "at": 1, "kind": "have", "occur": 0, "target": "(bit_test off_0 15)", "pattern": "bit_test$off15" }, - "children": { "Bit #15 (inf)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0166, - "steps": 32 } ], + "children": { "Bit #15 (inf)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0194, + "steps": 52 } ], "Bit #15 (sup)": [ { "prover": "qed", "verdict": "valid" } ] } } ] diff --git a/src/plugins/wp/tests/wp_plugin/config.sh b/src/plugins/wp/tests/wp_plugin/config.sh index d0f7c134c09979614f7908269d1d33e30e9dc8f1..de8bba4f29673ebd4f2af8b6285e07cb5a34a682 100755 --- a/src/plugins/wp/tests/wp_plugin/config.sh +++ b/src/plugins/wp/tests/wp_plugin/config.sh @@ -1,7 +1,7 @@ #!/bin/sh -ERGO=`alt-ergo -version` -WHY3=`why3 --version` +ERGO=$(alt-ergo --version) +WHY3=$(why3 --version) echo "----------------------------------------------------------" echo "WP Requirements for Qualif Tests" diff --git a/src/plugins/wp/tests/wp_plugin/math.i b/src/plugins/wp/tests/wp_plugin/math.i index 53a3106b4c5a605686807ae0bf937daa3a0c65db..ee5b3f68102f0e7431b942ddb1f54d3abb689ff9 100644 --- a/src/plugins/wp/tests/wp_plugin/math.i +++ b/src/plugins/wp/tests/wp_plugin/math.i @@ -3,8 +3,8 @@ */ /* run.config_qualif - OPT: -wp-prover alt-ergo -wp-prop=-ko -wp-timeout 100 -wp-steps 1500 - OPT: -wp-prover alt-ergo -wp-prop=ko -wp-timeout 100 -wp-steps 10 + OPT: -wp-prover alt-ergo -wp-prop=-ko + OPT: -wp-prover alt-ergo -wp-prop=ko -wp-steps 10 */ // -------------------------------------------------------------------------- diff --git a/src/plugins/wp/tests/wp_plugin/no_step_limit.conf b/src/plugins/wp/tests/wp_plugin/no_step_limit.conf index 8431029cc72c4dc267bef9b413c03d74406ae297..b027de63b86182b44d982297506a0715de163531 100644 --- a/src/plugins/wp/tests/wp_plugin/no_step_limit.conf +++ b/src/plugins/wp/tests/wp_plugin/no_step_limit.conf @@ -6,8 +6,8 @@ running_provers_max = 2 timelimit = 5 [prover] -command = "alt-ergo -timelimit %t %f" -driver = "alt_ergo_2_2_0" +command = "alt-ergo --timelimit %t %f" +driver = "alt_ergo" in_place = false interactive = false name = "no-steps" diff --git a/src/plugins/wp/tests/wp_plugin/no_step_limit.i b/src/plugins/wp/tests/wp_plugin/no_step_limit.i index 874baf0c74f20fa9a2510a1cbc783138caedaf2a..569fecc3020f9ba4076e2c733b7c4f109bdac3d1 100644 --- a/src/plugins/wp/tests/wp_plugin/no_step_limit.i +++ b/src/plugins/wp/tests/wp_plugin/no_step_limit.i @@ -7,7 +7,7 @@ OPT: -wp -wp-prover no-steps -wp-steps 10 -wp-timeout 1 -wp-cache none -wp-no-cache-env -wp-msg-key shell */ -// cache is locally deactivated to see the option +// cache is locally deactivated to be sure that we call the prover /*@ lemma truc: \false ; diff --git a/src/plugins/wp/tests/wp_plugin/nth.i b/src/plugins/wp/tests/wp_plugin/nth.i index 33236ef838299d9fff8a9616d03b62b76f261b9c..88491366a5ba6dc6e2092f577d26e26635d20578 100644 --- a/src/plugins/wp/tests/wp_plugin/nth.i +++ b/src/plugins/wp/tests/wp_plugin/nth.i @@ -83,14 +83,16 @@ check lemma nth_repeat_3: ok: \nth ( ([| f(0), f(1), f(2), f(3) |] *^ 3) ^ [| f(12) |] , 12 ) == f(12); check lemma nth_repeat_4: ok: \nth ( ([| f(0), f(1), f(2), f(3) |] *^ 3) ^ [| f(12),f(13),f(14)|] ^ S, 13 ) == f(13); - lemma access_16_16: ok: - \forall integer k ; 0 <= k < 16 ==> - f(k)==\nth([| f(0), f(1), f(2), f(3), f(4), f(5), f(6), f(7), - f(8), f(9), f(10), f(11), f(12), f(13), f(14), f(15) |], k); lemma access_4_4: ok: \forall integer k ; 0 <= k < 4 ==> - f(k)==\nth([| f(0), f(1), f(2), f(3) |], k); + f(k)==\nth([| f(0), f(1), f(2), f(3) |], k); + + // Performance problem with Alt-Ergo, cvc4 & z3 are ok. + lemma access_8_8: ko: + \forall integer k ; 0 <= k < 6 ==> + f(k)==\nth([| f(0), f(1), f(2), f(3), + f(4), f(5), f(6), f(7) |], k); lemma eq_repeat_concat_3: ok: (S *^ 3) == (S ^ S ^ S) ; diff --git a/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle index 9f83df04d9f5f3ca44cb15ff7c72b6eb6ca4d3fc..916d7d88f9aadff39b4464b8fe1e785ef7762ada 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle/bool.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-no-let [...] +# frama-c -wp [...] [kernel] Parsing bool.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle index 78ddf615c388fbb450e6f01f9deb175c6107177b..95d16f1f5457093aa994b77335a29b679251ca08 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle/dynamic.1.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-no-let [...] +# frama-c -wp [...] [kernel] Parsing dynamic.i (no preprocessing) [wp] Running WP plugin... [kernel:dyncalls] Computing dynamic calls. diff --git a/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle index c93629cbb62d4b5fa92e4144cc23d6e0c1089cf1..3042f600a4b71ccf48ac6ebb5e178b17fd97c225 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle/nth.res.oracle @@ -96,35 +96,33 @@ Prove: true Axiomatic 'Nth' ------------------------------------------------------------ -Lemma access_16_16: -Prove: (0<=k_0) -> (k_0<=15) +Lemma access_4_4: +Prove: (0<=k_0) -> (k_0<=3) -> ((nth - (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3)) - (elt (L_f 4)) (elt (L_f 5)) (elt (L_f 6)) (elt (L_f 7)) - (elt (L_f 8)) (elt (L_f 9)) (elt (L_f 10)) (elt (L_f 11)) - (elt (L_f 12)) (elt (L_f 13)) (elt (L_f 14)) (elt (L_f 15))) + (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3))) k_0)=(L_f k_0)) ------------------------------------------------------------ -Lemma access_4_4: -Assume: 'access_16_16' -Prove: (0<=k_0) -> (k_0<=3) +Lemma access_8_8: +Assume: 'access_4_4' +Prove: (0<=k_0) -> (k_0<=5) -> ((nth - (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3))) - k_0)=(L_f k_0)) + (concat (elt (L_f 0)) (elt (L_f 1)) (elt (L_f 2)) (elt (L_f 3)) + (elt (L_f 4)) (elt (L_f 5)) (elt (L_f 6)) (elt (L_f 7))) k_0)= + (L_f k_0)) ------------------------------------------------------------ Lemma access_repeat_concat_3: -Assume: 'eq_repeat_concat_3' 'access_4_4' 'access_16_16' +Assume: 'eq_repeat_concat_3' 'access_8_8' 'access_4_4' Prove: (0<=k_0) -> (k_0<(3*(length L_S))) -> ((nth (concat L_S L_S L_S) k_0)=(nth (repeat L_S 3) k_0)) ------------------------------------------------------------ Lemma eq_repeat_concat_3: -Assume: 'access_4_4' 'access_16_16' +Assume: 'access_8_8' 'access_4_4' Prove: true ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle index 142edc4f0cf5a5c62c1e991a3b6ef2d7e1802877..80ce1585aa40e373b6a763e0313aa7362379c287 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/bool.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-no-let [...] +# frama-c -wp [...] [kernel] Parsing bool.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle index 97170530440a3845d5f2f211a8210288c2fe968d..872f60957845a4f288caf9656729b8c01337fdfb 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/config.res.oracle @@ -1,7 +1,7 @@ ---------------------------------------------------------- WP Requirements for Qualif Tests ---------------------------------------------------------- -1. The Alt-Ergo theorem prover, version 2.2.0 +1. The Alt-Ergo theorem prover, version 2.4.2 2. The Why3 platform, version 1.6.0 3. The environment variable FRAMAC_WP_CACHEDIR is defined 4. The environment variable FRAMAC_WP_CACHE is defined diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle index 81a4482c29daf7beee20bc107cd21a74967cd539..b14c7877833655b73d792637d3590c03ac47c185 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_call.2.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-split [...] +# frama-c -wp [...] [kernel] Parsing doomed_call.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle index 79b0373da5e3574e35ac0322a24ca4698fa1044c..7af31c3fade31c46da6450fb0c3854db349c6566 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/doomed_dead.1.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-split -wp-steps 100 [...] +# frama-c -wp -wp-steps 100 [...] [kernel] Parsing doomed_dead.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle index 071c3882ef864c99746b31c65f61d79bd3750fe8..6a8654dd7d2de39d670103ad43abc2a9cd79692d 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/dynamic.1.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-no-let [...] +# frama-c -wp [...] [kernel] Parsing dynamic.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle index 439fab9b307931b975e697bb0cf2e8b7672fffbe..64b72dd87d8a2b06987d2ecd68d2073131bd47d9 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/fallback.res.oracle @@ -2,7 +2,7 @@ [kernel] Parsing fallback.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards -[wp] Warning: Prover 'Alt-Ergo:1.2.0' not found, fallback to 'Alt-Ergo:2.2.0' +[wp] Warning: Prover 'Alt-Ergo:1.2.0' not found, fallback to 'Alt-Ergo:2.4.2' [wp] 1 goal scheduled [wp] [Valid] typed_job_ensures (Alt-Ergo) (Cached) [wp] Proved goals: 1 / 1 diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle index e48d5ca2e49ca5c7a548b7a861bff87d268acf30..e524c1cb1cb2d70a571f66dfe6902ba21b6f0eeb 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.0.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-timeout 100 -wp-steps 1500 [...] +# frama-c -wp [...] [kernel] Parsing math.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle index fc8e2c09ad5ec29ca0ab3ddfb253427904cce81b..12b2a96e99f4d5f9d51037d6e9530a6db39d8391 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/math.1.res.oracle @@ -1,4 +1,4 @@ -# frama-c -wp -wp-timeout 100 -wp-steps 10 [...] +# frama-c -wp -wp-steps 10 [...] [kernel] Parsing math.i (no preprocessing) [wp] Running WP plugin... [wp] Warning: Missing RTE guards diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle index 452e8047b202ff04ef91186ef6d26c207cc78dc8..0ad955337d7de65fff2945690804cd5a4d4f4b11 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/no_step_limit.res.oracle @@ -2,6 +2,7 @@ [kernel] Parsing no_step_limit.i (no preprocessing) [wp] Running WP plugin... [wp] 1 goal scheduled +[wp] Warning: no-steps does not support steps limit (ignored option) [wp] [Unsuccess] typed_lemma_truc (no-steps) [wp] Proved goals: 0 / 1 Unsuccess: 1 diff --git a/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle index 1aeb2e63b01db6747367dd9c88cba0399224c93d..edb9844f6a4b1a158e205f172e3bd85ea2241b20 100644 --- a/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle +++ b/src/plugins/wp/tests/wp_plugin/oracle_qualif/nth.res.oracle @@ -2,8 +2,8 @@ [kernel] Parsing nth.i (no preprocessing) [wp] Running WP plugin... [wp] 26 goals scheduled -[wp] [Valid] typed_lemma_access_16_16_ok (Alt-Ergo) (Cached) [wp] [Valid] typed_lemma_access_4_4_ok (Alt-Ergo) (Cached) +[wp] [Unsuccess] typed_lemma_access_8_8_ko (Alt-Ergo) (Cached) [wp] [Valid] typed_lemma_access_repeat_concat_3_ok_lack (Alt-Ergo) (Cached) [wp] [Valid] typed_check_lemma_constructor_elt_ok (Qed) [wp] [Valid] typed_lemma_eq_repeat_concat_3_ok (Qed) @@ -28,13 +28,13 @@ [wp] [Valid] typed_check_lemma_right_unfold_repeat1_ok (Qed) [wp] [Valid] typed_check_lemma_right_unfold_repeat2_ok (Qed) [wp] [Valid] typed_check_lemma_subsequence1_ok (Qed) -[wp] Proved goals: 25 / 26 +[wp] Proved goals: 24 / 26 Qed: 22 - Alt-Ergo: 3 - Unsuccess: 1 + Alt-Ergo: 2 + Unsuccess: 2 ------------------------------------------------------------ Axiomatics WP Alt-Ergo Total Success Axiomatic Equality 13 - 13 100% Axiomatic MkRepeat 4 - 4 100% - Axiomatic Nth 5 3 9 88.9% + Axiomatic Nth 5 2 9 77.8% ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json b/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json index c4a3730943a5705f49d9a0510a3f8b28c275b328..1eb7da85a99959de78cab81e75af587c16b003e7 100644 --- a/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json +++ b/src/plugins/wp/tests/wp_plugin/unsigned.0.session_qualif/script/lemma_U32.json @@ -1,11 +1,9 @@ -[ { "prover": "Alt-Ergo:2.2.0", "verdict": "timeout", "time": 10. }, - { "prover": "script", "verdict": "valid" }, +[ { "prover": "script", "verdict": "unknown" }, { "header": "Bitwise Eq.", "tactic": "Wp.bitwised", "params": { "Wp.bitwised.range": 32 }, "select": { "select": "clause-goal", "target": "(land 4294967295 x_0)=x_0", "pattern": "=land$x4294967295$x" }, - "children": { "range": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0054, - "steps": 15 } ], + "children": { "range": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. } ], "bitwise": [ { "prover": "qed", "verdict": "valid" } ] } } ] diff --git a/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json b/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json index 77a4f51c832cb8e9d049e59dd20d0b4644788ff9..8b2dde4abb4656b6c0861116139230d62716131a 100644 --- a/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json +++ b/src/plugins/wp/tests/wp_tip/induction.0.session_qualif/script/lemma_ByInd.json @@ -1,12 +1,13 @@ -[ { "header": "Induction", "tactic": "Wp.induction", +[ { "prover": "script", "verdict": "valid", "time": 0.04 }, + { "header": "Induction", "tactic": "Wp.induction", "params": { "base": { "select": "kint", "val": "0" } }, "select": { "select": "inside-goal", "occur": 0, "target": "(L_f x_0)", "pattern": "L_f$x" }, - "children": { "Base": [ { "prover": "Alt-Ergo:2.2.0", "verdict": "valid", - "time": 0.0074, "steps": 6 } ], - "Induction (sup)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0098, - "steps": 21 } ], - "Induction (inf)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0097, - "steps": 20 } ] } } ] + "children": { "Base": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid", + "time": 0.0035, "steps": 14 } ], + "Induction (sup)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0247, + "steps": 325 } ], + "Induction (inf)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0118, + "steps": 32 } ] } } ] diff --git a/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json b/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json index d5763f40f15dd0fb0e845177f6d42085f36486ca..475ea8fe40f40e261b057116b3796f55f5e84f28 100644 --- a/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json +++ b/src/plugins/wp/tests/wp_tip/induction.1.session_qualif/script/lemma_ByInd.json @@ -1,12 +1,11 @@ -[ { "prover": "Alt-Ergo:2.2.0", "verdict": "unknown" }, - { "prover": "script", "verdict": "unknown" }, +[ { "prover": "script", "verdict": "unknown" }, { "header": "Induction", "tactic": "Wp.induction", "params": { "base": { "select": "kint", "val": "0" } }, "select": { "select": "inside-goal", "occur": 0, "target": "x_0", "pattern": "$x" }, - "children": { "Base": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "unknown" } ], - "Induction (sup)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "unknown" } ], - "Induction (inf)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "timeout", "time": 1. } ] } } ] + "children": { "Base": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. } ], + "Induction (sup)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. } ], + "Induction (inf)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. } ] } } ] diff --git a/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json b/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json index 5e068a85c7f8f2ef58ef88d2b0b651607423e155..19e60ed0b607ee5b192a441d5d08ae2c86ed06af 100644 --- a/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json +++ b/src/plugins/wp/tests/wp_tip/induction.2.session_qualif/script/lemma_ByInd.json @@ -1,12 +1,11 @@ -[ { "prover": "Alt-Ergo:2.2.0", "verdict": "unknown" }, - { "prover": "script", "verdict": "unknown" }, +[ { "prover": "script", "verdict": "unknown" }, { "header": "Induction", "tactic": "Wp.induction", "params": { "base": { "select": "kint", "val": "0" } }, "select": { "select": "inside-goal", "occur": 0, "target": "y_0", "pattern": "$y" }, - "children": { "Base": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "unknown" } ], - "Induction (sup)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "unknown" } ], - "Induction (inf)": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "timeout", "time": 1. } ] } } ] + "children": { "Base": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. } ], + "Induction (sup)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. } ], + "Induction (inf)": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. } ] } } ] diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/proof.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/proof.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..276f2354052a77a51a160cbd408812bcc194595a --- /dev/null +++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/proof.res.oracle @@ -0,0 +1,11 @@ +# frama-c -wp [...] +[kernel] Parsing proof.i (no preprocessing) +[wp] Running WP plugin... +[wp] Warning: No goal generated +------------------------------------------------------------ +/* Generated by Frama-C */ +/*@ strategy P1: \prover("alt-ergo"); */ +/*@ strategy P2: \prover(0.5); */ +/*@ strategy P3: \prover("alt-ergo",3.0); */ +/*@ strategy P4: P1, P2, P3, \default; */ + diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.0.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0bcfae5a92959b95342e01fa937cd88c40831ebe --- /dev/null +++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.0.res.oracle @@ -0,0 +1,28 @@ +# frama-c -wp [...] +[kernel] Parsing strategy.c (with preprocessing) +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +[wp] 2 goals scheduled +[wp] [Unsuccess] typed_target_ensures (Alt-Ergo) (Cached) +[wp] [Valid] typed_target_assigns (Qed) +[wp] Proved goals: 1 / 2 + Qed: 1 + Unsuccess: 1 +------------------------------------------------------------ + Function target +------------------------------------------------------------ + +Goal Post-condition (file strategy.c, line 46) in 'target': +Assume { + Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z). + (* Pre-condition *) + Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999). +} +Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))). +Prover Alt-Ergo returns Unsuccess + +------------------------------------------------------------ +------------------------------------------------------------ + Functions WP Alt-Ergo Total Success + target 1 - 2 50.0% +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.1.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..a439255effce75c9e03ad1957717ddcc7e77cf90 --- /dev/null +++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.1.res.oracle @@ -0,0 +1,52 @@ +# frama-c -wp [...] +[kernel] Parsing strategy.c (with preprocessing) +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +[wp] 2 goals scheduled +[wp] [Valid] typed_target_assigns (Qed) +[wp] [Unsuccess] typed_target_ensures (Tactics 13) +[wp] Proved goals: 1 / 2 + Qed: 1 + Unsuccess: 1 +------------------------------------------------------------ + Function target +------------------------------------------------------------ + +Goal Post-condition (file strategy.c, line 46) in 'target': +Assume { + Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z). + (* Pre-condition *) + Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999). +} +Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))). +Prover Script returns Unsuccess + +------------------------------------------------------------ +Subgoal 1/1: + - Post-condition + - Overflow (In-Range) + - Overflow (In-Range) + - Overflow (In-Range) +Goal Wp.Tactical.typed_target_ensures-12 (generated): +Let x_1 = t + x + y + z. +Let x_2 = x + y + z. +Let x_3 = x + y. +Assume { + Have: 0 <= x_3. + Have: x_3 <= 4294967295. + Have: 0 <= x_2. + Have: x_2 <= 4294967295. + Have: (-2147483648) <= x_1. + Have: x_1 <= 2147483647. + Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z). + (* Pre-condition *) + Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999). +} +Prove: P_P(x_1). +Prover Alt-Ergo returns Unsuccess + +------------------------------------------------------------ +------------------------------------------------------------ + Functions WP Alt-Ergo Total Success + target 1 - 2 50.0% +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.2.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.2.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ca5793fb1a1ba8e7da0c82f34edb192a2236e25c --- /dev/null +++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.2.res.oracle @@ -0,0 +1,52 @@ +# frama-c -wp [...] +[kernel] Parsing strategy.c (with preprocessing) +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +[wp] 2 goals scheduled +[wp] [Valid] typed_target_assigns (Qed) +[wp] [Unsuccess] typed_target_ensures (Tactics 3) (Alt-Ergo 4/4) (Cached) +[wp] Proved goals: 1 / 2 + Qed: 1 + Unsuccess: 1 +------------------------------------------------------------ + Function target +------------------------------------------------------------ + +Goal Post-condition (file strategy.c, line 46) in 'target': +Assume { + Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z). + (* Pre-condition *) + Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999). +} +Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))). +Prover Script returns Unsuccess + +------------------------------------------------------------ +Subgoal 1/1: + - Post-condition + - Overflow (In-Range) + - Overflow (In-Range) + - Overflow (In-Range) +Goal Wp.Tactical.typed_target_ensures-6 (generated): +Let x_1 = t + x + y + z. +Let x_2 = x + y + z. +Let x_3 = x + y. +Assume { + Have: 0 <= x_3. + Have: x_3 <= 4294967295. + Have: 0 <= x_2. + Have: x_2 <= 4294967295. + Have: (-2147483648) <= x_1. + Have: x_1 <= 2147483647. + Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z). + (* Pre-condition *) + Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999). +} +Prove: P_P(x_1). +Prover Alt-Ergo returns Unsuccess + +------------------------------------------------------------ +------------------------------------------------------------ + Functions WP Alt-Ergo Total Success + target 1 - 2 50.0% +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.3.res.oracle b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.3.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..ad30c792620a6ac36164a3de5f3a7eb8bcfff589 --- /dev/null +++ b/src/plugins/wp/tests/wp_tip/oracle_qualif/strategy.3.res.oracle @@ -0,0 +1,53 @@ +# frama-c -wp [...] +[kernel] Parsing strategy.c (with preprocessing) +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +[wp] 2 goals scheduled +[wp] [Valid] typed_target_assigns (Qed) +[wp] [Unsuccess] typed_target_ensures (Tactics 3) (Alt-Ergo 4/4) (Cached) +[wp] Proved goals: 1 / 2 + Qed: 1 + Unsuccess: 1 +------------------------------------------------------------ + Function target +------------------------------------------------------------ + +Goal Post-condition (file strategy.c, line 46) in 'target': +Assume { + Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z). + (* Pre-condition *) + Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999). +} +Prove: P_P(to_sint32(t + to_uint32(z + to_uint32(x + y)))). +Prover Alt-Ergo returns Unsuccess +Prover Script returns Unsuccess + +------------------------------------------------------------ +Subgoal 1/1: + - Post-condition + - Overflow (In-Range) + - Overflow (In-Range) + - Overflow (In-Range) +Goal Wp.Tactical.typed_target_ensures-6 (generated): +Let x_1 = t + x + y + z. +Let x_2 = x + y + z. +Let x_3 = x + y. +Assume { + Have: 0 <= x_3. + Have: x_3 <= 4294967295. + Have: 0 <= x_2. + Have: x_2 <= 4294967295. + Have: (-2147483648) <= x_1. + Have: x_1 <= 2147483647. + Type: is_uint32(t) /\ is_uint32(x) /\ is_uint32(y) /\ is_uint32(z). + (* Pre-condition *) + Have: (t <= 999) /\ (x <= 999) /\ (y <= 999) /\ (z <= 999). +} +Prove: P_P(x_1). +Prover Alt-Ergo returns Unsuccess + +------------------------------------------------------------ +------------------------------------------------------------ + Functions WP Alt-Ergo Total Success + target 1 - 2 50.0% +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json index 255539ba9f34b22d89852d5659ffc0969380c9f1..28f66b07060696d4cab811bb4b79ab4f08e7efa3 100644 --- a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json +++ b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_char.json @@ -1,27 +1,28 @@ -[ { "header": "Overflow", "tactic": "Wp.overflow", "params": {}, +[ { "prover": "script", "verdict": "valid", "time": 0.0322 }, + { "header": "Overflow", "tactic": "Wp.overflow", "params": {}, "select": { "select": "inside-goal", "occur": 0, "target": "(to_uint32 c_0)", "pattern": "to_uint32$c" }, - "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0094, - "steps": 25 } ], - "Lower": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0157, - "steps": 53 }, + "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0082, + "steps": 32 } ], + "Lower": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.024, + "steps": 155 }, { "header": "Overflow", "tactic": "Wp.overflow", "params": {}, "select": { "select": "inside-goal", "occur": 0, "target": "(to_uint32\n (ui_0+((4294967296+c_0+(-4294967296*(c_0 div 4294967296))) mod 4294967296)))", "pattern": "to_uint32+$ui%+42949672964294967296" }, - "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0", + "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid", "time": 0.0166, "steps": 27 } ], - "Lower": [ { "prover": "Alt-Ergo:2.2.0", + "Lower": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid", "time": 0.023, "steps": 25 } ], - "Upper": [ { "prover": "Alt-Ergo:2.2.0", + "Upper": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid", "time": 0.0739, "steps": 73 } ] } } ], diff --git a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json index 97c383396b0c68dc8ea302b5db23e1fe35c93227..4e30c1ba53e77f51474cc2b14f03f2bde9d19c1a 100644 --- a/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json +++ b/src/plugins/wp/tests/wp_tip/overflow.0.session_qualif/script/lemma_j_incr_short.json @@ -1,27 +1,28 @@ -[ { "header": "Overflow", "tactic": "Wp.overflow", "params": {}, +[ { "prover": "script", "verdict": "valid", "time": 0.0235 }, + { "header": "Overflow", "tactic": "Wp.overflow", "params": {}, "select": { "select": "inside-goal", "occur": 0, "target": "(to_uint32 s_0)", "pattern": "to_uint32$s" }, - "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0098, - "steps": 25 } ], - "Lower": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0198, - "steps": 54 }, + "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0069, + "steps": 32 } ], + "Lower": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0166, + "steps": 154 }, { "header": "Overflow", "tactic": "Wp.overflow", "params": {}, "select": { "select": "inside-goal", "occur": 0, "target": "(to_uint32\n (ui_0+((4294967296+s_0+(-4294967296*(s_0 div 4294967296))) mod 4294967296)))", "pattern": "to_uint32+$ui%+42949672964294967296" }, - "children": { "In-Range": [ { "prover": "Alt-Ergo:2.2.0", + "children": { "In-Range": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid", "time": 0.017, "steps": 27 } ], - "Lower": [ { "prover": "Alt-Ergo:2.2.0", + "Lower": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid", "time": 0.0232, "steps": 25 } ], - "Upper": [ { "prover": "Alt-Ergo:2.2.0", + "Upper": [ { "prover": "Alt-Ergo:2.4.2", "verdict": "valid", "time": 0.2614, "steps": 73 } ] } } ], diff --git a/src/plugins/wp/tests/wp_tip/proof.i b/src/plugins/wp/tests/wp_tip/proof.i new file mode 100644 index 0000000000000000000000000000000000000000..83b6f05d2aaae1a387ffdb8a9d128ca173efc6f7 --- /dev/null +++ b/src/plugins/wp/tests/wp_tip/proof.i @@ -0,0 +1,16 @@ +/* run.config + DONTRUN: +*/ + +/* run.config_qualif + OPT: -print + */ + +// Provers + +/*@ + strategy P1: \prover("alt-ergo"); + strategy P2: \prover(0.5); + strategy P3: \prover("alt-ergo",3.0); + strategy P4: P1, P2, P3, \default; + */ diff --git a/src/plugins/wp/tests/wp_tip/strategy.c b/src/plugins/wp/tests/wp_tip/strategy.c new file mode 100644 index 0000000000000000000000000000000000000000..48535ecd7a7de5894e172116d7ef8b29294dc5b5 --- /dev/null +++ b/src/plugins/wp/tests/wp_tip/strategy.c @@ -0,0 +1,52 @@ +/* run.config + DONTRUN: +*/ + +/* run.config_qualif + OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy Prover + OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy Eager + OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy EagerRange + OPT: -wp-status -wp-prover tip -wp-script dry -wp-strategy Lazy + */ + +/*@ + axiomatic Observers { + predicate P(integer x); + } +*/ + +/*@ + strategy Prover: \prover("alt-ergo",0.1); + + strategy Lazy: + Prover, + \tactic("Wp.overflow" + ,\pattern(\any(to_uint32(_),to_sint32(_))) + ); + + strategy Eager: + \tactic("Wp.overflow" + ,\pattern(\any(to_uint32(_),to_sint32(_))) + ), + Prover; + + strategy EagerRange: + \tactic("Wp.overflow" + ,\pattern(\any(to_uint32(_),to_sint32(_))) + ,\child("In-Range",EagerRange) + ,\children(Prover) + ), + Prover; + +*/ + + +/*@ + requires x < 1000 && y < 1000 && z < 1000 && t < 1000; + ensures P(\result); + assigns \nothing; +*/ +int target(unsigned x, unsigned y, unsigned z, unsigned t) +{ + return x+y+z+t; +} diff --git a/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json b/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json index c70dddec42c798d67d2e64caedcd77123e5f7e9c..4808c8f42b02e081c60a6b774215a29326d459c5 100644 --- a/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json +++ b/src/plugins/wp/tests/wp_tip/tac_split_quantifiers.0.session_qualif/script/split_ensures_Goal_Exist_Or.json @@ -2,5 +2,4 @@ "select": { "select": "clause-goal", "target": "exists i_0,i_1,i_2:int.\n(P_Q1 1) \\/ (P_P1 i_0) \\/ (P_P2 i_1 i_2) \\/ (exists i_3:int.\n (P_Q2 i_0 i_3))", "pattern": "\\EP_Q11" }, - "children": { "Split": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "unknown" } ] } } ] + "children": { "Split": [ ] } } ] diff --git a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle index 91d993407e90198cfac7642dd37c622a3ba79925..11203eb0f175287b1e86ce888cc404cc9f9c9aa5 100644 --- a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle +++ b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.0.res.oracle @@ -5,9 +5,18 @@ [wp] cast_fits.i:13: Warning: Cast with incompatible pointers types (source: __anonstruct_L2_2*) (target: sint32*) +[wp:union] cast_fits.i:45: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] cast_fits.i:52: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] cast_fits.i:54: Warning: Cast with incompatible pointers types (source: __anonunion_L8_8*) (target: sint32*) +[wp:union] cast_fits.i:61: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] cast_fits.i:60: Warning: Cast with incompatible pointers types (source: sint32*) (target: __anonunion_L8_8*) diff --git a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle index 76f3b9532f3c8ba5cf43aac5657b1af1bfd9d1c9..1d8b88a4d13589c516d004147b4678d62f2ea2ba 100644 --- a/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle +++ b/src/plugins/wp/tests/wp_typed/oracle/cast_fits.1.res.oracle @@ -5,9 +5,18 @@ [wp] cast_fits.i:13: Warning: Cast with incompatible pointers types (source: __anonstruct_L2_2*) (target: sint32*) +[wp:union] cast_fits.i:45: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] cast_fits.i:52: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] cast_fits.i:54: Warning: Cast with incompatible pointers types (source: __anonunion_L8_8*) (target: sint32*) +[wp:union] cast_fits.i:61: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] cast_fits.i:60: Warning: Cast with incompatible pointers types (source: sint32*) (target: __anonunion_L8_8*) diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle index 8f652bcc9d04f6adee76d97b60152802f2958b57..87ff7ce151b9fecfb0a2e46a31f66fea5b317107 100644 --- a/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle +++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/cast_fits.res.oracle @@ -5,9 +5,18 @@ [wp] cast_fits.i:13: Warning: Cast with incompatible pointers types (source: __anonstruct_L2_2*) (target: sint32*) +[wp:union] cast_fits.i:45: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. +[wp:union] cast_fits.i:52: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] cast_fits.i:54: Warning: Cast with incompatible pointers types (source: __anonunion_L8_8*) (target: sint32*) +[wp:union] cast_fits.i:61: Warning: + Accessing union fields with WP might be unsound. + Please refer to WP manual. [wp] cast_fits.i:60: Warning: Cast with incompatible pointers types (source: sint32*) (target: __anonunion_L8_8*) diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle index d45965e41d3734ccdf206c083cb67f0dac3fb562..bfa547fec04c79c4e902f386ba93ad7591e83747 100644 --- a/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle +++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/frame.res.oracle @@ -3,18 +3,18 @@ [wp] Running WP plugin... [wp] Warning: Missing RTE guards [wp] 6 goals scheduled -[wp] [Unsuccess] typed_compound_assert_SEP (Alt-Ergo) (Cached) +[wp] [Valid] typed_compound_assert_SEP (Alt-Ergo) (Cached) [wp] [Valid] typed_compound_assert_RES (Alt-Ergo) (Cached) [wp] [Valid] typed_local_region_assert_A_X (Alt-Ergo) (Cached) [wp] [Unsuccess] typed_local_region_assert_A_Y (Alt-Ergo) (Cached) [wp] [Valid] typed_formal_region_assert_A_X (Alt-Ergo) (Cached) [wp] [Unsuccess] typed_formal_region_assert_A_Y (Alt-Ergo) (Cached) -[wp] Proved goals: 3 / 6 - Alt-Ergo: 3 - Unsuccess: 3 +[wp] Proved goals: 4 / 6 + Alt-Ergo: 4 + Unsuccess: 2 ------------------------------------------------------------ Functions WP Alt-Ergo Total Success - compound - 1 2 50.0% + compound - 2 2 100% local_region - 1 2 50.0% formal_region - 1 2 50.0% ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle index 8a24f1e423a4276d97d597a9ac1c3e7203a76bc6..76c6bfc124616648c6b1276948108368101252ff 100644 --- a/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle +++ b/src/plugins/wp/tests/wp_typed/oracle_qualif/user_init.1.res.oracle @@ -4,163 +4,559 @@ [wp] Warning: Missing RTE guards [wp] 23 goals scheduled [wp] [Valid] typed_init_t2_v2_loop_assigns_part1 (Qed) -[wp] [Valid] typed_init_t2_v2_loop_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached) -[wp] [Valid] typed_init_t2_v2_loop_assigns_part3 (Tactic) (Alt-Ergo 2/2) (Cached) +[wp] [Valid] typed_init_t2_v2_loop_assigns_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached) +[wp] [Valid] typed_init_t2_v2_loop_assigns_part3 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached) [wp] [Valid] typed_init_t2_v2_loop_assigns_2_part1 (Qed) -[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part2 (Tactic) (Alt-Ergo 2/2) (Cached) -[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part3 (Tactic) (Alt-Ergo 2/2) (Cached) +[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached) +[wp] [Valid] typed_init_t2_v2_loop_assigns_2_part3 (Tactics 3) (Qed 34/34) [wp] [Valid] typed_init_t2_v2_assigns_part1 (Qed) [wp] [Valid] typed_init_t2_v2_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached) [wp] [Valid] typed_init_t2_v3_loop_assigns_part1 (Qed) -[wp] [Valid] typed_init_t2_v3_loop_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached) -[wp] [Valid] typed_init_t2_v3_loop_assigns_part3 (Tactic) (Alt-Ergo 2/2) (Cached) +[wp] [Valid] typed_init_t2_v3_loop_assigns_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached) +[wp] [Valid] typed_init_t2_v3_loop_assigns_part3 (Tactics 3) (Qed 34/34) [wp] [Valid] typed_init_t2_v3_loop_assigns_2_part1 (Qed) [wp] [Valid] typed_init_t2_v3_loop_assigns_2_part2 (Qed) [wp] [Valid] typed_init_t2_v3_assigns_part1 (Qed) [wp] [Valid] typed_init_t2_v3_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached) [wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part1 (Qed) -[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part2 (Tactic) (Alt-Ergo 2/2) (Cached) -[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part3 (Tactic) (Alt-Ergo 2/2) (Cached) +[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached) +[wp] [Valid] typed_init_t2_bis_v2_loop_assigns_part3 (Tactics 2) (Qed 22/23) (Alt-Ergo 1/23) (Cached) [wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part1 (Qed) -[wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part2 (Tactic) (Alt-Ergo 2/2) (Cached) +[wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached) [wp] [Valid] typed_init_t2_bis_v2_assigns_exit_part3 (Qed) [wp] [Valid] typed_init_t2_bis_v2_assigns_normal_part1 (Qed) -[wp] [Valid] typed_init_t2_bis_v2_assigns_normal_part2 (Tactic) (Alt-Ergo 2/2) (Cached) +[wp] [Valid] typed_init_t2_bis_v2_assigns_normal_part2 (Tactics 2) (Qed 12/13) (Alt-Ergo 1/13) (Cached) [wp] Proved goals: 23 / 23 Qed: 11 - Script: 12 (Tactics 12) (Alt-Ergo 24/24) (Cached) + Script: 12 (Tactics 24) (Qed 174/186) (Alt-Ergo 12/186) (Cached) [wp] Proof script for typed_init_t2_bis_v2_assigns_normal_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_138) /\\ (i_1<=i_139) /\\ (0<=i_0) /\\ (i_138<=i_0) /\\ (i_139<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0088, - "steps": 24 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0116, - "steps": 24 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.3801, + "steps": 1028 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_138", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_bis_v2_assigns_exit_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_138) /\\ (i_1<=i_139) /\\ (0<=i_0) /\\ (i_138<=i_0) /\\ (i_139<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0088, - "steps": 24 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0116, - "steps": 24 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.3801, + "steps": 1028 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_138", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_bis_v2_loop_assigns_part3: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_2:int.\n(i_0<=i_1) /\\ (i_2<=i_3) /\\ (0<=i_0) /\\ (i_1<=i_0) /\\ (i_3<=i_2) /\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0074, - "steps": 31 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0078, - "steps": 31 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 19 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_3", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 10": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 11": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 12": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 13": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 14": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 15": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 16": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 17": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 18": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 19": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 19": [ { "prover": "qed", + "verdict": "valid" } ] } } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 7.1853, + "steps": 25331 } ] } } ] [wp] Proof script for typed_init_t2_bis_v2_loop_assigns_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_9) /\\ (i_1<=i_10) /\\ (0<=i_0) /\\ (i_9<=i_0) /\\ (i_10<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0124, - "steps": 43 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0121, - "steps": 43 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 7.5676, + "steps": 26376 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_9", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_v3_assigns_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_149) /\\ (i_1<=i_150) /\\ (0<=i_0) /\\ (i_149<=i_0) /\\ (i_150<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.011, - "steps": 16 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0092, - "steps": 16 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0835, + "steps": 193 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 1.8111, + "steps": 5702 } ] } } ] [wp] Proof script for typed_init_t2_v3_loop_assigns_part3: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_4) /\\ (i_1<=i_6) /\\ (0<=i_0) /\\ (i_4<=i_0) /\\ (i_6<=i_1) /\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0169, - "steps": 33 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0081, - "steps": 33 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 19 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_6", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 10": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 11": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 12": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 13": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 14": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 15": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 16": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 17": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 18": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 19": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 19": [ { "prover": "qed", + "verdict": "valid" } ] } } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_4", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_v3_loop_assigns_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_13) /\\ (i_1<=i_14) /\\ (0<=i_0) /\\ (i_13<=i_0) /\\ (i_14<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0139, - "steps": 45 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0127, - "steps": 45 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 1.3179, + "steps": 3085 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_13", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_v2_assigns_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_158) /\\ (i_1<=i_159) /\\ (0<=i_0) /\\ (i_158<=i_0) /\\ (i_159<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.011, - "steps": 16 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0092, - "steps": 16 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 0.0835, + "steps": 193 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 1.8111, + "steps": 5702 } ] } } ] [wp] Proof script for typed_init_t2_v2_loop_assigns_2_part3: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_2:int.\n(i_0<=i_1) /\\ (0<=i_0) /\\ (i_1<=i_0) /\\ (j_1<=i_2) /\\ (i_2<=j_1) /\\ (i_0<=9)", "pattern": "\\E$i0$i$j$j9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0094, - "steps": 26 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0101, - "steps": 26 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 19 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "j_1", + "pattern": "$j" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 10": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 11": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 12": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 13": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 14": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 15": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 16": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 17": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 18": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 19": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 19": [ { "prover": "qed", + "verdict": "valid" } ] } } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_1", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_v2_loop_assigns_2_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_13) /\\ (i_1<=i_14) /\\ (0<=i_0) /\\ (i_13<=i_0) /\\ (i_14<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0099, - "steps": 42 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0124, - "steps": 42 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 1.9461, + "steps": 3681 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_13", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_v2_loop_assigns_part3: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_8) /\\ (i_1<=i_9) /\\ (0<=i_0) /\\ (i_8<=i_0) /\\ (i_9<=i_1) /\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0098, - "steps": 35 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0048, - "steps": 35 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 1.2688, + "steps": 2727 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_8", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Proof script for typed_init_t2_v2_loop_assigns_part2: [ { "header": "Split", "tactic": "Wp.split", "params": {}, "select": { "select": "clause-goal", "target": "exists i_0,i_1:int.\n(i_0<=i_21) /\\ (i_1<=i_22) /\\ (0<=i_0) /\\ (i_21<=i_0) /\\ (i_22<=i_1)\n/\\ (i_0<=9)", "pattern": "\\E$i$i0$i$i9" }, - "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0098, - "steps": 35 } ], - "Goal 2/2": [ { "prover": "Alt-Ergo:2.2.0", - "verdict": "valid", "time": 0.0048, - "steps": 35 } ] } } ] + "children": { "Goal 1/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "valid", "time": 1.2688, + "steps": 2727 } ], + "Goal 2/2": [ { "prover": "Alt-Ergo:2.4.2", + "verdict": "timeout", "time": 10. }, + { "header": "Range", "tactic": "Wp.range", + "params": { "inf": 0, "sup": 9 }, + "select": { "select": "inside-goal", + "occur": 0, "target": "i_21", + "pattern": "$i" }, + "children": { "Lower 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 0": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 1": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 2": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 3": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 4": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 5": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 6": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 7": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 8": [ { "prover": "qed", + "verdict": "valid" } ], + "Value 9": [ { "prover": "qed", + "verdict": "valid" } ], + "Upper 9": [ { "prover": "qed", + "verdict": "valid" } ] } } ] } } ] [wp] Updated session - 12 new valid scripts ------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_usage/oracle/switch.0.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/switch.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..0d25c225e9b863ac6bc3eddcbc36f2d340d2b695 --- /dev/null +++ b/src/plugins/wp/tests/wp_usage/oracle/switch.0.res.oracle @@ -0,0 +1,37 @@ +# frama-c -wp [...] +[kernel] Parsing switch.i (no preprocessing) +[kernel] switch.i:10: Warning: + parsing obsolete ACSL construct 'logic declaration'. 'an axiomatic block' should be used instead. +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +------------------------------------------------------------ + Function f +------------------------------------------------------------ + +Goal Post-condition (file switch.i, line 12) in 'f' (1/3): +Tags: Default. +Assume { + Type: is_sint32(x). + (* Default *) + Have: (x != 0) /\ (x != 1) /\ (x != 2) /\ (x != 3). +} +Prove: P_P(30). + +------------------------------------------------------------ + +Goal Post-condition (file switch.i, line 12) in 'f' (2/3): +Tags: Case 3. +Prove: P_P(20). + +------------------------------------------------------------ + +Goal Post-condition (file switch.i, line 12) in 'f' (3/3): +Tags: Cases 0,1,2. +Assume { + Type: is_sint32(x). + (* Cases 0,1,2 *) + Have: (x = 0) \/ (x = 1) \/ (x = 2). +} +Prove: P_P(10). + +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_usage/oracle/switch.1.res.oracle b/src/plugins/wp/tests/wp_usage/oracle/switch.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..05401cb7de08cd90b0fe752ea130d2109f25e1c2 --- /dev/null +++ b/src/plugins/wp/tests/wp_usage/oracle/switch.1.res.oracle @@ -0,0 +1,29 @@ +# frama-c -wp [...] +[kernel] Parsing switch.i (no preprocessing) +[kernel] switch.i:10: Warning: + parsing obsolete ACSL construct 'logic declaration'. 'an axiomatic block' should be used instead. +[wp] Running WP plugin... +[wp] Warning: Missing RTE guards +------------------------------------------------------------ + Function f +------------------------------------------------------------ + +Goal Post-condition (file switch.i, line 12) in 'f': +Assume { + Type: is_sint32(f) /\ is_sint32(x). + (* Merge *) + Either { + Case: + (* Cases 0,1,2 *) + Have: (x = 0) \/ (x = 1) \/ (x = 2). + Have: f = 10. + Case: (* Case 3 *) Have: x = 3. Have: f = 20. + Case: + (* Default *) + Have: (x != 0) /\ (x != 1) /\ (x != 2) /\ (x != 3). + Have: f = 30. + } +} +Prove: P_P(f). + +------------------------------------------------------------ diff --git a/src/plugins/wp/tests/wp_usage/switch.i b/src/plugins/wp/tests/wp_usage/switch.i new file mode 100644 index 0000000000000000000000000000000000000000..5dd6ae4b6171f91633e793c636099a8582ed25f0 --- /dev/null +++ b/src/plugins/wp/tests/wp_usage/switch.i @@ -0,0 +1,24 @@ +/* run.config + OPT: + OPT: -wp-no-split-switch +*/ + +/* run.config_qualif + DONTRUN: +*/ + +//@ predicate P(integer v); + +/*@ ensures P(\result); */ +int f(int x) { + switch(x) { + case 0: + case 1: + case 2: + return 10; + case 3: + return 20; + default: + return 30; + } +} diff --git a/src/plugins/wp/wp.ml b/src/plugins/wp/wp.ml index fee701a4e93cb711c41f82ebaba10288d38bcfe2..4b5e2dffbd611dc4f6e0afe23ffb03d873d662b2 100644 --- a/src/plugins/wp/wp.ml +++ b/src/plugins/wp/wp.ml @@ -190,6 +190,7 @@ module ProofScript = ProofScript module ProverScript = ProverScript module ProverSearch = ProverSearch module ProofSession = ProofSession +module ProofStrategy = ProofStrategy (** {2 Tactics} *) @@ -217,6 +218,7 @@ module TacSequence = TacSequence module TacShift = TacShift module TacSplit = TacSplit module TacUnfold = TacUnfold +module TacCompute = TacCompute (** {2 Error Management} *) diff --git a/src/plugins/wp/wpContext.ml b/src/plugins/wp/wpContext.ml index 1adc3cfd70d17731f5f4d2198cca1b046abaf920..238d6c163ac643dac8ed5d664298ac9d988eb6c0 100644 --- a/src/plugins/wp/wpContext.ml +++ b/src/plugins/wp/wpContext.ml @@ -490,10 +490,11 @@ module type Generator = sig type key type data - val get : key -> data val mem : key -> bool - val clear : unit -> unit + val get : key -> data + val set : key -> data -> unit val remove : key -> unit + val clear : unit -> unit end module StaticGenerator(K : Key)(D : Data with type key = K.t) = @@ -508,6 +509,7 @@ struct type key = D.key type data = D.data let get = G.memoize D.compile + let set = G.update let mem = G.mem let clear = G.clear let remove = G.remove @@ -525,6 +527,7 @@ struct type key = D.key type data = D.data let get = G.memoize D.compile + let set = G.update let mem = G.mem let clear = G.clear let remove = G.remove @@ -542,6 +545,7 @@ struct type key = D.key type data = D.data let get = G.memoize (fun k -> D.compile k (G.id ~basename:(D.basename k) k)) + let set = G.update let mem = G.mem let clear = G.clear let remove = G.remove @@ -559,6 +563,7 @@ struct type key = D.key type data = D.data let get = G.memoize (fun k -> D.compile k (G.id ~basename:(D.basename k) k)) + let set = G.update let mem = G.mem let clear = G.clear let remove = G.remove diff --git a/src/plugins/wp/wpContext.mli b/src/plugins/wp/wpContext.mli index 17a3273679d240ac7e24c53eb9716cae712378a6..9f6be07073a925679b0ca1e7c1a162a899d9544d 100644 --- a/src/plugins/wp/wpContext.mli +++ b/src/plugins/wp/wpContext.mli @@ -112,7 +112,7 @@ sig val clear : unit -> unit val remove : key -> unit val define : key -> data -> unit - (** no redefinition ; circularity protected *) + (** no redefinition unless forced ; circularity protected *) val update : key -> data -> unit (** set current value, with no protection *) @@ -163,10 +163,11 @@ module type Generator = sig type key type data - val get : key -> data val mem : key -> bool - val clear : unit -> unit + val get : key -> data + val set : key -> data -> unit val remove : key -> unit + val clear : unit -> unit end (** projectified, depend on the model, not serialized *) diff --git a/src/plugins/wp/wpPropId.ml b/src/plugins/wp/wpPropId.ml index 1ca08f3e221fdd78b5be9f44997876149eed18e8..3632d8514dd634e86021c748e118798b24219317 100644 --- a/src/plugins/wp/wpPropId.ml +++ b/src/plugins/wp/wpPropId.ml @@ -746,7 +746,10 @@ let user_prop_pid pid = let p_prop = match pid.p_kind with | PKPre (_,_,p_prop) -> p_prop | _ -> property_of_id pid in - user_prop_names p_prop + let names = user_prop_names p_prop in + match Property.get_kf p_prop with + | None -> names + | Some kf -> Kernel_function.get_name kf :: names let select_default pid = let names = user_prop_pid pid in diff --git a/src/plugins/wp/wpReached.ml b/src/plugins/wp/wpReached.ml index d797a9f04791cd8b3ef40aad0317cdd56748a260..0193f2e46302df193b6845b86662edd7be889299 100644 --- a/src/plugins/wp/wpReached.ml +++ b/src/plugins/wp/wpReached.ml @@ -211,9 +211,9 @@ let rec protected node = and protected_by prev = match prev.flow with - | F_dead | F_entry | F_effect -> true + | F_return | F_dead | F_entry | F_effect -> true | F_goto -> protected prev - | F_call | F_branch | F_return -> unreachable prev + | F_call | F_branch -> unreachable prev let smoking_node n = match n.flow with diff --git a/src/plugins/wp/wpTacApi.ml b/src/plugins/wp/wpTacApi.ml index 97e5c4d33bf2542e555259a6d8e032979549163c..8aec7bffc6a821cfcd523ab067e4bc09417a9c80 100644 --- a/src/plugins/wp/wpTacApi.ml +++ b/src/plugins/wp/wpTacApi.ml @@ -402,7 +402,7 @@ class configurator (tactic : Tactical.tactical) = method private commit tree node process = try - let jtactic = ProofScript.jtactic ~title tactic target in + let jtactic = ProofScript.jtactic tactic target in let fork = ProofEngine.fork tree ~anchor:node jtactic process in let children = snd @@ ProofEngine.commit fork in List.map snd children diff --git a/src/plugins/wp/wp_parameters.ml b/src/plugins/wp/wp_parameters.ml index 23ff0dda57c622e47b57170e242faee62c225069..7a37701948b3aed89218fd9b2d1433c3b81b6453 100644 --- a/src/plugins/wp/wp_parameters.ml +++ b/src/plugins/wp/wp_parameters.ml @@ -440,30 +440,34 @@ module SmokeDeadloop = end) let () = Parameter_customize.set_group wp_strategy -module Split = +module SplitBranch = False(struct let option_name = "-wp-split" - let help = "Split conjunctions into sub-goals." + let help = "Split if-then-else into sub-goals (see also -wp-max-split)" end) let () = Parameter_customize.set_group wp_strategy -module UnfoldAssigns = - Int(struct - let option_name = "-wp-unfold-assigns" - let default = 0 - let arg_name = "n" - let help = "Unfold up to <n> levels of aggregates and arrays in assigns.\n\ - Value -1 means unlimited depth (default 0)" +module SplitSwitch = + True(struct + let option_name = "-wp-split-switch" + let help = "Split switch-cases into sub-goals (see also -wp-max-split)." + end) + +let () = Parameter_customize.set_group wp_strategy +module SplitConj = + False(struct + let option_name = "-wp-split-conj" + let help = "Split conjunctive goals into sub-goals" end) let () = Parameter_customize.set_group wp_strategy -module SplitDepth = +module SplitCNF = Int(struct - let option_name = "-wp-split-depth" + let option_name = "-wp-split-cnf" let default = 0 - let arg_name = "p" - let help = "Set depth for splitting conjunctions into sub-goals.\n\ - Value -1 means unlimited depth (default 0)" + let arg_name = "N" + let help = + "Apply CNF transformation on goals at depth N (default 0, -1 unlimited)" end) let () = Parameter_customize.set_group wp_strategy @@ -475,6 +479,16 @@ module SplitMax = let help = "Set maximum number of splitted sub-goals (default 1000)" end) +let () = Parameter_customize.set_group wp_strategy +module UnfoldAssigns = + Int(struct + let option_name = "-wp-unfold-assigns" + let default = 0 + let arg_name = "n" + let help = "Unfold up to <n> levels of aggregates and arrays in assigns.\n\ + Value -1 means unlimited depth (default 0)" + end) + let () = Parameter_customize.set_group wp_strategy let () = Parameter_customize.is_invisible () module DynCall = @@ -694,13 +708,43 @@ module Interactive = String let help = "WP mode for interactive Why-3 provers (eg: Coq):\n\ - 'batch': check current proof (default)\n\ - - 'update': update and check proof\n\ - - 'edit': edit proof before check\n\ - - 'fix': check and edit proof if necessary\n\ - - 'fixup': update proof and fix\n\ + - 'update': check updated proof\n\ + - 'edit': edit current proof\n\ + - 'fix': check current proof and edit if needed\n\ + - 'fixup': update proof, check it and edit if needed\n\ " end) +let () = Parameter_customize.set_group wp_prover +module ScriptMode = String + (struct + let option_name = "-wp-script" + let arg_name = "mode" + let default = "" + let help = + "WP mode for managing scripts and proof strategies:\n\ + - 'batch': proof scripts are reused but not updated (default for script prover)\n\ + - 'update': proof scripts are reused and updated (default for tip prover)\n\ + - 'init': proof scripts are generated from scratch and saved\n\ + - 'dry': proof scripts are explored from scratch and not saved\n\ + See also option -wp-cache-env." + end) + +let () = Parameter_customize.set_group wp_prover +module StrategyEngine = True + (struct + let option_name = "-wp-strategy-engine" + let help = "Activate @strategy and @proof annotations. (default: yes)" + end) + +let () = Parameter_customize.set_group wp_prover +module DefaultStrategies = String_list + (struct + let option_name = "-wp-strategy" + let arg_name = "s,..." + let help = "Use the specified strategies as default." + end) + let () = Parameter_customize.set_group wp_prover module RunAllProvers = False(struct @@ -723,18 +767,7 @@ module Cache = String - 'replay': update mode with no cache update\n\ - 'rebuild': always run provers and update cache\n\ - 'offline': use cache but never run provers\n\ - You can also use the environment variable FRAMAC_WP_CACHE instead." - end) - -let () = Parameter_customize.set_group wp_prover -module CacheEnv = False - (struct - let option_name = "-wp-cache-env" - let help = "Gives environment variables precedence over command line\n\ - for cache management:\n\ - - FRAMAC_WP_CACHE overrides -wp-cache\n\ - - FRAMAC_WP_CACHEDIR overrides -wp-cache-dir\n\ - Disabled by default." + See also option -wp-cache-env." end) let () = Parameter_customize.set_group wp_prover @@ -746,7 +779,19 @@ module CacheDir = String let help = "Specify global cache directory (no cleanup mode).\n\ By default, cache entries are stored in the WP session directory.\n\ - You can also use the environment variable FRAMAC_WP_CACHEDIR instead." + See also option -wp-cache-env." + end) + +let () = Parameter_customize.set_group wp_prover +module CacheEnv = False + (struct + let option_name = "-wp-cache-env" + let help = "Gives environment variables precedence over command line\n\ + for cache management:\n\ + - FRAMAC_WP_SCRIPT overrides -wp-script\n\ + - FRAMAC_WP_CACHE overrides -wp-cache\n\ + - FRAMAC_WP_CACHEDIR overrides -wp-cache-dir\n\ + Disabled by default." end) let () = Parameter_customize.set_group wp_prover @@ -805,6 +850,14 @@ module Detect = Action end) let () = on_reset Detect.clear +module Tactics = String_list + (struct + let option_name = "-wp-tactic" + let arg_name = "id,..." + let help = "Describe tactic. Use '?' for listing tactic names." + end) +let () = on_reset Tactics.clear + let () = Parameter_customize.set_group wp_prover module Drivers = String_list @@ -827,7 +880,7 @@ let () = Parameter_customize.set_group wp_prover module Timeout = Int(struct let option_name = "-wp-timeout" - let default = 10 + let default = 2 let arg_name = "n" let help = Printf.sprintf @@ -1022,6 +1075,15 @@ module Print = end) let () = on_reset Print.clear +let () = Parameter_customize.set_group wp_po +let () = Parameter_customize.do_not_save () +module Status = + Action(struct + let option_name = "-wp-status" + let help = "Pretty-prints pending proof obligations on standard output." + end) +let () = on_reset Print.clear + let () = Parameter_customize.set_group wp_po let () = Parameter_customize.do_not_save () module Report = diff --git a/src/plugins/wp/wp_parameters.mli b/src/plugins/wp/wp_parameters.mli index 786bf2d170668267ba39a507a078806ac18793de..53d15e5b02311f7fd22328e247729ded1359ba4b 100644 --- a/src/plugins/wp/wp_parameters.mli +++ b/src/plugins/wp/wp_parameters.mli @@ -92,9 +92,11 @@ module Ground: Parameter_sig.Bool module Reduce: Parameter_sig.Bool module ExtEqual : Parameter_sig.Bool module UnfoldAssigns : Parameter_sig.Int -module Split: Parameter_sig.Bool +module SplitBranch: Parameter_sig.Bool +module SplitSwitch: Parameter_sig.Bool module SplitMax: Parameter_sig.Int -module SplitDepth: Parameter_sig.Int +module SplitConj: Parameter_sig.Bool +module SplitCNF: Parameter_sig.Int module DynCall : Parameter_sig.Bool module SimplifyIsCint : Parameter_sig.Bool module SimplifyLandMask : Parameter_sig.Bool @@ -110,6 +112,7 @@ module TerminatesVariantHyp : Parameter_sig.Bool (** {2 Prover Interface} *) module Detect: Parameter_sig.Bool +module Tactics: Parameter_sig.String_list module Generate:Parameter_sig.Bool module ScriptOnStdout: Parameter_sig.Bool module PrepareScripts: Parameter_sig.Bool @@ -117,6 +120,9 @@ module FinalizeScripts: Parameter_sig.Bool module DryFinalizeScripts: Parameter_sig.Bool module Provers: Parameter_sig.String_list module Interactive: Parameter_sig.String +module StrategyEngine: Parameter_sig.Bool +module ScriptMode: Parameter_sig.String +module DefaultStrategies: Parameter_sig.String_list module RunAllProvers: Parameter_sig.Bool module Cache: Parameter_sig.String module CacheEnv: Parameter_sig.Bool @@ -147,6 +153,7 @@ module BackTrack: Parameter_sig.Int module TruncPropIdFileName: Parameter_sig.Int module Print: Parameter_sig.Bool +module Status: Parameter_sig.Bool module Report: Parameter_sig.String_list module ReportJson: Parameter_sig.String module OldReportJson: Parameter_sig.String diff --git a/src/plugins/wp/wpo.ml b/src/plugins/wp/wpo.ml index e318b87601001b8bd67417fdfde5264bedee2177..f8e1321feabd05400a7f3e2702e21c512798a50e 100644 --- a/src/plugins/wp/wpo.ml +++ b/src/plugins/wp/wpo.ml @@ -886,6 +886,10 @@ let pp_goal_model fmt w = let pp_goal fmt w = WpContext.on_context (get_context w) (pp_goal_model fmt) w +let pp_flow fmt = + Format.fprintf fmt "@\n%s@\n" bar ; + flow := false + let pp_goal_flow fmt g = begin if not !flow then Format.pp_print_newline fmt () ; diff --git a/src/plugins/wp/wpo.mli b/src/plugins/wp/wpo.mli index 7d62470252ee947250b1cc6eadb08670dfd1e5b6..ee373c54bc5b31e28efe1ba346ecc5fd6d3f5652 100644 --- a/src/plugins/wp/wpo.mli +++ b/src/plugins/wp/wpo.mli @@ -234,6 +234,7 @@ val pp_logfile : Format.formatter -> t -> prover -> unit val pp_axiomatics : Format.formatter -> string option -> unit val pp_function : Format.formatter -> Kernel_function.t -> string option -> unit val pp_goal_flow : Format.formatter -> t -> unit +val pp_flow : Format.formatter -> unit (* -------------------------------------------------------------------------- *) (* --- Generators --- *) diff --git a/tests/builtins/oracle/free.res.oracle b/tests/builtins/oracle/free.res.oracle index 1f95b2c0061d6e8413677644bcc0482f456e261e..4f5cb6ae56f07cb9ca6b0984d705f3d7a0d5965f 100644 --- a/tests/builtins/oracle/free.res.oracle +++ b/tests/builtins/oracle/free.res.oracle @@ -15,7 +15,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/linked_list.0.res.oracle b/tests/builtins/oracle/linked_list.0.res.oracle index c7cf1e9421823e655895d76109504721949c758a..61083435b7ad0833144f3dac32cd6b0b7545b794 100644 --- a/tests/builtins/oracle/linked_list.0.res.oracle +++ b/tests/builtins/oracle/linked_list.0.res.oracle @@ -15,12 +15,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -58,12 +58,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -97,12 +97,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -139,12 +139,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -180,12 +180,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -225,12 +225,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -268,12 +268,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -315,12 +315,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -360,12 +360,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -409,12 +409,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -456,12 +456,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -507,12 +507,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -800,12 +800,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -1095,12 +1095,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -1386,12 +1386,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -1681,12 +1681,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -1973,12 +1973,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -2269,12 +2269,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..2047] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/linked_list.1.res.oracle b/tests/builtins/oracle/linked_list.1.res.oracle index a6456f3e810b6a38cf5d9ac6b270397aa8ae9bde..ab1cd53fb4aa9ca57158e091604b734523bed717 100644 --- a/tests/builtins/oracle/linked_list.1.res.oracle +++ b/tests/builtins/oracle/linked_list.1.res.oracle @@ -15,12 +15,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -58,12 +58,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -97,12 +97,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -139,12 +139,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -180,12 +180,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -225,12 +225,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -268,12 +268,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -315,12 +315,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -360,12 +360,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -409,12 +409,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -457,12 +457,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -509,12 +509,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -556,12 +556,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -601,12 +601,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -642,12 +642,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -687,12 +687,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -731,12 +731,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -775,12 +775,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/linked_list.2.res.oracle b/tests/builtins/oracle/linked_list.2.res.oracle index 43dbed7de1ea30104b2d1febee8b01851ac22549..72eef5ce30bbac814bab7dad0c7a5340e4d6d28d 100644 --- a/tests/builtins/oracle/linked_list.2.res.oracle +++ b/tests/builtins/oracle/linked_list.2.res.oracle @@ -15,12 +15,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -58,12 +58,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -96,12 +96,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -138,12 +138,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -179,12 +179,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -224,12 +224,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -267,12 +267,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -314,12 +314,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -359,12 +359,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -408,12 +408,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -455,12 +455,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -506,12 +506,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -555,12 +555,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -608,12 +608,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -659,12 +659,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -714,12 +714,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -767,12 +767,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -824,12 +824,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -879,12 +879,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -938,12 +938,12 @@ __fc_stdout ∈ {{ &__fc_initial_stdout }} __fc_fopen[0..15] ∈ {0} __fc_p_fopen ∈ {{ &__fc_fopen[0] }} - __fc_tmpnam[0..0x7FF] ∈ {0} + __fc_tmpnam[0..19] ∈ {0} __fc_p_tmpnam ∈ {{ &__fc_tmpnam[0] }} __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {0x7FFF} + __fc_rand_max ∈ {0x7FFFFFFF} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/malloc-size-zero.0.res.oracle b/tests/builtins/oracle/malloc-size-zero.0.res.oracle index 144bf5624b341f5494df694a89dce00eaa23c34e..1b725ab6061ad2238e62ba1eff947b2aa979b398 100644 --- a/tests/builtins/oracle/malloc-size-zero.0.res.oracle +++ b/tests/builtins/oracle/malloc-size-zero.0.res.oracle @@ -50,7 +50,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/malloc-size-zero.1.res.oracle b/tests/builtins/oracle/malloc-size-zero.1.res.oracle index 79f6728188cf3d82355fdece2946fce400f57dac..511d5f834c36fd9081ee2e2bd86866fcb38c10d5 100644 --- a/tests/builtins/oracle/malloc-size-zero.1.res.oracle +++ b/tests/builtins/oracle/malloc-size-zero.1.res.oracle @@ -32,7 +32,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/realloc.res.oracle b/tests/builtins/oracle/realloc.res.oracle index 3441c23c27b3a9e7b8c34e0d64ae935f31a6a3cb..df107558a522d428e7c910802a4affbe07f80eb3 100644 --- a/tests/builtins/oracle/realloc.res.oracle +++ b/tests/builtins/oracle/realloc.res.oracle @@ -13,7 +13,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -41,7 +41,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -87,7 +87,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -129,7 +129,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -161,7 +161,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -226,7 +226,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -280,7 +280,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -342,7 +342,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -371,7 +371,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -436,7 +436,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -463,7 +463,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -501,7 +501,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -538,7 +538,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -576,7 +576,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -606,7 +606,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/realloc_multiple.0.res.oracle b/tests/builtins/oracle/realloc_multiple.0.res.oracle index 90a945812a66a13ef7723e9c41c1291ebedb8c47..5908db2b9e507a91de87ff057e31832be7b548e8 100644 --- a/tests/builtins/oracle/realloc_multiple.0.res.oracle +++ b/tests/builtins/oracle/realloc_multiple.0.res.oracle @@ -21,7 +21,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -56,7 +56,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -105,7 +105,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -142,7 +142,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -196,7 +196,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -238,7 +238,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -280,7 +280,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/realloc_multiple.1.res.oracle b/tests/builtins/oracle/realloc_multiple.1.res.oracle index 831c3434213e54c9259aee81a7a24548c3d49be5..052f0f273fa2a1f63c42e4ef5be7fa27b6c5d044 100644 --- a/tests/builtins/oracle/realloc_multiple.1.res.oracle +++ b/tests/builtins/oracle/realloc_multiple.1.res.oracle @@ -29,7 +29,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -64,7 +64,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -95,7 +95,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -150,7 +150,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -187,7 +187,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -222,7 +222,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -280,7 +280,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -326,7 +326,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -368,7 +368,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle/strnlen.res.oracle b/tests/builtins/oracle/strnlen.res.oracle index 0853c554d1693daa487e1b60d57214326cceee9a..06fce1695a9043d52dd273ac7e84a54f3d19a130 100644 --- a/tests/builtins/oracle/strnlen.res.oracle +++ b/tests/builtins/oracle/strnlen.res.oracle @@ -37,7 +37,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/builtins/oracle_gauges/realloc.res.oracle b/tests/builtins/oracle_gauges/realloc.res.oracle index 05fc14b03b3cfda3926bac350cbafeacaa044e5e..7db5bb2855581132216cb4aff783b868c8fd005b 100644 --- a/tests/builtins/oracle_gauges/realloc.res.oracle +++ b/tests/builtins/oracle_gauges/realloc.res.oracle @@ -8,7 +8,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -36,7 +36,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -64,7 +64,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -92,7 +92,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -120,7 +120,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -148,7 +148,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -176,7 +176,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -204,7 +204,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -232,7 +232,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -261,7 +261,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -289,7 +289,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -317,7 +317,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/float/oracle/const1.res.oracle b/tests/float/oracle/const1.res.oracle index a843cb7cf3b3001cd1594f0f21aa7148c4b6b5d4..8fbb1ef225d90d95581c0e8b293af2795ff5da08 100644 --- a/tests/float/oracle/const1.res.oracle +++ b/tests/float/oracle/const1.res.oracle @@ -5,7 +5,7 @@ [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva:alarm] const1.i:1: Warning: - non-finite float value. assert \is_finite((float)1e40f); + non-finite float value. assert \is_finite(1e40f); [eva] const1.i:1: Warning: evaluation of initializer '(unsigned long long)1e40f' failed [eva] Initial state computed diff --git a/tests/float/oracle/const2.res.oracle b/tests/float/oracle/const2.res.oracle index 94744b2de338fad025efb90e4b9908e02488725a..8dd6596c994a7f134c54f94a632b43f205e9c061 100644 --- a/tests/float/oracle/const2.res.oracle +++ b/tests/float/oracle/const2.res.oracle @@ -5,7 +5,7 @@ [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva:alarm] const2.i:2: Warning: - non-finite float value. assert \is_finite((float)1e40f); + non-finite float value. assert \is_finite(1e40f); [eva] const2.i:2: Warning: evaluation of initializer '1e40f' failed [eva] Initial state computed [eva:initial-state] Values of globals at initialization diff --git a/tests/float/oracle/const4.0.res.oracle b/tests/float/oracle/const4.0.res.oracle index fa336743685bb9299c681af68b70f7df506c97d1..6582b5a74178ba39ffb450f0d02a75fb248d2a60 100644 --- a/tests/float/oracle/const4.0.res.oracle +++ b/tests/float/oracle/const4.0.res.oracle @@ -6,7 +6,7 @@ [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva:alarm] const4.i:7: Warning: - non-finite float value. assert \is_finite((float)3.405e38f); + non-finite float value. assert \is_finite(3.405e38f); [eva] const4.i:7: Warning: evaluation of initializer '(double)3.405e38f' failed [eva] Initial state computed [eva:initial-state] Values of globals at initialization diff --git a/tests/float/oracle/const4.1.res.oracle b/tests/float/oracle/const4.1.res.oracle index 85a2c33e173e9932409b5cc8a4778d10b568ec68..8854b8b2448d6cd9fd7ec98ede98a3d0cbabde8b 100644 --- a/tests/float/oracle/const4.1.res.oracle +++ b/tests/float/oracle/const4.1.res.oracle @@ -8,7 +8,7 @@ [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva:alarm] const4.i:7: Warning: - non-finite float value. assert \is_finite((float)3.405e38f); + non-finite float value. assert \is_finite(3.405e38f); [eva] Initial state computed [eva:initial-state] Values of globals at initialization f1 ∈ [3.39999995214e+38 .. 3.40000015497e+38] diff --git a/tests/float/oracle/cte_overflow.res.oracle b/tests/float/oracle/cte_overflow.res.oracle index 50328773570d84b2cc7982447936bb3466e625f3..d7287cf5d95221001a911e1a0f56f073a9be7f31 100644 --- a/tests/float/oracle/cte_overflow.res.oracle +++ b/tests/float/oracle/cte_overflow.res.oracle @@ -15,7 +15,7 @@ [eva:alarm] cte_overflow.i:12: Warning: non-finite double value. assert \is_finite((double)1e500); [eva:alarm] cte_overflow.i:17: Warning: - non-finite float value. assert \is_finite((float)1e80f); + non-finite float value. assert \is_finite(1e80f); [eva] Recording results for main [eva] done for function main [eva] cte_overflow.i:12: diff --git a/tests/float/oracle/parse.res.oracle b/tests/float/oracle/parse.res.oracle index f9c65e85c126e12b56abc0f52d25d2027bd2b99e..57d0b1b1bce9064e56bc30a472ca0c93a691c1fd 100644 --- a/tests/float/oracle/parse.res.oracle +++ b/tests/float/oracle/parse.res.oracle @@ -18,7 +18,7 @@ [eva] parse.i:36: Warning: cannot parse floating-point constant, returning imprecise result [eva:alarm] parse.i:36: Warning: - non-finite long double value. assert \is_finite((long double)0x1p32767L); + non-finite long double value. assert \is_finite(0x1p32767L); [eva:alarm] parse.i:37: Warning: non-finite long double value. assert \is_finite(l); [eva:alarm] parse.i:37: Warning: diff --git a/tests/idct/oracle/ieee_1180_1990.res.oracle b/tests/idct/oracle/ieee_1180_1990.res.oracle index 2b84b5e6d38b4bc9695b2eac24820d8a7b12bfde..76dc3eb09e9db269d984133d66acb38c400de4a7 100644 --- a/tests/idct/oracle/ieee_1180_1990.res.oracle +++ b/tests/idct/oracle/ieee_1180_1990.res.oracle @@ -1136,16 +1136,15 @@ \result ≡ __fc_p_tmpnam Unverifiable but considered Valid. [ Extern ] Assigns (file FRAMAC_SHARE/libc/stdio.h, line 109) - assigns *(__fc_p_tmpnam + (0 .. 2048)), *(s + (0 .. 2048)), - \result; + assigns *(__fc_p_tmpnam + (0 .. 20)), *(s + (0 .. 20)), \result; Unverifiable but considered Valid. [ Extern ] Froms (file FRAMAC_SHARE/libc/stdio.h, line 109) - assigns *(__fc_p_tmpnam + (0 .. 2048)) - \from *(__fc_p_tmpnam + (0 .. 2048)), (indirect: s); + assigns *(__fc_p_tmpnam + (0 .. 20)) + \from *(__fc_p_tmpnam + (0 .. 20)), (indirect: s); Unverifiable but considered Valid. [ Extern ] Froms (file FRAMAC_SHARE/libc/stdio.h, line 111) - assigns *(s + (0 .. 2048)) - \from (indirect: s), *(__fc_p_tmpnam + (0 .. 2048)); + assigns *(s + (0 .. 20)) + \from (indirect: s), *(__fc_p_tmpnam + (0 .. 20)); Unverifiable but considered Valid. [ Extern ] Froms (file FRAMAC_SHARE/libc/stdio.h, line 112) assigns \result \from s, __fc_p_tmpnam; @@ -1426,7 +1425,7 @@ [ Extern ] Post-condition 'result_uchar_or_eof' ensures - result_uchar_or_eof: (0 ≤ \result ≤ 255) ∨ \result ≡ -1 + result_uchar_or_eof: (0 ≤ \result ≤ 255U) ∨ \result ≡ -1 Unverifiable but considered Valid. [ Extern ] Assigns (file FRAMAC_SHARE/libc/stdio.h, line 261) assigns *stream, \result; diff --git a/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle b/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle index 51a1a894ad988e333fa9e44015a7e7498df8a2d8..47aa5d3e5dd20d6f1977724377123cb11af05543 100644 --- a/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle +++ b/tests/idct/oracle_multidim/ieee_1180_1990.res.oracle @@ -265,7 +265,7 @@ < "output.\n"[bits 0 to 71] --- > idct_init; idct_mc1[0..7][0..7]; idct_mc2[0..7][0..7] -3910,3932d3744 +3909,3931d3743 < [ - ] Assertion 'Eva,initialization' (file idct.c, line 129) < assert Eva: initialization: \initialized(&tmp1[i][j]); < tried with Eva. @@ -289,7 +289,7 @@ < assert Eva: initialization: \initialized(&tmp1[i][j]); < By RedundantAlarms, with pending: < - Assertion 'Eva,initialization' (file idct.c, line 145) -3936,3958d3747 +3935,3957d3746 < [ - ] Assertion 'Eva,initialization' (file idct.c, line 163) < assert Eva: initialization: \initialized(&tmp1[i][j]); < tried with Eva. @@ -313,11 +313,11 @@ < assert Eva: initialization: \initialized(&tmp1[i][j]); < By RedundantAlarms, with pending: < - Assertion 'Eva,initialization' (file idct.c, line 180) -3980,3982d3768 +3979,3981d3767 < [ - ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 109) < assert Eva: initialization: \initialized(&tmp1[i][j]); < tried with Eva. -3986,4019d3771 +3985,4018d3770 < [ - ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 116) < assert Eva: initialization: \initialized(&tmp2[i][j]); < tried with Eva. @@ -352,11 +352,11 @@ < [ - ] Assertion 'Eva,float_to_int' (file ieee_1180_1990.c, line 124) < assert Eva: float_to_int: tmp2[i][j] - 0.5 < 2147483648; < tried with Eva. -4040,4042d3791 +4039,4041d3790 < [ - ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 150) < assert Eva: initialization: \initialized(&tmp1[i][j]); < tried with Eva. -4046,4079d3794 +4045,4078d3793 < [ - ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 157) < assert Eva: initialization: \initialized(&tmp2[i][j]); < tried with Eva. @@ -391,7 +391,7 @@ < [ - ] Assertion 'Eva,float_to_int' (file ieee_1180_1990.c, line 165) < assert Eva: float_to_int: tmp2[i][j] - 0.5 < 2147483648; < tried with Eva. -4179,4195c3894,3900 +4178,4194c3893,3899 < [ Partial ] Assertion 'Eva,initialization' (file ieee_1180_1990.c, line 358) < assert Eva: initialization: \initialized(&res[i].pmse[j][k]); < By RedundantAlarms, with pending: @@ -417,7 +417,7 @@ > reachability of stmt line 196 in main > by Eva. > [ Dead ] Instance of 'Pre-condition (file FRAMAC_SHARE/libc/stdio.h, line 211)' at call 'printf_va_1' (file ieee_1180_1990.c, line 195) -4199,4200c3904,3907 +4198,4199c3903,3906 < by Eva. < [ Valid ] Instance of 'Pre-condition (file FRAMAC_SHARE/libc/stdio.h, line 211)' at call 'printf_va_2' (file ieee_1180_1990.c, line 196) --- @@ -425,18 +425,18 @@ > By Eva because: > - Unreachable call 'printf_va_1' (file ieee_1180_1990.c, line 195) > [ Dead ] Instance of 'Pre-condition (file FRAMAC_SHARE/libc/stdio.h, line 211)' at call 'printf_va_2' (file ieee_1180_1990.c, line 196) -4204c3911,3913 +4203c3910,3912 < by Eva. --- > Locally valid, but unreachable. > By Eva because: > - Unreachable call 'printf_va_2' (file ieee_1180_1990.c, line 196) -4261,4262c3970 +4260,4261c3969 < 194 Completely validated < 16 Locally validated --- > 192 Completely validated -4264,4265c3972,3975 +4263,4264c3971,3974 < 56 To be validated < 836 Total --- diff --git a/tests/libc/fc_builtin_c.c b/tests/libc/fc_builtin_c.c index ea336b1e04e74964ed8d1f4be98dbe91cc52e110..abd1f7ce3defdd44419c38365fc2ce69d680f3b8 100644 --- a/tests/libc/fc_builtin_c.c +++ b/tests/libc/fc_builtin_c.c @@ -34,4 +34,11 @@ int main() { Frama_C_unsigned_long_interval(LONG_MAX - 1UL, LONG_MAX + 1UL); //@ assert bounds: LONG_MAX - 1 <= ul <= LONG_MAX + 1; //@ assert sampling:unknown: ul == LONG_MAX; + +#ifdef __WORDSIZE + int w = __WORDSIZE; +#else + int w = -1; +#endif + //@ assert __WORDSIZE_is_defined: w > 0; } diff --git a/tests/libc/limits_h.c b/tests/libc/limits_h.c index 2c663b2c5645c1ac80856c0c08a53b438939debf..54c08b971f7eb3f03fbe707e6634b41e55940517 100644 --- a/tests/libc/limits_h.c +++ b/tests/libc/limits_h.c @@ -7,6 +7,8 @@ STDOPT: +"-machdep gcc_x86_64" STDOPT: +"-machdep ppc_32" STDOPT: +"-machdep msvc_x86_64" + STDOPT: +"-machdep avr_8" + STDOPT: +"-machdep avr_16" */ #include <sys/types.h> #include <stdint.h> diff --git a/tests/libc/oracle/fc_builtin_c.res.oracle b/tests/libc/oracle/fc_builtin_c.res.oracle index d922ab4e1efacfb6929daebe1b0ce6160246ba19..6ca7e87a24c415fee903563b95ff56478deaecd8 100644 --- a/tests/libc/oracle/fc_builtin_c.res.oracle +++ b/tests/libc/oracle/fc_builtin_c.res.oracle @@ -73,6 +73,7 @@ [eva] fc_builtin_c.c:35: assertion 'bounds' got status valid. [eva:alarm] fc_builtin_c.c:36: Warning: assertion 'sampling,unknown' got status unknown. +[eva] fc_builtin_c.c:43: assertion '__WORDSIZE_is_defined' got status valid. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== @@ -111,4 +112,5 @@ d ∈ [12345678901.2 .. 12345678901.2] l ∈ {-3} ul ∈ {2147483647} + w ∈ {32} __retres ∈ {0} diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle index 45092e46f291f3ead9cfe6dae97543f9ee079c99..af69919cfaada999bd2993b0d2fbe07eda3e0625 100644 --- a/tests/libc/oracle/fc_libc.1.res.oracle +++ b/tests/libc/oracle/fc_libc.1.res.oracle @@ -1,7 +1,7 @@ [kernel] Parsing fc_libc.c (with preprocessing) /* Generated by Frama-C */ typedef unsigned int size_t; -typedef int wchar_t; +typedef long wchar_t; struct __fc_div_t { int quot ; int rem ; @@ -773,7 +773,7 @@ axiomatic WMemChr { axiom wmemchr_def{L}: ∀ wchar_t *s; - ∀ int c; + ∀ long c; ∀ ℤ n; wmemchr(s, c, n) ≡ \true ⇔ (∃ int i; 0 ≤ i < n ∧ *(s + i) ≡ c); @@ -1162,7 +1162,7 @@ extern unsigned long long strtoull(char const * restrict nptr, /*@ ghost extern int __fc_random_counter __attribute__((__unused__)); */ -unsigned long const __fc_rand_max = (unsigned long)32767; +unsigned long const __fc_rand_max = (unsigned long)2147483647; /*@ ensures result_range: 0 ≤ \result ≤ __fc_rand_max; assigns \result, __fc_random_counter; assigns \result \from __fc_random_counter; @@ -3523,8 +3523,7 @@ extern float frexpf(float x, int *exp); extern long double frexpl(long double x, int *exp); /*@ requires - finite_logic_res: - \is_finite((double)(x * pow((double)2.0d, (double)exp))); + finite_logic_res: \is_finite((double)(x * pow(2.0d, (double)exp))); ensures finite_result: \is_finite(\result); ensures __fc_errno: __fc_errno ≡ 34 ∨ __fc_errno ≡ \old(__fc_errno); @@ -3536,8 +3535,7 @@ extern double ldexp(double x, int exp); /*@ requires finite_logic_res: - \is_finite((float)(x * - pow((double)((float)2.0f), (double)((float)exp)))); + \is_finite((float)(x * pow((double)(2.0f), (double)((float)exp)))); ensures finite_result: \is_finite(\result); ensures __fc_errno: __fc_errno ≡ 34 ∨ __fc_errno ≡ \old(__fc_errno); @@ -4070,7 +4068,7 @@ extern int volatile __fc_fds[1024]; 0 ≤ i < iovcnt ⇒ \valid((char *)(&(iov + i)->iov_base) + (0 .. (iov + i)->iov_len - 1)); - requires bounded_iovcnt: 0 ≤ iovcnt ≤ 1024; + requires bounded_iovcnt: 0 ≤ iovcnt ≤ 255; ensures result_error_or_read_bytes: \result ≡ -1 ∨ @@ -4103,7 +4101,7 @@ extern ssize_t readv(int fd, struct iovec const *iov, int iovcnt); 0 ≤ i < iovcnt ⇒ \valid_read((char *)(iov + i)->iov_base + (0 .. (iov + i)->iov_len - 1)); - requires bounded_iovcnt: 0 ≤ iovcnt ≤ 1024; + requires bounded_iovcnt: 0 ≤ iovcnt ≤ 255; requires bounded_lengths: \sum(0, iovcnt - 1, \lambda ℤ k; (iov + k)->iov_len) ≤ 2147483647; @@ -4555,19 +4553,19 @@ int getaddrinfo(char const * restrict nodename, } tmp_3 = Frama_C_interval(0,43); sa->sa_family = (sa_family_t)tmp_3; - /*@ slevel 15; */ + /*@ slevel 15; */ ; { int i = 0; while (i < 14) { { int tmp_4; - tmp_4 = Frama_C_interval(-128,127); + tmp_4 = Frama_C_interval(-127 - 1,127); sa->sa_data[i] = (char)tmp_4; } i ++; } } - /*@ slevel default; */ + /*@ slevel default; */ ; ai->ai_flags = 0; ai->ai_family = (int)sa->sa_family; ai->ai_socktype = Frama_C_interval(0,5); @@ -4597,7 +4595,7 @@ static int res_search(char const *dname, int rec_class, int type, { int i = 0; while (i < anslen - 1) { - *(answer + i) = Frama_C_char_interval((char)(-128),(char)127); + *(answer + i) = Frama_C_char_interval((char)(-127 - 1),(char)127); i ++; } } @@ -6065,18 +6063,18 @@ FILE * const __fc_p_fopen = __fc_fopen; */ extern FILE *tmpfile(void); -char __fc_tmpnam[2048]; +char __fc_tmpnam[20]; char * const __fc_p_tmpnam = __fc_tmpnam; -/*@ requires valid_s_or_null: s ≡ \null ∨ \valid(s + (0 .. 2048)); +/*@ requires valid_s_or_null: s ≡ \null ∨ \valid(s + (0 .. 20)); 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 *(__fc_p_tmpnam + (0 .. 20)), *(s + (0 .. 20)), \result; + assigns *(__fc_p_tmpnam + (0 .. 20)) + \from *(__fc_p_tmpnam + (0 .. 20)), (indirect: s); + assigns *(s + (0 .. 20)) + \from (indirect: s), *(__fc_p_tmpnam + (0 .. 20)); assigns \result \from s, __fc_p_tmpnam; */ extern char *tmpnam(char *s); @@ -6729,7 +6727,7 @@ char *fgets(char * restrict s, int size, FILE * restrict stream) __retres = s; goto return_label; } - tmp_2 = Frama_C_interval(-128,127); + tmp_2 = Frama_C_interval(-127 - 1,127); char c = (char)tmp_2; *(s + i) = c; if ((int)c == '\n') { @@ -6746,7 +6744,7 @@ char *fgets(char * restrict s, int size, FILE * restrict stream) } /*@ requires valid_stream: \valid(stream); - ensures result_uchar_or_eof: (0 ≤ \result ≤ 255) ∨ \result ≡ -1; + ensures result_uchar_or_eof: (0 ≤ \result ≤ 255U) ∨ \result ≡ -1; assigns *stream, \result; assigns *stream \from *stream; assigns \result \from (indirect: *stream); @@ -6774,7 +6772,7 @@ int fgetc(FILE * restrict stream) else { unsigned char tmp_1; tmp_1 = Frama_C_unsigned_char_interval((unsigned char)0, - (unsigned char)255); + (unsigned char)255U); __retres = (int)tmp_1; goto return_label; } @@ -7227,9 +7225,9 @@ char *realpath(char const * restrict file_name, char * restrict resolved_name) goto return_label; default: break; } - int realpath_len = Frama_C_interval(1,256); + int realpath_len = Frama_C_interval(1,4096); if (! resolved_name) { - resolved_name = (char *)malloc((size_t)256); + resolved_name = (char *)malloc((size_t)4096); if (! resolved_name) { __fc_errno = 12; __retres = (char *)0; @@ -8609,7 +8607,8 @@ int getopt(int argc, char * const *argv, char const *optstring) optarg = (char *)Frama_C_nondet_ptr((void *)0, (void *)(*(argv + nondet_ind) + nondet_indlen)); optind = Frama_C_interval(1,argc + 1); - tmp_2 = Frama_C_unsigned_char_interval((unsigned char)0,(unsigned char)255); + tmp_2 = Frama_C_unsigned_char_interval((unsigned char)0, + (unsigned char)255U); tmp_3 = Frama_C_nondet(-1,(int)tmp_2); __retres = tmp_3; return_label: return __retres; @@ -8679,11 +8678,11 @@ wchar_t *wcscpy(wchar_t *dest, wchar_t const *src) { size_t i; i = (size_t)0; - while (*(src + i) != 0) { + while (*(src + i) != 0L) { *(dest + i) = *(src + i); i ++; } - *(dest + i) = 0; + *(dest + i) = 0L; return dest; } @@ -8696,7 +8695,7 @@ size_t wcslen(wchar_t const *str) { size_t i; i = (size_t)0; - while (*(str + i) != 0) i ++; + while (*(str + i) != 0L) i ++; return i; } @@ -8718,11 +8717,11 @@ wchar_t *wcsncpy(wchar_t *dest, wchar_t const *src, size_t n) i = (size_t)0; while (i < n) { *(dest + i) = *(src + i); - if (*(src + i) == 0) break; + if (*(src + i) == 0L) break; i ++; } while (i < n) { - *(dest + i) = 0; + *(dest + i) = 0L; i ++; } return dest; @@ -8750,11 +8749,11 @@ wchar_t *wcscat(wchar_t *dest, wchar_t const *src) size_t i; size_t n = wcslen((wchar_t const *)dest); i = (size_t)0; - while (*(src + i) != 0) { + while (*(src + i) != 0L) { *(dest + (n + i)) = *(src + i); i ++; } - *(dest + (n + i)) = 0; + *(dest + (n + i)) = 0L; return dest; } @@ -8782,13 +8781,13 @@ wchar_t *wcsncat(wchar_t *dest, wchar_t const *src, size_t n) i = (size_t)0; while (1) { if (i < n) { - if (! (*(src + i) != 0)) break; + if (! (*(src + i) != 0L)) break; } else break; *(dest + (dest_len + i)) = *(src + i); i ++; } - *(dest + (dest_len + i)) = 0; + *(dest + (dest_len + i)) = 0L; return dest; } @@ -10212,7 +10211,7 @@ extern int iconv_close(iconv_t __x0); */ extern iconv_t iconv_open(char const *tocode, char const *fromcode); -extern char __fc_basename[256]; +extern char __fc_basename[4096]; char *__fc_p_basename = __fc_basename; /*@ requires @@ -10227,7 +10226,7 @@ char *__fc_p_basename = __fc_basename; */ extern char *basename(char *path); -extern char __fc_dirname[256]; +extern char __fc_dirname[4096]; char *__fc_p_dirname = __fc_dirname; /*@ requires diff --git a/tests/libc/oracle/fc_libc.2.res.oracle b/tests/libc/oracle/fc_libc.2.res.oracle index dc3e1747f8b51da5427112734c10885ea157d00a..b8e07f4d5104574e045c2d0751cfc89acda935f0 100644 --- a/tests/libc/oracle/fc_libc.2.res.oracle +++ b/tests/libc/oracle/fc_libc.2.res.oracle @@ -44,8 +44,6 @@ [kernel] Parsing FRAMAC_SHARE/libc/__fc_inet.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/__fc_integer.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/__fc_libc.h (with preprocessing) -[kernel] Parsing FRAMAC_SHARE/libc/__fc_machdep.h (with preprocessing) -skipping FRAMAC_SHARE/libc/__fc_machdep_linux_shared.h [kernel] Parsing FRAMAC_SHARE/libc/__fc_select.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/__fc_string_axiomatic.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/aio.h (with preprocessing) diff --git a/tests/libc/oracle/inttypes_h.2.res.oracle b/tests/libc/oracle/inttypes_h.2.res.oracle index 92f400d2eb09f2eaf2e35ed7bd2037d5632d7974..df0cd81b6ed3724ab9a3a7826de79ae61ef9ba46 100644 --- a/tests/libc/oracle/inttypes_h.2.res.oracle +++ b/tests/libc/oracle/inttypes_h.2.res.oracle @@ -1641,7 +1641,7 @@ int printf_va_54(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_55(char const * restrict format, int *param0); +int scanf_va_55(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1654,7 +1654,7 @@ int scanf_va_55(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_55(char const * restrict format, int param0); +int printf_va_55(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1671,7 +1671,7 @@ int printf_va_55(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_56(char const * restrict format, int *param0); +int scanf_va_56(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1684,7 +1684,7 @@ int scanf_va_56(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_56(char const * restrict format, int param0); +int printf_va_56(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1701,7 +1701,7 @@ int printf_va_56(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_57(char const * restrict format, unsigned int *param0); +int scanf_va_57(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1714,7 +1714,7 @@ int scanf_va_57(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_57(char const * restrict format, unsigned int param0); +int printf_va_57(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1731,7 +1731,7 @@ int printf_va_57(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_58(char const * restrict format, unsigned int *param0); +int scanf_va_58(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1744,7 +1744,7 @@ int scanf_va_58(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_58(char const * restrict format, unsigned int param0); +int printf_va_58(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1761,7 +1761,7 @@ int printf_va_58(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_59(char const * restrict format, unsigned int *param0); +int scanf_va_59(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1774,7 +1774,7 @@ int scanf_va_59(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_59(char const * restrict format, unsigned int param0); +int printf_va_59(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1791,7 +1791,7 @@ int printf_va_59(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_60(char const * restrict format, unsigned int *param0); +int scanf_va_60(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1804,7 +1804,7 @@ int scanf_va_60(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_60(char const * restrict format, unsigned int param0); +int printf_va_60(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1821,7 +1821,7 @@ int printf_va_60(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_61(char const * restrict format, int *param0); +int scanf_va_61(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1834,7 +1834,7 @@ int scanf_va_61(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_61(char const * restrict format, int param0); +int printf_va_61(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1851,7 +1851,7 @@ int printf_va_61(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_62(char const * restrict format, int *param0); +int scanf_va_62(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1864,7 +1864,7 @@ int scanf_va_62(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_62(char const * restrict format, int param0); +int printf_va_62(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1881,7 +1881,7 @@ int printf_va_62(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_63(char const * restrict format, unsigned int *param0); +int scanf_va_63(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1894,7 +1894,7 @@ int scanf_va_63(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_63(char const * restrict format, unsigned int param0); +int printf_va_63(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1911,7 +1911,7 @@ int printf_va_63(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_64(char const * restrict format, unsigned int *param0); +int scanf_va_64(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1924,7 +1924,7 @@ int scanf_va_64(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_64(char const * restrict format, unsigned int param0); +int printf_va_64(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1941,7 +1941,7 @@ int printf_va_64(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_65(char const * restrict format, unsigned int *param0); +int scanf_va_65(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1954,7 +1954,7 @@ int scanf_va_65(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_65(char const * restrict format, unsigned int param0); +int printf_va_65(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1971,7 +1971,7 @@ int printf_va_65(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_66(char const * restrict format, unsigned int *param0); +int scanf_va_66(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1984,7 +1984,7 @@ int scanf_va_66(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_66(char const * restrict format, unsigned int param0); +int printf_va_66(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -2693,39 +2693,39 @@ int main(void) } { int_fast16_t x_17; - scanf("%d",& x_17); /* scanf_va_55 */ - printf("%d",x_17); /* printf_va_55 */ - scanf("%i",& x_17); /* scanf_va_56 */ - printf("%i",x_17); /* printf_va_56 */ + scanf("%ld",& x_17); /* scanf_va_55 */ + printf("%ld",x_17); /* printf_va_55 */ + scanf("%li",& x_17); /* scanf_va_56 */ + printf("%li",x_17); /* printf_va_56 */ } { uint_fast16_t x_18; - scanf("%o",& x_18); /* scanf_va_57 */ - printf("%o",x_18); /* printf_va_57 */ - scanf("%u",& x_18); /* scanf_va_58 */ - printf("%u",x_18); /* printf_va_58 */ - scanf("%x",& x_18); /* scanf_va_59 */ - printf("%x",x_18); /* printf_va_59 */ - scanf("%x",& x_18); /* scanf_va_60 */ - printf("%X",x_18); /* printf_va_60 */ + scanf("%lo",& x_18); /* scanf_va_57 */ + printf("%lo",x_18); /* printf_va_57 */ + scanf("%lu",& x_18); /* scanf_va_58 */ + printf("%lu",x_18); /* printf_va_58 */ + scanf("%lx",& x_18); /* scanf_va_59 */ + printf("%lx",x_18); /* printf_va_59 */ + scanf("%lx",& x_18); /* scanf_va_60 */ + printf("%lX",x_18); /* printf_va_60 */ } { int_fast32_t x_19; - scanf("%d",& x_19); /* scanf_va_61 */ - printf("%d",x_19); /* printf_va_61 */ - scanf("%i",& x_19); /* scanf_va_62 */ - printf("%i",x_19); /* printf_va_62 */ + scanf("%ld",& x_19); /* scanf_va_61 */ + printf("%ld",x_19); /* printf_va_61 */ + scanf("%li",& x_19); /* scanf_va_62 */ + printf("%li",x_19); /* printf_va_62 */ } { uint_fast32_t x_20; - scanf("%o",& x_20); /* scanf_va_63 */ - printf("%o",x_20); /* printf_va_63 */ - scanf("%u",& x_20); /* scanf_va_64 */ - printf("%u",x_20); /* printf_va_64 */ - scanf("%x",& x_20); /* scanf_va_65 */ - printf("%x",x_20); /* printf_va_65 */ - scanf("%x",& x_20); /* scanf_va_66 */ - printf("%X",x_20); /* printf_va_66 */ + scanf("%lo",& x_20); /* scanf_va_63 */ + printf("%lo",x_20); /* printf_va_63 */ + scanf("%lu",& x_20); /* scanf_va_64 */ + printf("%lu",x_20); /* printf_va_64 */ + scanf("%lx",& x_20); /* scanf_va_65 */ + printf("%lx",x_20); /* printf_va_65 */ + scanf("%lx",& x_20); /* scanf_va_66 */ + printf("%lX",x_20); /* printf_va_66 */ } { int_fast64_t x_21; diff --git a/tests/libc/oracle/inttypes_h.5.res.oracle b/tests/libc/oracle/inttypes_h.5.res.oracle index 92f400d2eb09f2eaf2e35ed7bd2037d5632d7974..df0cd81b6ed3724ab9a3a7826de79ae61ef9ba46 100644 --- a/tests/libc/oracle/inttypes_h.5.res.oracle +++ b/tests/libc/oracle/inttypes_h.5.res.oracle @@ -1641,7 +1641,7 @@ int printf_va_54(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_55(char const * restrict format, int *param0); +int scanf_va_55(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1654,7 +1654,7 @@ int scanf_va_55(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_55(char const * restrict format, int param0); +int printf_va_55(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1671,7 +1671,7 @@ int printf_va_55(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_56(char const * restrict format, int *param0); +int scanf_va_56(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1684,7 +1684,7 @@ int scanf_va_56(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_56(char const * restrict format, int param0); +int printf_va_56(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1701,7 +1701,7 @@ int printf_va_56(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_57(char const * restrict format, unsigned int *param0); +int scanf_va_57(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1714,7 +1714,7 @@ int scanf_va_57(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_57(char const * restrict format, unsigned int param0); +int printf_va_57(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1731,7 +1731,7 @@ int printf_va_57(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_58(char const * restrict format, unsigned int *param0); +int scanf_va_58(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1744,7 +1744,7 @@ int scanf_va_58(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_58(char const * restrict format, unsigned int param0); +int printf_va_58(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1761,7 +1761,7 @@ int printf_va_58(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_59(char const * restrict format, unsigned int *param0); +int scanf_va_59(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1774,7 +1774,7 @@ int scanf_va_59(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_59(char const * restrict format, unsigned int param0); +int printf_va_59(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1791,7 +1791,7 @@ int printf_va_59(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_60(char const * restrict format, unsigned int *param0); +int scanf_va_60(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1804,7 +1804,7 @@ int scanf_va_60(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_60(char const * restrict format, unsigned int param0); +int printf_va_60(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1821,7 +1821,7 @@ int printf_va_60(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_61(char const * restrict format, int *param0); +int scanf_va_61(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1834,7 +1834,7 @@ int scanf_va_61(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_61(char const * restrict format, int param0); +int printf_va_61(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1851,7 +1851,7 @@ int printf_va_61(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_62(char const * restrict format, int *param0); +int scanf_va_62(char const * restrict format, long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1864,7 +1864,7 @@ int scanf_va_62(char const * restrict format, int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_62(char const * restrict format, int param0); +int printf_va_62(char const * restrict format, long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1881,7 +1881,7 @@ int printf_va_62(char const * restrict format, int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_63(char const * restrict format, unsigned int *param0); +int scanf_va_63(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1894,7 +1894,7 @@ int scanf_va_63(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_63(char const * restrict format, unsigned int param0); +int printf_va_63(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1911,7 +1911,7 @@ int printf_va_63(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_64(char const * restrict format, unsigned int *param0); +int scanf_va_64(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1924,7 +1924,7 @@ int scanf_va_64(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_64(char const * restrict format, unsigned int param0); +int printf_va_64(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1941,7 +1941,7 @@ int printf_va_64(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_65(char const * restrict format, unsigned int *param0); +int scanf_va_65(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1954,7 +1954,7 @@ int scanf_va_65(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_65(char const * restrict format, unsigned int param0); +int printf_va_65(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -1971,7 +1971,7 @@ int printf_va_65(char const * restrict format, unsigned int param0); \from (indirect: __fc_stdin->__fc_FILE_id), __fc_stdin->__fc_FILE_data, (indirect: *(format + (0 ..))); */ -int scanf_va_66(char const * restrict format, unsigned int *param0); +int scanf_va_66(char const * restrict format, unsigned long *param0); /*@ requires valid_read_string(format); assigns \result, __fc_stdout->__fc_FILE_data; @@ -1984,7 +1984,7 @@ int scanf_va_66(char const * restrict format, unsigned int *param0); __fc_stdout->__fc_FILE_data, (indirect: *(format + (0 ..))), param0; */ -int printf_va_66(char const * restrict format, unsigned int param0); +int printf_va_66(char const * restrict format, unsigned long param0); /*@ requires \valid(param0); requires valid_read_string(format); @@ -2693,39 +2693,39 @@ int main(void) } { int_fast16_t x_17; - scanf("%d",& x_17); /* scanf_va_55 */ - printf("%d",x_17); /* printf_va_55 */ - scanf("%i",& x_17); /* scanf_va_56 */ - printf("%i",x_17); /* printf_va_56 */ + scanf("%ld",& x_17); /* scanf_va_55 */ + printf("%ld",x_17); /* printf_va_55 */ + scanf("%li",& x_17); /* scanf_va_56 */ + printf("%li",x_17); /* printf_va_56 */ } { uint_fast16_t x_18; - scanf("%o",& x_18); /* scanf_va_57 */ - printf("%o",x_18); /* printf_va_57 */ - scanf("%u",& x_18); /* scanf_va_58 */ - printf("%u",x_18); /* printf_va_58 */ - scanf("%x",& x_18); /* scanf_va_59 */ - printf("%x",x_18); /* printf_va_59 */ - scanf("%x",& x_18); /* scanf_va_60 */ - printf("%X",x_18); /* printf_va_60 */ + scanf("%lo",& x_18); /* scanf_va_57 */ + printf("%lo",x_18); /* printf_va_57 */ + scanf("%lu",& x_18); /* scanf_va_58 */ + printf("%lu",x_18); /* printf_va_58 */ + scanf("%lx",& x_18); /* scanf_va_59 */ + printf("%lx",x_18); /* printf_va_59 */ + scanf("%lx",& x_18); /* scanf_va_60 */ + printf("%lX",x_18); /* printf_va_60 */ } { int_fast32_t x_19; - scanf("%d",& x_19); /* scanf_va_61 */ - printf("%d",x_19); /* printf_va_61 */ - scanf("%i",& x_19); /* scanf_va_62 */ - printf("%i",x_19); /* printf_va_62 */ + scanf("%ld",& x_19); /* scanf_va_61 */ + printf("%ld",x_19); /* printf_va_61 */ + scanf("%li",& x_19); /* scanf_va_62 */ + printf("%li",x_19); /* printf_va_62 */ } { uint_fast32_t x_20; - scanf("%o",& x_20); /* scanf_va_63 */ - printf("%o",x_20); /* printf_va_63 */ - scanf("%u",& x_20); /* scanf_va_64 */ - printf("%u",x_20); /* printf_va_64 */ - scanf("%x",& x_20); /* scanf_va_65 */ - printf("%x",x_20); /* printf_va_65 */ - scanf("%x",& x_20); /* scanf_va_66 */ - printf("%X",x_20); /* printf_va_66 */ + scanf("%lo",& x_20); /* scanf_va_63 */ + printf("%lo",x_20); /* printf_va_63 */ + scanf("%lu",& x_20); /* scanf_va_64 */ + printf("%lu",x_20); /* printf_va_64 */ + scanf("%lx",& x_20); /* scanf_va_65 */ + printf("%lx",x_20); /* printf_va_65 */ + scanf("%lx",& x_20); /* scanf_va_66 */ + printf("%lX",x_20); /* printf_va_66 */ } { int_fast64_t x_21; diff --git a/tests/libc/oracle/libgen_h.res.oracle b/tests/libc/oracle/libgen_h.res.oracle index 2eeaf40c580c209ef0fd72c3720998b966ec0697..4d57e4b9a64827602fb28e5ea3f577c496d9e625 100644 --- a/tests/libc/oracle/libgen_h.res.oracle +++ b/tests/libc/oracle/libgen_h.res.oracle @@ -38,8 +38,8 @@ [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: - __fc_basename[0..255] ∈ [--..--] - __fc_dirname[0..255] ∈ [--..--] + __fc_basename[0..4095] ∈ [--..--] + __fc_dirname[0..4095] ∈ [--..--] path[0..127] ∈ [--..--] base ∈ {{ &__fc_basename[0] ; &path[0] }} base2 ∈ {{ NULL ; &__fc_basename[0] }} diff --git a/tests/libc/oracle/limits_h.0.res.oracle b/tests/libc/oracle/limits_h.0.res.oracle index 5efc6b677c12f12f339a65a77dd04ed411871a97..d42e459085a4be11eaabb8306061dd7af7309f38 100644 --- a/tests/libc/oracle/limits_h.0.res.oracle +++ b/tests/libc/oracle/limits_h.0.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,13 +24,15 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 6 assertion(s) [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: size_max ∈ {65535} - ssize_max ∈ {2147483647} + ssize_max ∈ {32767} intptr_max ∈ {2147483647} intptr_min ∈ {-2147483648} uintptr_max ∈ {4294967295} diff --git a/tests/libc/oracle/limits_h.1.res.oracle b/tests/libc/oracle/limits_h.1.res.oracle index 3affdff5cd178c4aaf8f9d2e55e081a1d36a3e60..d78a8936659922e423a02379a1a422f772c7bc8a 100644 --- a/tests/libc/oracle/limits_h.1.res.oracle +++ b/tests/libc/oracle/limits_h.1.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,6 +24,8 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 7 assertion(s) diff --git a/tests/libc/oracle/limits_h.2.res.oracle b/tests/libc/oracle/limits_h.2.res.oracle index f58b4f6de22cafe5371119260e1a015ec9f0f04d..f319e18684ca720670392c267aa897263718e6d4 100644 --- a/tests/libc/oracle/limits_h.2.res.oracle +++ b/tests/libc/oracle/limits_h.2.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,6 +24,8 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 7 assertion(s) diff --git a/tests/libc/oracle/limits_h.3.res.oracle b/tests/libc/oracle/limits_h.3.res.oracle index 5efc6b677c12f12f339a65a77dd04ed411871a97..d42e459085a4be11eaabb8306061dd7af7309f38 100644 --- a/tests/libc/oracle/limits_h.3.res.oracle +++ b/tests/libc/oracle/limits_h.3.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,13 +24,15 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 6 assertion(s) [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: size_max ∈ {65535} - ssize_max ∈ {2147483647} + ssize_max ∈ {32767} intptr_max ∈ {2147483647} intptr_min ∈ {-2147483648} uintptr_max ∈ {4294967295} diff --git a/tests/libc/oracle/limits_h.4.res.oracle b/tests/libc/oracle/limits_h.4.res.oracle index 3affdff5cd178c4aaf8f9d2e55e081a1d36a3e60..d78a8936659922e423a02379a1a422f772c7bc8a 100644 --- a/tests/libc/oracle/limits_h.4.res.oracle +++ b/tests/libc/oracle/limits_h.4.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,6 +24,8 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 7 assertion(s) diff --git a/tests/libc/oracle/limits_h.5.res.oracle b/tests/libc/oracle/limits_h.5.res.oracle index f58b4f6de22cafe5371119260e1a015ec9f0f04d..f319e18684ca720670392c267aa897263718e6d4 100644 --- a/tests/libc/oracle/limits_h.5.res.oracle +++ b/tests/libc/oracle/limits_h.5.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,6 +24,8 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 7 assertion(s) diff --git a/tests/libc/oracle/limits_h.6.res.oracle b/tests/libc/oracle/limits_h.6.res.oracle index 3affdff5cd178c4aaf8f9d2e55e081a1d36a3e60..d78a8936659922e423a02379a1a422f772c7bc8a 100644 --- a/tests/libc/oracle/limits_h.6.res.oracle +++ b/tests/libc/oracle/limits_h.6.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,6 +24,8 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 7 assertion(s) diff --git a/tests/libc/oracle/limits_h.7.res.oracle b/tests/libc/oracle/limits_h.7.res.oracle index c5ca9b76a1d60e30ad18a2156d760d0487b2628c..5cd6ee11b6548aa5c94a7d21ff596a60ece19dbc 100644 --- a/tests/libc/oracle/limits_h.7.res.oracle +++ b/tests/libc/oracle/limits_h.7.res.oracle @@ -4,9 +4,7 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] limits_h.c:16: assertion got status valid. [eva] limits_h.c:18: assertion got status valid. -[eva] limits_h.c:19: assertion got status valid. [eva] limits_h.c:20: assertion got status valid. [eva] limits_h.c:21: assertion got status valid. [eva] limits_h.c:22: assertion got status valid. @@ -26,6 +24,8 @@ [eva] limits_h.c:36: assertion got status valid. [eva] limits_h.c:37: assertion got status valid. [eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. [eva] Recording results for main [eva] done for function main [scope:rm_asserts] removing 7 assertion(s) diff --git a/tests/libc/oracle/limits_h.8.res.oracle b/tests/libc/oracle/limits_h.8.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..01d45df1542894c909d0b1598daad6f65f3e79f0 --- /dev/null +++ b/tests/libc/oracle/limits_h.8.res.oracle @@ -0,0 +1,38 @@ +[kernel] Parsing limits_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] limits_h.c:18: assertion got status valid. +[eva] limits_h.c:20: assertion got status valid. +[eva] limits_h.c:21: assertion got status valid. +[eva] limits_h.c:22: assertion got status valid. +[eva] limits_h.c:23: assertion got status valid. +[eva] limits_h.c:24: assertion got status valid. +[eva] limits_h.c:25: assertion got status valid. +[eva] limits_h.c:26: assertion got status valid. +[eva] limits_h.c:27: assertion got status valid. +[eva] limits_h.c:28: assertion got status valid. +[eva] limits_h.c:29: assertion got status valid. +[eva] limits_h.c:30: assertion got status valid. +[eva] limits_h.c:31: assertion got status valid. +[eva] limits_h.c:32: assertion got status valid. +[eva] limits_h.c:33: assertion got status valid. +[eva] limits_h.c:34: assertion got status valid. +[eva] limits_h.c:35: assertion got status valid. +[eva] limits_h.c:36: assertion got status valid. +[eva] limits_h.c:37: assertion got status valid. +[eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. +[eva] Recording results for main +[eva] done for function main +[scope:rm_asserts] removing 6 assertion(s) +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + size_max ∈ {65535} + intptr_max ∈ {32767} + intptr_min ∈ {-32768} + uintptr_max ∈ {65535} + uintmax_max ∈ {18446744073709551615} diff --git a/tests/libc/oracle/limits_h.9.res.oracle b/tests/libc/oracle/limits_h.9.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..01d45df1542894c909d0b1598daad6f65f3e79f0 --- /dev/null +++ b/tests/libc/oracle/limits_h.9.res.oracle @@ -0,0 +1,38 @@ +[kernel] Parsing limits_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] limits_h.c:18: assertion got status valid. +[eva] limits_h.c:20: assertion got status valid. +[eva] limits_h.c:21: assertion got status valid. +[eva] limits_h.c:22: assertion got status valid. +[eva] limits_h.c:23: assertion got status valid. +[eva] limits_h.c:24: assertion got status valid. +[eva] limits_h.c:25: assertion got status valid. +[eva] limits_h.c:26: assertion got status valid. +[eva] limits_h.c:27: assertion got status valid. +[eva] limits_h.c:28: assertion got status valid. +[eva] limits_h.c:29: assertion got status valid. +[eva] limits_h.c:30: assertion got status valid. +[eva] limits_h.c:31: assertion got status valid. +[eva] limits_h.c:32: assertion got status valid. +[eva] limits_h.c:33: assertion got status valid. +[eva] limits_h.c:34: assertion got status valid. +[eva] limits_h.c:35: assertion got status valid. +[eva] limits_h.c:36: assertion got status valid. +[eva] limits_h.c:37: assertion got status valid. +[eva] limits_h.c:38: assertion got status valid. +[eva] limits_h.c:39: assertion got status valid. +[eva] limits_h.c:40: assertion got status valid. +[eva] Recording results for main +[eva] done for function main +[scope:rm_asserts] removing 6 assertion(s) +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function main: + size_max ∈ {65535} + intptr_max ∈ {32767} + intptr_min ∈ {-32768} + uintptr_max ∈ {65535} + uintmax_max ∈ {18446744073709551615} diff --git a/tests/libc/oracle/signal_h.res.oracle b/tests/libc/oracle/signal_h.res.oracle index 7c70744fb716464287f0a4115e9fc8b0831f7884..efade1922a061ad31e4bdcaa1ff5ad0f22ace360 100644 --- a/tests/libc/oracle/signal_h.res.oracle +++ b/tests/libc/oracle/signal_h.res.oracle @@ -126,7 +126,7 @@ function sigaction: precondition 'valid_read_act_or_null' got status valid. [eva] signal_h.c:48: function sigaction: precondition 'separation,separated_acts' got status valid. -[eva] FRAMAC_SHARE/libc/signal.h:223: +[eva] FRAMAC_SHARE/libc/signal.h:229: cannot evaluate ACSL term, unsupported ACSL construct: logic coercion struct sigaction -> set<struct sigaction> [eva] Done for function sigaction [eva] computing for function sigaction <- main. diff --git a/tests/libc/oracle/stdlib_c.0.res.oracle b/tests/libc/oracle/stdlib_c.0.res.oracle index cb22bbb0198fb86def1f95ae8ab4817a07775f8c..276e662d50c399250dce2614e96308566c68c36b 100644 --- a/tests/libc/oracle/stdlib_c.0.res.oracle +++ b/tests/libc/oracle/stdlib_c.0.res.oracle @@ -256,21 +256,21 @@ resolved_name ∈ {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ; &__malloc_realpath_l224_0[0] }} - realpath_len ∈ [1..256] + realpath_len ∈ [1..4096] __retres ∈ {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ; &__malloc_realpath_l224_0[0] }} - __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED + __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224_0[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED [eva:final-states] Values at end of function canonicalize_file_name: __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_errno ∈ [--..--] __malloc_realpath_l224_0[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED [eva:final-states] Values at end of function main: __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] @@ -289,8 +289,8 @@ canon ∈ {{ NULL ; &__malloc_realpath_l224_0[0] }} __retres ∈ {0; 1} __calloc_w_main_l33[0..1073741823] ∈ {0; 42} - __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED + __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224_0[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED diff --git a/tests/libc/oracle/stdlib_c.1.res.oracle b/tests/libc/oracle/stdlib_c.1.res.oracle index 96a5d173a353310558116dac6f02425b4a3d3b39..95a6a6d6b063be4bf82b8f17affcbf3e9e09f9fe 100644 --- a/tests/libc/oracle/stdlib_c.1.res.oracle +++ b/tests/libc/oracle/stdlib_c.1.res.oracle @@ -274,21 +274,21 @@ resolved_name ∈ {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ; &__malloc_realpath_l224_0[0] }} - realpath_len ∈ [1..256] + realpath_len ∈ [1..4096] __retres ∈ {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ; &__malloc_realpath_l224_0[0] }} - __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED + __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224_0[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED [eva:final-states] Values at end of function canonicalize_file_name: __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_errno ∈ [--..--] __malloc_realpath_l224_0[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED [eva:final-states] Values at end of function main: __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] @@ -307,8 +307,8 @@ canon ∈ {{ NULL ; &__malloc_realpath_l224_0[0] }} __retres ∈ {0} __calloc_w_main_l33[0..1073741823] ∈ {0; 42} - __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED + __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED __malloc_realpath_l224_0[0] ∈ [--..--] - [1..255] ∈ [--..--] or UNINITIALIZED + [1..4095] ∈ [--..--] or UNINITIALIZED diff --git a/tests/libc/oracle/stdlib_c.2.res.oracle b/tests/libc/oracle/stdlib_c.2.res.oracle index ff5db5635efaa67de7c7c6da5d9953b25c86a9c4..8090933af98958cc3fd154206444496df7d62a26 100644 --- a/tests/libc/oracle/stdlib_c.2.res.oracle +++ b/tests/libc/oracle/stdlib_c.2.res.oracle @@ -228,18 +228,18 @@ resolved_name ∈ {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ; &__malloc_realpath_l224_0[0] }} - realpath_len ∈ [1..256] + realpath_len ∈ [1..4096] __retres ∈ {{ NULL ; &__malloc_main_l44[0] ; &__malloc_realpath_l224[0] ; &__malloc_realpath_l224_0[0] }} - __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED - __malloc_realpath_l224[0..255] ∈ [--..--] or UNINITIALIZED - __malloc_realpath_l224_0[0..255] ∈ [--..--] or UNINITIALIZED + __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED + __malloc_realpath_l224[0..4095] ∈ [--..--] or UNINITIALIZED + __malloc_realpath_l224_0[0..4095] ∈ [--..--] or UNINITIALIZED [eva:final-states] Values at end of function canonicalize_file_name: __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] __fc_errno ∈ [--..--] - __malloc_realpath_l224_0[0..255] ∈ [--..--] or UNINITIALIZED + __malloc_realpath_l224_0[0..4095] ∈ [--..--] or UNINITIALIZED [eva:final-states] Values at end of function main: __fc_heap_status ∈ [--..--] Frama_C_entropy_source ∈ [--..--] @@ -260,6 +260,6 @@ __malloc_calloc_l72[0..3] ∈ [--..--] or UNINITIALIZED __malloc_calloc_l72_0[0..4294967291] ∈ [--..--] or UNINITIALIZED __malloc_w_calloc_l72_1[0..4294967291] ∈ [--..--] or UNINITIALIZED - __malloc_main_l44[0..255] ∈ [--..--] or UNINITIALIZED - __malloc_realpath_l224[0..255] ∈ [--..--] or UNINITIALIZED - __malloc_realpath_l224_0[0..255] ∈ [--..--] or UNINITIALIZED + __malloc_main_l44[0..4095] ∈ [--..--] or UNINITIALIZED + __malloc_realpath_l224[0..4095] ∈ [--..--] or UNINITIALIZED + __malloc_realpath_l224_0[0..4095] ∈ [--..--] or UNINITIALIZED diff --git a/tests/libc/runtime.c b/tests/libc/runtime.c index ec7f02cf510f4293be5c1215a9fc6d403eae49ef..25588a82e04f0833265e745ac70217161f1b0ef7 100644 --- a/tests/libc/runtime.c +++ b/tests/libc/runtime.c @@ -1,7 +1,7 @@ /* run.config* COMMENT: tests that the runtime can compile without errors (for PathCrawler, E-ACSL, ...) - CMD: gcc -D__FC_MACHDEP_X86_64 @FRAMAC_SHARE@/libc/__fc_runtime.c -Wno-attributes -std=c99 -Wall -Wwrite-strings -o @DEV_NULL@ - OPT: + CMD: FRAMAC='@frama-c@' %{dep:@PTEST_DIR@/runtime.sh} + OPT: %{dep:@FRAMAC_SHARE@/libc/__fc_runtime.c} */ int main() { diff --git a/tests/libc/runtime.sh b/tests/libc/runtime.sh new file mode 100755 index 0000000000000000000000000000000000000000..aee0cf3d823f1aa61f34db70db8fd8caae2f4239 --- /dev/null +++ b/tests/libc/runtime.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e +if test -z "$FRAMAC"; then echo "variable FRAMAC must be set"; exit 1; fi +TMPDIR=$(mktemp -d fc_test_libc_XXXXXXXX) +$FRAMAC -print-machdep-header > $TMPDIR/__fc_machdep.h +gcc -I$TMPDIR -D__FC_MACHDEP_X86_64 $@ -Wno-attributes -std=c99 -Wall -Wwrite-strings -o /dev/null +rm -fr $TMPDIR diff --git a/tests/misc/add_assigns.ml b/tests/misc/add_assigns.ml index 11df28607ac8e92edffb3d1ef12b31e1b4f8440d..04d7bec1b147135f8b102a33365da9196a1c918f 100644 --- a/tests/misc/add_assigns.ml +++ b/tests/misc/add_assigns.ml @@ -11,7 +11,7 @@ let main () = computed := true; Ast.compute (); let kf = Globals.Functions.find_by_name "f" in - let y = Globals.Vars.find_from_astinfo "y" (VFormal kf) in + let y = Globals.Vars.find_from_astinfo "y" (Formal kf) in let mem = Logic_const.( new_identified_term diff --git a/tests/misc/custom_machdep.c b/tests/misc/custom_machdep.c index c51544e41f4e98bea09bda86ebeb580a1c6db8b8..1152d590191677fbcd9ca7a88afa65f5d71aa6b3 100644 --- a/tests/misc/custom_machdep.c +++ b/tests/misc/custom_machdep.c @@ -1,11 +1,6 @@ /* run.config* - EXIT: 1 - MODULE: @PTEST_NAME@.cmxs - DEPS: @PTEST_NAME@/__fc_machdep_custom.h - OPT: -cpp-extra-args="-I./@PTEST_NAME@ -D__FC_MACHDEP_CUSTOM" -machdep custom -print -then -print - COMMENT: we need a -then to test double registering of a machdep + OPT: -machdep %{dep:@PTEST_DIR@/@PTEST_NAME@.yaml} -print */ -#include "__fc_machdep_custom.h" // most of the following includes are not directly used, but they test if // the custom machdep has defined the necessary constants #include <ctype.h> @@ -22,4 +17,4 @@ #include <time.h> #include <wchar.h> -int main() { return INT_MAX; } +int main() { return INT_MAX - CUSTOM_MACHDEP; } diff --git a/tests/misc/custom_machdep.ml b/tests/misc/custom_machdep.ml deleted file mode 100644 index 503611ae1fec6f6b921e2d1cdeecfeae7fba075b..0000000000000000000000000000000000000000 --- a/tests/misc/custom_machdep.ml +++ /dev/null @@ -1,57 +0,0 @@ -open Cil_types - -let mach = - { - version = "foo"; - compiler = "bar"; - cpp_arch_flags = []; - sizeof_short = 2; - sizeof_int = 3; - sizeof_long = 4; - sizeof_longlong = 8; - sizeof_ptr = 4; - sizeof_float = 4; - sizeof_double = 8; - sizeof_longdouble = 12; - sizeof_void = 1; - sizeof_fun = 1; - size_t = "unsigned long"; - wchar_t = "int"; - ptrdiff_t = "int"; - alignof_short = 2; - alignof_int = 3; - alignof_long = 4; - alignof_longlong = 4; - alignof_ptr = 4; - alignof_float = 4; - alignof_double = 4; - alignof_longdouble = 4; - alignof_str = 1; - alignof_fun = 1; - alignof_aligned= 16; - char_is_unsigned = false; - const_string_literals = true; - little_endian = true; - underscore_name = false ; - has__builtin_va_list = true; - } - -let mach2 = { mach with compiler = "baz" } - -(* First run : register [mach] under name [custom]. - Second run : - - register [mach] under name [custom] again. This must work. - - then register [mach2] under name [custom]. This must result in an error. -*) -let () = - let ran = ref false in - Cmdline.run_after_loading_stage - (fun () -> - Kernel.result "Registering machdep 'mach' as 'custom'"; - File.new_machdep "custom" mach; - if !ran then begin - Kernel.result "Trying to register machdep 'mach2' as 'custom'"; - File.new_machdep "custom" mach2 - end - else ran := true - ) diff --git a/tests/misc/custom_machdep.yaml b/tests/misc/custom_machdep.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7872b93e4ddd025199dbcedd0a868d908bc8909a --- /dev/null +++ b/tests/misc/custom_machdep.yaml @@ -0,0 +1,80 @@ +alignof_aligned: 16 +alignof_double: 4 +alignof_float: 4 +alignof_fun: 1 +alignof_int: 3 +alignof_long: 4 +alignof_longdouble: 4 +alignof_longlong: 4 +alignof_ptr: 4 +alignof_short: 2 +alignof_str: 1 +char_is_unsigned: false +compiler: bar +cpp_arch_flags: [] +has__builtin_va_list: true +little_endian: true +ptrdiff_t: int +intptr_t: long +uintptr_t: unsigned long +int_fast8_t: signed char +int_fast16_t: long +int_fast32_t: long +int_fast64_t: long long +uint_fast8_t: unsigned char +uint_fast16_t: unsigned long +uint_fast32_t: unsigned long +uint_fast64_t: unsigned long long +wint_t: int +size_t: unsigned long +sizeof_double: 8 +sizeof_float: 4 +sizeof_fun: 1 +sizeof_int: 3 +sizeof_long: 4 +sizeof_longdouble: 12 +sizeof_longlong: 8 +sizeof_ptr: 4 +sizeof_short: 2 +sizeof_void: 1 +ssize_t: long +version: foo +wchar_t: int +weof: (-1) +wordsize: '24' +posix_version: '200809L' +bufsiz: '255' +eof: (-1) +fopen_max: '128' +filename_max: '1023' +l_tmpnam: '255' +tmp_max: '255' +tty_name_max: '255' +host_name_max: '255' +path_max: '256' +rand_max: '0xFFFFFE' +mb_cur_max: '16' +sig_atomic_t: int +time_t: long +nsig: '' +errno: + edom: "33" + eilseq: "84" + erange: "34" + eintr: "35" + eagain: "36" + ebadf: "37" + efbig: "38" + einval: "39" + eio: "40" + enospc: "41" + eoverflow: "42" + epipe: "43" + espipe: "44" + enxio: "45" + emfile: "46" + enomem: "47" + enotsup: "48" +machdep_name: custom_machdep +custom_defs: | + #define CUSTOM_MACHDEP 1 diff --git a/tests/misc/custom_machdep/__fc_machdep_custom.h b/tests/misc/custom_machdep/__fc_machdep_custom.h deleted file mode 100644 index 27db308403368e394b64d739b9ac7e2c9699f936..0000000000000000000000000000000000000000 --- a/tests/misc/custom_machdep/__fc_machdep_custom.h +++ /dev/null @@ -1,243 +0,0 @@ -/* skeleton of a real custom machdep header. - Note: the values provided here are merely for illustrative purposes - and are not necessarily consistent between them. */ -#ifndef __FC_MACHDEP -#define __FC_MACHDEP - -#ifdef __FC_MACHDEP_CUSTOM - -/* Constants required by the C standard */ -#undef __CHAR_UNSIGNED__ -#define __WORDSIZE 32 -#define __SIZEOF_SHORT 2 -#define __SIZEOF_INT 3 -#define __SIZEOF_LONG 4 -#define __SIZEOF_LONGLONG 8 -#define __CHAR_BIT 8 -#define __PTRDIFF_T int -#define __SIZE_T unsigned int - -#define __FC_SCHAR_MIN (-128) -#define __FC_SCHAR_MAX 127 -#define __FC_UCHAR_MAX 255 -#define __FC_SHRT_MIN (-32768) -#define __FC_SHRT_MAX 32767 -#define __FC_USHRT_MAX 65535 -#define __FC_INT_MIN (-2147483647 - 1) -#define __FC_INT_MAX 2147483647 -#define __FC_UINT_MAX 4294967295U -#define __FC_LONG_MIN (-2147483647L -1L) -#define __FC_LONG_MAX 2147483647L -#define __FC_ULONG_MAX 4294967295UL -#define __FC_LLONG_MIN (-9223372036854775807LL -1LL) -#define __FC_LLONG_MAX 9223372036854775807LL -#define __FC_ULLONG_MAX 18446744073709551615ULL - -#define __INT_MAX_T signed long long -#define __UINT_MAX_T unsigned long long - -#define __FC_PATH_MAX 256 -#define __FC_SIZE_MAX __FC_ULLONG_MAX - -/* Optional constants */ -#define __INT8_T signed char -#define __UINT8_T unsigned char -#define __INT16_T signed short -#define __UINT16_T unsigned short - -#define __INTPTR_T signed long -#define __UINTPTR_T unsigned long -#define __INT32_T signed long -#define __UINT32_T unsigned long -#define __INT64_T signed long long -#define __UINT64_T unsigned long long - -/* Required constants */ -#define __INT_LEAST8_T signed char -#define __UINT_LEAST8_T unsigned char -#define __INT_LEAST16_T signed short -#define __UINT_LEAST16_T unsigned short -#define __INT_LEAST32_T signed long -#define __UINT_LEAST32_T unsigned long -#define __INT_LEAST64_T signed long long -#define __UINT_LEAST64_T unsigned long long - -#define __INT_FAST8_T signed char -#define __UINT_FAST8_T unsigned char -#define __INT_FAST16_T signed int -#define __UINT_FAST16_T unsigned int -#define __INT_FAST32_T signed long -#define __UINT_FAST32_T unsigned long -#define __INT_FAST64_T signed long long -#define __UINT_FAST64_T unsigned long long - - -/* 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 -#define __FC_INTMAX_MIN (-9223372036854775807LL -1LL) -#define __FC_INTMAX_MAX 9223372036854775807LL -#define __FC_UINTMAX_MAX 18446744073709551615ULL - -#define __FC_EOF (-1) -#define __FC_FOPEN_MAX 20 -#define __FC_RAND_MAX 32767 -#define __WCHAR_T unsigned short - -/* for stdarg.h */ -#define __FC_VA_LIST_T char* - -/* for time.h */ -#define __FC_TIME_T long - -/* for wchar.h */ -#define __WINT_T unsigned int -#define __FC_WEOF (0xFFFFFFFFU) -#define __FC_WINT_MIN 0 -#define __FC_WINT_MAX __FC_UINT_MAX - -/* for errno.h */ - -#define __FC_EPERM 1 -#define __FC_ENOENT 2 -#define __FC_ESRCH 3 -#define __FC_EINTR 4 -#define __FC_EIO 5 -#define __FC_ENXIO 6 -#define __FC_E2BIG 7 -#define __FC_ENOEXEC 8 -#define __FC_EBADF 9 -#define __FC_ECHILD 10 -#define __FC_EAGAIN 11 -#define __FC_ENOMEM 12 -#define __FC_EACCES 13 -#define __FC_EFAULT 14 -#define __FC_ENOTBLK 15 -#define __FC_EBUSY 16 -#define __FC_EEXIST 17 -#define __FC_EXDEV 18 -#define __FC_ENODEV 19 -#define __FC_ENOTDIR 20 -#define __FC_EISDIR 21 -#define __FC_EINVAL 22 -#define __FC_ENFILE 23 -#define __FC_EMFILE 24 -#define __FC_ENOTTY 25 -#define __FC_ETXTBSY 26 -#define __FC_EFBIG 27 -#define __FC_ENOSPC 28 -#define __FC_ESPIPE 29 -#define __FC_EROFS 30 -#define __FC_EMLINK 31 -#define __FC_EPIPE 32 -#define __FC_EDOM 33 -#define __FC_ERANGE 34 -#define __FC_EDEADLK 35 -#define __FC_ENAMETOOLONG 36 -#define __FC_ENOLCK 37 -#define __FC_ENOSYS 38 -#define __FC_ENOTEMPTY 39 -#define __FC_ELOOP 40 -#define __FC_EWOULDBLOCK EAGAIN -#define __FC_ENOMSG 42 -#define __FC_EIDRM 43 -#define __FC_ECHRNG 44 -#define __FC_EL2NSYNC 45 -#define __FC_EL3HLT 46 -#define __FC_EL3RST 47 -#define __FC_ELNRNG 48 -#define __FC_EUNATCH 49 -#define __FC_ENOCSI 50 -#define __FC_EL2HLT 51 -#define __FC_EBADE 52 -#define __FC_EBADR 53 -#define __FC_EXFULL 54 -#define __FC_ENOANO 55 -#define __FC_EBADRQC 56 -#define __FC_EBADSLT 57 -#define __FC_EDEADLOCK EDEADLK -#define __FC_EBFONT 59 -#define __FC_ENOSTR 60 -#define __FC_ENODATA 61 -#define __FC_ETIME 62 -#define __FC_ENOSR 63 -#define __FC_ENONET 64 -#define __FC_ENOPKG 65 -#define __FC_EREMOTE 66 -#define __FC_ENOLINK 67 -#define __FC_EADV 68 -#define __FC_ESRMNT 69 -#define __FC_ECOMM 70 -#define __FC_EPROTO 71 -#define __FC_EMULTIHOP 72 -#define __FC_EDOTDOT 73 -#define __FC_EBADMSG 74 -#define __FC_EOVERFLOW 75 -#define __FC_ENOTUNIQ 76 -#define __FC_EBADFD 77 -#define __FC_EREMCHG 78 -#define __FC_ELIBACC 79 -#define __FC_ELIBBAD 80 -#define __FC_ELIBSCN 81 -#define __FC_ELIBMAX 82 -#define __FC_ELIBEXEC 83 -#define __FC_EILSEQ 84 -#define __FC_ERESTART 85 -#define __FC_ESTRPIPE 86 -#define __FC_EUSERS 87 -#define __FC_ENOTSOCK 88 -#define __FC_EDESTADDRREQ 89 -#define __FC_EMSGSIZE 90 -#define __FC_EPROTOTYPE 91 -#define __FC_ENOPROTOOPT 92 -#define __FC_EPROTONOSUPPORT 93 -#define __FC_ESOCKTNOSUPPORT 94 -#define __FC_ENOTSUP 95 -#define __FC_EOPNOTSUPP 95 -#define __FC_EPFNOSUPPORT 96 -#define __FC_EAFNOSUPPORT 97 -#define __FC_EADDRINUSE 98 -#define __FC_EADDRNOTAVAIL 99 -#define __FC_ENETDOWN 100 -#define __FC_ENETUNREACH 101 -#define __FC_ENETRESET 102 -#define __FC_ECONNABORTED 103 -#define __FC_ECONNRESET 104 -#define __FC_ENOBUFS 105 -#define __FC_EISCONN 106 -#define __FC_ENOTCONN 107 -#define __FC_ESHUTDOWN 108 -#define __FC_ETOOMANYREFS 109 -#define __FC_ETIMEDOUT 110 -#define __FC_ECONNREFUSED 111 -#define __FC_EHOSTDOWN 112 -#define __FC_EHOSTUNREACH 113 -#define __FC_EALREADY 114 -#define __FC_EINPROGRESS 115 -#define __FC_ESTALE 116 -#define __FC_EUCLEAN 117 -#define __FC_ENOTNAM 118 -#define __FC_ENAVAIL 119 -#define __FC_EISNAM 120 -#define __FC_EREMOTEIO 121 -#define __FC_EDQUOT 122 -#define __FC_ENOMEDIUM 123 -#define __FC_EMEDIUMTYPE 124 -#define __FC_ECANCELED 125 -#define __FC_ENOKEY 126 -#define __FC_EKEYEXPIRED 127 -#define __FC_EKEYREVOKED 128 -#define __FC_EKEYREJECTED 129 -#define __FC_EOWNERDEAD 130 -#define __FC_ENOTRECOVERABLE 131 -#define __FC_ERFKILL 132 -#define __FC_EHWPOISON 133 - -#else - error "I'm supposed to be called with __FC_MACHDEP_CUSTOM macro defined" -#endif -#endif diff --git a/tests/misc/dune b/tests/misc/dune deleted file mode 100644 index 350ae7160b3c799e3d13271dd4342fb7e90279c8..0000000000000000000000000000000000000000 --- a/tests/misc/dune +++ /dev/null @@ -1,3 +0,0 @@ -(subdir - result/custom_machdep - (copy_files ../../custom_machdep/*)) diff --git a/tests/misc/oracle/custom_machdep.res.oracle b/tests/misc/oracle/custom_machdep.res.oracle index dfa8454076f143b1f9a7fd8f5d71a56519f74ab5..85375c33f5000a97731ffc41e079abbdfb50a323 100644 --- a/tests/misc/oracle/custom_machdep.res.oracle +++ b/tests/misc/oracle/custom_machdep.res.oracle @@ -1,4 +1,3 @@ -[kernel] Registering machdep 'mach' as 'custom' [kernel] Parsing custom_machdep.c (with preprocessing) /* Generated by Frama-C */ #include "ctype.h" @@ -19,12 +18,8 @@ int main(void) { int __retres; - __retres = (int)2147483647; + __retres = 8388607 - 1; return __retres; } -[kernel] Registering machdep 'mach' as 'custom' -[kernel] Trying to register machdep 'mach2' as 'custom' -[kernel] User Error: trying to register incompatible machdeps under name `custom' -[kernel] Frama-C aborted: invalid user input. diff --git a/tests/misc/oracle/print_machdep.res.oracle b/tests/misc/oracle/print_machdep.res.oracle index 7c9a04850ea7f793b0235931ec0b95c651c2cead..b1566c66852eb15e98254fa0cfbaaf4a89ee1885 100644 --- a/tests/misc/oracle/print_machdep.res.oracle +++ b/tests/misc/oracle/print_machdep.res.oracle @@ -1,4 +1,4 @@ -Machine: gcc 4.0.3 AMD64 +Machine: gcc (GCC) 13.1.1 20230429 sizeof short = 2 (16 bits, aligned on 16 bits) sizeof int = 4 (32 bits, aligned on 32 bits) sizeof long = 8 (64 bits, aligned on 64 bits) @@ -14,6 +14,4 @@ Machine: gcc 4.0.3 AMD64 typeof ptrdiff_t = long char is signed machine is little endian - strings are const chars - assembly names have no leading '_' compiler has builtin __va_list diff --git a/tests/misc/oracle/stdint.0.res.oracle b/tests/misc/oracle/stdint.0.res.oracle index 361bf0a731d25c48a5968997fe52adc755984705..09ab5559b6a1fc7f710aa034c89d37e44aa0c611 100644 --- a/tests/misc/oracle/stdint.0.res.oracle +++ b/tests/misc/oracle/stdint.0.res.oracle @@ -1,16 +1,16 @@ [kernel] Parsing stdint.i (no preprocessing) [kernel] stdint.i:10: Warning: - bad type 'int' (16 bits) for typedef 'int8_t'; + bad type 'int' (16 bits) for typedef 'int8_t' using machdep machdep_x86_16; check for mismatch between -machdep flag and headers used [kernel] stdint.i:11: Warning: - bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t'; + bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t' using machdep machdep_x86_16; check for mismatch between -machdep flag and headers used [kernel] stdint.i:12: Warning: - bad type 'short' (16 bits) for typedef 'int_fast32_t'; + bad type 'short' (16 bits) for typedef 'int_fast32_t' using machdep machdep_x86_16; check for mismatch between -machdep flag and headers used [kernel] stdint.i:13: Warning: - bad type 'char' (8 bits) for typedef 'intptr_t'; + bad type 'char' (8 bits) for typedef 'intptr_t' using machdep machdep_x86_16; check for mismatch between -machdep flag and headers used [kernel] stdint.i:14: Warning: - bad type 'unsigned short' (16 bits) for typedef 'uintmax_t'; + bad type 'unsigned short' (16 bits) for typedef 'uintmax_t' using machdep machdep_x86_16; check for mismatch between -machdep flag and headers used diff --git a/tests/misc/oracle/stdint.1.res.oracle b/tests/misc/oracle/stdint.1.res.oracle index f293275aad7449242b56d10e4cc386e2970208e7..1bcb5d7a0942a3a28924e4678f5271d44dc3df45 100644 --- a/tests/misc/oracle/stdint.1.res.oracle +++ b/tests/misc/oracle/stdint.1.res.oracle @@ -1,16 +1,16 @@ [kernel] Parsing stdint.i (no preprocessing) [kernel] stdint.i:10: Warning: - bad type 'int' (32 bits) for typedef 'int8_t'; + bad type 'int' (32 bits) for typedef 'int8_t' using machdep machdep_ppc_32; check for mismatch between -machdep flag and headers used [kernel] stdint.i:11: Warning: - bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t'; + bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t' using machdep machdep_ppc_32; check for mismatch between -machdep flag and headers used [kernel] stdint.i:12: Warning: - bad type 'short' (16 bits) for typedef 'int_fast32_t'; + bad type 'short' (16 bits) for typedef 'int_fast32_t' using machdep machdep_ppc_32; check for mismatch between -machdep flag and headers used [kernel] stdint.i:13: Warning: - bad type 'char' (8 bits) for typedef 'intptr_t'; + bad type 'char' (8 bits) for typedef 'intptr_t' using machdep machdep_ppc_32; check for mismatch between -machdep flag and headers used [kernel] stdint.i:14: Warning: - bad type 'unsigned short' (16 bits) for typedef 'uintmax_t'; + bad type 'unsigned short' (16 bits) for typedef 'uintmax_t' using machdep machdep_ppc_32; check for mismatch between -machdep flag and headers used diff --git a/tests/misc/oracle/stdint.2.res.oracle b/tests/misc/oracle/stdint.2.res.oracle index f293275aad7449242b56d10e4cc386e2970208e7..7079c2fcd815cc8fae3a25d4b682b71360475c24 100644 --- a/tests/misc/oracle/stdint.2.res.oracle +++ b/tests/misc/oracle/stdint.2.res.oracle @@ -1,16 +1,16 @@ [kernel] Parsing stdint.i (no preprocessing) [kernel] stdint.i:10: Warning: - bad type 'int' (32 bits) for typedef 'int8_t'; + bad type 'int' (32 bits) for typedef 'int8_t' using machdep machdep_msvc_x86_64; check for mismatch between -machdep flag and headers used [kernel] stdint.i:11: Warning: - bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t'; + bad type 'unsigned char' (8 bits) for typedef 'uint_least64_t' using machdep machdep_msvc_x86_64; check for mismatch between -machdep flag and headers used [kernel] stdint.i:12: Warning: - bad type 'short' (16 bits) for typedef 'int_fast32_t'; + bad type 'short' (16 bits) for typedef 'int_fast32_t' using machdep machdep_msvc_x86_64; check for mismatch between -machdep flag and headers used [kernel] stdint.i:13: Warning: - bad type 'char' (8 bits) for typedef 'intptr_t'; + bad type 'char' (8 bits) for typedef 'intptr_t' using machdep machdep_msvc_x86_64; check for mismatch between -machdep flag and headers used [kernel] stdint.i:14: Warning: - bad type 'unsigned short' (16 bits) for typedef 'uintmax_t'; + bad type 'unsigned short' (16 bits) for typedef 'uintmax_t' using machdep machdep_msvc_x86_64; check for mismatch between -machdep flag and headers used diff --git a/tests/pretty_printing/test_config b/tests/pretty_printing/test_config index 5feb4989bf0a2bfd00639668a9521d46037895a4..ada89b488ceb4a09d2ed04c6e273ab0c6c3e99ad 100644 --- a/tests/pretty_printing/test_config +++ b/tests/pretty_printing/test_config @@ -2,5 +2,4 @@ COMMENT: this directory is meant to test the parser and pretty-printer COMMENT: the default option checks that pretty-printed code can be merged COMMENT: with the original one PLUGIN: -CMD: FRAMAC_PLUGIN=tests/.empty @frama-c@ OPT: @PTEST_FILE@ -print -then -ocode ./ocode_@PTEST_NAME@.c -print -then ./ocode_@PTEST_NAME@.c @PTEST_FILE@ -ocode="" -print diff --git a/tests/spec/array_conversion.c b/tests/spec/array_conversion.c index 930e58c457654fb23a1400d44a7feb03e0957548..3313cb3ecb8d72c3445d3060cb51a19660a4e106 100644 --- a/tests/spec/array_conversion.c +++ b/tests/spec/array_conversion.c @@ -36,3 +36,7 @@ void ftest(void) { //@ lemma array_not_null: a != \null; + +int const ca[1] = { 0 }; + +//@ lemma const_array_init: \initialized(&ca[0]); diff --git a/tests/spec/oracle/array_conversion.res.oracle b/tests/spec/oracle/array_conversion.res.oracle index cdcd418791e268f2b97577be9be119b4cbb946c9..891a21b5b85b66a02e901e2df8adc8e946d06af3 100644 --- a/tests/spec/oracle/array_conversion.res.oracle +++ b/tests/spec/oracle/array_conversion.res.oracle @@ -45,6 +45,9 @@ void ftest(void) } /*@ lemma array_not_null{L}: (int *)a ≢ \null; + */ +int const ca[1] = {0}; +/*@ lemma const_array_init{L}: \initialized((int const *)ca); */ diff --git a/tests/spec/oracle/ghost_array.res.oracle b/tests/spec/oracle/ghost_array.res.oracle index 1b05dae72afda76b43e3679db1a3fa5dfa8a1bba..1681b804dd43e4d472f4a5e213b77e3487475860 100644 --- a/tests/spec/oracle/ghost_array.res.oracle +++ b/tests/spec/oracle/ghost_array.res.oracle @@ -10,8 +10,8 @@ uint32 s[2]; /*@ predicate equal_t_s{L}(ℤ i) = \at(t[i] ≡ - (unsigned long const)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡ - *(((uint8 *)((uint32 *)s) + i) + 1))), + (unsigned long)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡ + *(((uint8 *)((uint32 *)s) + i) + 1))), L); */ uint8 Array[10]; @@ -23,10 +23,9 @@ predicate mypredl{L}= ∀ ℤ MyNum; 0 ≤ MyNum < FCG_Number ⇒ FCG_Var2[MyNum] ≡ - (unsigned long \ghost)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1)) - * 256 + - *((uint8 *)((&Array[FCG_Var1[MyNum]] + - (1 + 2)) - + 1)))); + (unsigned long)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1)) * 256 + + + *((uint8 *)((&Array[FCG_Var1[MyNum]] + (1 + 2)) + + 1)))); */ diff --git a/tests/spec/oracle/ghost_array_pretty.c b/tests/spec/oracle/ghost_array_pretty.c index 658b0f698a998b028f103de603f45cb5a27ca61f..b02d5fd80ff35ac08f02a0e58ac2066c8e6ca5cb 100644 --- a/tests/spec/oracle/ghost_array_pretty.c +++ b/tests/spec/oracle/ghost_array_pretty.c @@ -8,8 +8,8 @@ uint32 s[2]; /*@ predicate equal_t_s{L}(ℤ i) = \at(t[i] ≡ - (unsigned long const)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡ - *(((uint8 *)((uint32 *)s) + i) + 1))), + (unsigned long)((uint16)(*((uint8 *)((uint32 *)s) + i) ≡ + *(((uint8 *)((uint32 *)s) + i) + 1))), L); */ uint8 Array[10]; @@ -21,10 +21,9 @@ predicate mypredl{L}= ∀ ℤ MyNum; 0 ≤ MyNum < FCG_Number ⇒ FCG_Var2[MyNum] ≡ - (unsigned long \ghost)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1)) - * 256 + - *((uint8 *)((&Array[FCG_Var1[MyNum]] + - (1 + 2)) - + 1)))); + (unsigned long)((uint16)(*((uint8 *)(&Array[FCG_Var1[MyNum]] + 1)) * 256 + + + *((uint8 *)((&Array[FCG_Var1[MyNum]] + (1 + 2)) + + 1)))); */ diff --git a/tests/spec/oracle/kw.res.oracle b/tests/spec/oracle/kw.res.oracle index 8b6bdc8c2cc9b20df7e9ad0f3a7725e26d9855f8..cdc7824e878babe57e329155cace996037d20b38 100644 --- a/tests/spec/oracle/kw.res.oracle +++ b/tests/spec/oracle/kw.res.oracle @@ -30,7 +30,7 @@ int main(void) struct custom writes; struct at include; struct loop assert; - /*@ slevel 4; */ + /*@ slevel 4; */ ; behavior ++; /*@ assert diff --git a/tests/spec/oracle/polymorphic_inductive.res.oracle b/tests/spec/oracle/polymorphic_inductive.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f003162d035a68df660507c0df1a4a579ca6e527 --- /dev/null +++ b/tests/spec/oracle/polymorphic_inductive.res.oracle @@ -0,0 +1,8 @@ +[kernel] Parsing polymorphic_inductive.i (no preprocessing) +/* Generated by Frama-C */ +/*@ +inductive P<A>(A i, \list<A> s) { + case one<A>: ∀ A a, \list<A> s; \Cons(a, s) ≡ [| a |] ⇒ P(a, s); + } + */ + diff --git a/tests/spec/polymorphic_inductive.i b/tests/spec/polymorphic_inductive.i new file mode 100644 index 0000000000000000000000000000000000000000..c972f6c494a69c7129bc8a8e72fce8c64591f51f --- /dev/null +++ b/tests/spec/polymorphic_inductive.i @@ -0,0 +1,5 @@ +/*@ inductive P<A>(A i, \list<A> s){ + case one<A>: + \forall A a, \list<A> s ; \Cons(a, s) == [| a |] ==> P(a, s); + } +*/ diff --git a/tests/spec/property_test.ml b/tests/spec/property_test.ml index 00407c161ac46f53abe7aa0ccd0f38fc3d5a203d..9088cf306802455e82893b4042ccd39921790e5c 100644 --- a/tests/spec/property_test.ml +++ b/tests/spec/property_test.ml @@ -10,9 +10,9 @@ class visit prj = method! vbehavior b = let kf = Option.get self#current_kf in if Kernel_function.get_name kf = "main" then begin - let x = Globals.Vars.find_from_astinfo "X" VGlobal in + let x = Globals.Vars.find_from_astinfo "X" Global in let x = Cil.cvar_to_lvar x in - let c = Globals.Vars.find_from_astinfo "c" (VFormal kf) in + let c = Globals.Vars.find_from_astinfo "c" (Formal kf) in let c = Cil.cvar_to_lvar c in b.b_assigns <- Writes diff --git a/tests/syntax/assembly_gmp.c b/tests/syntax/assembly_gmp.c index 0d39854c42ebfe3febd235f71c57c8f1622c99ba..fb707e0976786536b638ca7bb56e24bddab1e60b 100644 --- a/tests/syntax/assembly_gmp.c +++ b/tests/syntax/assembly_gmp.c @@ -86,7 +86,7 @@ File modified by CEA LIST for inclusion in Frama-C test suite #endif #ifndef add_mssaaaa -#error "This test must run with machdep equals to x86_32, x86_64 or ppc_32" +#error "This test must run with machdep equals to gcc_x86_32, gcc_x86_64, or ppc_32" #endif #define umul_ppmm(ph, pl, m0, m1) \ diff --git a/tests/syntax/char_is_unsigned.i b/tests/syntax/char_is_unsigned.i index 02a2088fef3e3a4aa038f1bd41a176bd45e36cf1..e5a954b1ed03f0e50ec53ee0ba233ed5cd3070d7 100644 --- a/tests/syntax/char_is_unsigned.i +++ b/tests/syntax/char_is_unsigned.i @@ -1,7 +1,6 @@ /* run.config PLUGIN: rtegen - MODULE: machdep_char_unsigned - OPT: -print -machdep unsigned_char -then -constfold -rte + OPT: -print -machdep %{dep:@PTEST_DIR@/machdep_char_unsigned.yaml} -then -constfold -rte */ char t[10]; diff --git a/tests/syntax/cpp-command.c b/tests/syntax/cpp-command.c index af14a03a707cf3bfb577e1cbdbd80ce4e5c0eecb..5d0140181679d20deb6837e16bd854a804dc757e 100644 --- a/tests/syntax/cpp-command.c +++ b/tests/syntax/cpp-command.c @@ -1,5 +1,5 @@ /* run.config* - FILTER: sed "s:/[^ ]*[/]cpp-command\.[^ ]*\.i:TMPDIR/FILE.i:g; s:$PWD/::g; s:$(realpath @FRAMAC_SHARE@)/:FRAMAC_SHARE/:g; s:@PTEST_MAKE_DIR@/result@PTEST_CONFIG@/::g; s: -m32::; s: -m64::" + FILTER: sed "s:/[^ ]*[/]cpp-command\.[^ ]*\.i:TMPDIR/FILE.i:g; s:[^ ]*[/]__fc_machdep.*\.dir:-ITMP_MACHDEP:g; s:$PWD/::g; s:$(realpath @FRAMAC_SHARE@)/:FRAMAC_SHARE/:g; s:@PTEST_MAKE_DIR@/result@PTEST_CONFIG@/::g; s: -m32::; s: -m64::" OPT: -machdep x86_32 -cpp-frama-c-compliant -cpp-command "echo [\$(basename '%1') \$(basename '%1') \$(basename '%i') \$(basename '%input')] ['%2' '%2' '%o' '%output'] ['%args']" OPT: -machdep x86_32 -cpp-frama-c-compliant -cpp-command "echo %%1 = \$(basename '%1') %%2 = '%2' %%args = '%args'" OPT: -machdep x86_32 -cpp-frama-c-compliant -cpp-command "printf \"%s\n\" \"using \\% has no effect : \$(basename \"\%input\")\"" diff --git a/tests/syntax/get_astinfo_bts1136.ml b/tests/syntax/get_astinfo_bts1136.ml index 98c338bf7c935b57c284e2392d2380a4460982b8..e842f7e046d687f023eca1e6c8563c03d6d33ccf 100644 --- a/tests/syntax/get_astinfo_bts1136.ml +++ b/tests/syntax/get_astinfo_bts1136.ml @@ -2,7 +2,7 @@ let get_formal_variables name = let add_kf_vars kf vars = try - let v = Globals.Vars.find_from_astinfo name (Cil_types.VFormal kf) in + let v = Globals.Vars.find_from_astinfo name (Cil_types.Formal kf) in Format.printf "found variable vid:%d formal in %a@." v.Cil_types.vid Cil_datatype.Kf.pretty kf; v::vars @@ -14,7 +14,8 @@ let get_formal_variables name = let get_local_variables name = let add_kf_vars kf vars = try - let v = Globals.Vars.find_from_astinfo name (Cil_types.VLocal kf) in + let v = Globals.Vars.find_from_astinfo name (Cil_types.Whole_function kf) + in Format.printf "found variable vid:%d formal in %a@." v.Cil_types.vid Cil_datatype.Kf.pretty kf; v::vars @@ -30,16 +31,9 @@ let main () = let vars = get_formal_variables "x" in let vars' = get_local_variables "y" in let do_v v = - let pp_kind fmt kind = match kind with - | Cil_types.VGlobal -> Format.fprintf fmt "global" - | Cil_types.VFormal kf -> - Format.fprintf fmt "formal in %a" Cil_datatype.Kf.pretty kf - | Cil_types.VLocal kf -> - Format.fprintf fmt "local in %a" Cil_datatype.Kf.pretty kf - in let _, kind = Globals.Vars.get_astinfo v in Format.printf "[do_v] vid:%d %a@." v.Cil_types.vid - (* Cil_datatype.Localisation.pretty *) pp_kind kind + Cil_datatype.Syntactic_scope.pretty kind in List.iter do_v vars; List.iter do_v vars' let () = Db.Main.extend main diff --git a/tests/syntax/machdep_char_unsigned.ml b/tests/syntax/machdep_char_unsigned.ml index 2e0a28c35f4145122f84813999c726cd0315ffb3..034b0ca6fe72d47b36ca1056bd8b8297d424a59e 100644 --- a/tests/syntax/machdep_char_unsigned.ml +++ b/tests/syntax/machdep_char_unsigned.ml @@ -1,4 +1,3 @@ - open Cil_types let md = { @@ -27,13 +26,47 @@ let md = { alignof_fun = 0; alignof_aligned= 0; char_is_unsigned = true; - const_string_literals = true; little_endian = true; - underscore_name = true ; size_t = "unsigned int"; + ssize_t = "int"; wchar_t = "int"; + intptr_t = "int"; + uintptr_t = "unsigned int"; + int_fast8_t = "signed char"; + int_fast16_t = "long"; + int_fast32_t = "long"; + int_fast64_t = "long"; + uint_fast8_t = "unsigned char"; + uint_fast16_t = "unsigned long"; + uint_fast32_t = "unsigned long"; + uint_fast64_t = "usigned long"; ptrdiff_t = "int"; + wint_t = "long"; + sig_atomic_t = "int"; + time_t = "long"; has__builtin_va_list = true; + weof = "(-1L)"; + wordsize = "16"; + posix_version = ""; + bufsiz = "8192"; + eof = "(-1)"; + fopen_max = "16"; + host_name_max = "255"; + tty_name_max = "255"; + path_max = "255"; + filename_max = "2048"; + l_tmpnam = "2048"; + tmp_max = "0xFFFFFFFF"; + rand_max = "0xFFFFFFFE"; + mb_cur_max = "16"; + nsig = "64"; + errno = [ + "edom", "33"; + "eilseq", "84"; + "erange", "34"; + ]; + machdep_name = "machdep_char_unsigned"; + custom_defs = ""; } let () = diff --git a/tests/syntax/machdep_char_unsigned.yaml b/tests/syntax/machdep_char_unsigned.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cb4fbd6b6c6a360e076860b4e71b5794c463e17b --- /dev/null +++ b/tests/syntax/machdep_char_unsigned.yaml @@ -0,0 +1,183 @@ +alignof_aligned: 0 +alignof_short: 2 +compiler: gcc +version: 'N/A' +cpp_arch_flags: +- -m32 +sizeof_short: 2 +sizeof_int: 2 +sizeof_long: 4 +sizeof_longlong: 8 +sizeof_ptr: 4 +sizeof_float: 4 +sizeof_double: 8 +sizeof_longdouble: 8 +sizeof_void: -1 +sizeof_fun: 0 +alignof_int: 2 +alignof_long: 2 +alignof_longlong: 2 +alignof_ptr: 2 +alignof_float: 2 +alignof_double: 2 +alignof_longdouble: 2 +alignof_str: 0 +alignof_fun: 0 +char_is_unsigned: true +little_endian: true +size_t: 'unsigned int' +ssize_t: 'int' +wchar_t: 'int' +intptr_t: 'int' +uintptr_t: 'unsigned int' +int_fast8_t: 'signed char' +int_fast16_t: 'long' +int_fast32_t: 'long' +int_fast64_t: 'long' +uint_fast8_t: 'unsigned char' +uint_fast16_t: 'unsigned long' +uint_fast32_t: 'unsigned long' +uint_fast64_t: 'unsigned long' +ptrdiff_t: 'int' +wint_t: 'long' +sig_atomic_t: 'int' +time_t: 'long' +has__builtin_va_list: true +weof: '(-1L)' +wordsize: '16' +posix_version: '' +bufsiz: '8192' +eof: '(-1)' +fopen_max: '16' +host_name_max: '255' +tty_name_max: '255' +path_max: '255' +filename_max: '2048' +l_tmpnam: '2048' +tmp_max: '0xFFFFFFFF' +rand_max: '0xFFFFFFFE' +mb_cur_max: '16' +nsig: '64' +errno: + e2big: '7' + eacces: '13' + eaddrinuse: '98' + eaddrnotavail: '99' + eafnosupport: '97' + eagain: '11' + ealready: '114' + ebade: '52' + ebadf: '9' + ebadfd: '77' + ebadmsg: '74' + ebadr: '53' + ebadrqc: '56' + ebadslt: '57' + ebusy: '16' + ecanceled: '125' + echild: '10' + echrng: '44' + ecomm: '70' + econnaborted: '103' + econnrefused: '111' + econnreset: '104' + edeadlk: '35' + edeadlock: '35' + edestaddrreq: '89' + edom: '33' + edquot: '122' + eexist: '17' + efault: '14' + efbig: '27' + ehostdown: '112' + ehostunreach: '113' + eidrm: '43' + eilseq: '84' + einprogress: '115' + eintr: '4' + einval: '22' + eio: '5' + eisconn: '106' + eisdir: '21' + eisnam: '120' + ekeyexpired: '127' + ekeyrejected: '129' + ekeyrevoked: '128' + el2hlt: '51' + el2nsync: '45' + el3hlt: '46' + el3rst: '47' + elibacc: '79' + elibbad: '80' + elibexec: '83' + elibmax: '82' + elibscn: '81' + eloop: '40' + emediumtype: '124' + emfile: '24' + emlink: '31' + emsgsize: '90' + emultihop: '72' + enametoolong: '36' + enetdown: '100' + enetreset: '102' + enetunreach: '101' + enfile: '23' + enobufs: '105' + enodata: '61' + enodev: '19' + enoent: '2' + enoexec: '8' + enokey: '126' + enolck: '37' + enolink: '67' + enomedium: '123' + enomem: '12' + enomsg: '42' + enonet: '64' + enopkg: '65' + enoprotoopt: '92' + enospc: '28' + enosr: '63' + enostr: '60' + enosys: '38' + enotblk: '15' + enotconn: '107' + enotdir: '20' + enotempty: '39' + enotsock: '88' + enotsup: '95' + enotty: '25' + enotuniq: '76' + enxio: '6' + eopnotsupp: '95' + eoverflow: '75' + eperm: '1' + epfnosupport: '96' + epipe: '32' + eproto: '71' + eprotonosupport: '93' + eprototype: '91' + erange: '34' + eremchg: '78' + eremote: '66' + eremoteio: '121' + erestart: '85' + erofs: '30' + eshutdown: '108' + esocktnosupport: '94' + espipe: '29' + esrch: '3' + estale: '116' + estrpipe: '86' + etime: '62' + etimedout: '110' + etxtbsy: '26' + euclean: '117' + eunatch: '49' + eusers: '87' + ewouldblock: '11' + exdev: '18' + exfull: '54' +machdep_name: 'machdep_char_unsigned' +custom_defs: '' diff --git a/tests/syntax/oracle/cpp-command.0.res.oracle b/tests/syntax/oracle/cpp-command.0.res.oracle index e10baa0dfad5c10cedc7a23bc926b110277f5129..914862fa5a3192563071d1233952c09acfbf8ef5 100644 --- a/tests/syntax/oracle/cpp-command.0.res.oracle +++ b/tests/syntax/oracle/cpp-command.0.res.oracle @@ -1,2 +1,2 @@ [kernel] Parsing cpp-command.c (with preprocessing) -[cpp-command.c cpp-command.c cpp-command.c cpp-command.c] [TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i] [-IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_32 -dD -nostdinc] +[cpp-command.c cpp-command.c cpp-command.c cpp-command.c] [TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i TMPDIR/FILE.i] -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc] diff --git a/tests/syntax/oracle/cpp-command.1.res.oracle b/tests/syntax/oracle/cpp-command.1.res.oracle index f0b357a6deb2d9063b3f13d79524c9699c7237c7..6d8ee3a2017974d5b635775c02a3cf7abc5928fd 100644 --- a/tests/syntax/oracle/cpp-command.1.res.oracle +++ b/tests/syntax/oracle/cpp-command.1.res.oracle @@ -1,2 +1,2 @@ [kernel] Parsing cpp-command.c (with preprocessing) -%1 = cpp-command.c %2 = TMPDIR/FILE.i %args = -IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_32 -dD -nostdinc +%1 = cpp-command.c %2 = TMPDIR/FILE.i %args = -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc diff --git a/tests/syntax/oracle/cpp-command.4.res.oracle b/tests/syntax/oracle/cpp-command.4.res.oracle index c53f47b8877f466385ba44e02528ee98be75f667..e42375af42082ed6fd520737d8a4bde16a1b9289 100644 --- a/tests/syntax/oracle/cpp-command.4.res.oracle +++ b/tests/syntax/oracle/cpp-command.4.res.oracle @@ -1,2 +1,2 @@ [kernel] Preprocessing command: - gcc -E -C -I. -IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_32 -dD -nostdinc 'cpp-command.c' -o 'TMPDIR/FILE.i' + gcc -E -C -I. -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc 'cpp-command.c' -o 'TMPDIR/FILE.i' diff --git a/tests/syntax/oracle/cpp-command.6.res.oracle b/tests/syntax/oracle/cpp-command.6.res.oracle index b27c0fedfd6cd125f87b61226d70d164b66d5dbe..ef44555760ec5721b7f94c555e0d657fec0858f6 100644 --- a/tests/syntax/oracle/cpp-command.6.res.oracle +++ b/tests/syntax/oracle/cpp-command.6.res.oracle @@ -1,7 +1,7 @@ [kernel] Warning: your preprocessor is not known to handle option `-nostdinc'. If pre-processing fails because of it, please add -no-cpp-frama-c-compliant option to Frama-C's command-line. If you do not want to see this warning again, explicitly use option -cpp-frama-c-compliant. [kernel] Warning: your preprocessor is not known to handle option `-dD'. If pre-processing fails because of it, please add -no-cpp-frama-c-compliant option to Frama-C's command-line. If you do not want to see this warning again, explicitly use option -cpp-frama-c-compliant. [kernel] Parsing cpp-command.c (with preprocessing) -extra_args: -IFRAMAC_SHARE/libc -D__FRAMAC__ -D__FC_MACHDEP_X86_64 -dD -nostdinc file_extra global_extra +extra_args: -ITMP_MACHDEP -IFRAMAC_SHARE/libc -D__FRAMAC__ -dD -nostdinc file_extra global_extra [kernel] Warning: trying to preprocess annotation with an unknown preprocessor. /* Generated by Frama-C */ diff --git a/tests/syntax/oracle/get_astinfo_bts1136.res.oracle b/tests/syntax/oracle/get_astinfo_bts1136.res.oracle index 4201820cc17bf86f68100ee87549a14636977e5d..9c4b065ef072af884ea981f90301358d6285755b 100644 --- a/tests/syntax/oracle/get_astinfo_bts1136.res.oracle +++ b/tests/syntax/oracle/get_astinfo_bts1136.res.oracle @@ -5,9 +5,9 @@ found variable vid:28 formal in h found variable vid:30 formal in i found variable vid:32 formal in j found variable vid:34 formal in k -[do_v] vid:28 formal in h -[do_v] vid:25 formal in g -[do_v] vid:22 formal in f -[do_v] vid:34 local in k -[do_v] vid:32 local in j -[do_v] vid:30 local in i +[do_v] vid:28 Parameter of h +[do_v] vid:25 Parameter of g +[do_v] vid:22 Parameter of f +[do_v] vid:34 Local variable of k +[do_v] vid:32 Local variable of j +[do_v] vid:30 Local variable of i diff --git a/tests/value/ilevel.c b/tests/value/ilevel.c new file mode 100644 index 0000000000000000000000000000000000000000..cd68ed54ea80a0f2202a7373c2563e064534bfa7 --- /dev/null +++ b/tests/value/ilevel.c @@ -0,0 +1,48 @@ +/* run.config* + PLUGIN: @EVA_MAIN_PLUGINS@ inout,slicing + OPT: -eva @EVA_CONFIG@ -slice-return main -then-on "Slicing export" -eva -eva-ilevel 16 -eva-show-progress -then-on "default" -eva-ilevel 17 -then -eva-ilevel 48 + STDOPT: +"-eva-ilevel 400 -main large_ilevel" +*/ + +// Test in particular that ilevel is by-project, even though it is an ocaml ref + +#include "__fc_builtin.h" + +volatile int nondet; +int i, j, k, l; + +int main () { + do { i = nondet; } + while (! (0 <= i && i < 8)); + + do { j = nondet; } + while (! (0 <= j && j < 17)); + + k = j; + if (k == 16) k = 15; + + l = nondet; + if (nondet) { + //@ assert 0 <= l <= 4; + } else { + //@ assert 6 <= l <= 9; + } + Frama_C_show_each(l); // Possible problem with cache on offsetmap join + + return i+j+k+l; +} + +/* Tests printing large integer sets. */ +void large_ilevel (void) { + int i = Frama_C_interval(0, 10); + int j = nondet ? i : i - 25; + int k = Frama_C_interval(100, 200); + if (k == 128) return; + + int a[11] = {53, 17, 64, 99, 25, 12, 72, 81, 404, 303, -101}; + + int s2 = nondet ? 40 : (nondet ? 41 : 42); + int s1 = a[i]; + + int x = nondet ? (nondet ? j : k) : (nondet ? s1 : s2); +} diff --git a/tests/value/ilevel.i b/tests/value/ilevel.i deleted file mode 100644 index 30aaf6a78b8fe2795a46249604b5e0e6f7028aa7..0000000000000000000000000000000000000000 --- a/tests/value/ilevel.i +++ /dev/null @@ -1,27 +0,0 @@ -/* run.config* - PLUGIN: @EVA_MAIN_PLUGINS@ inout,slicing - OPT: -eva @EVA_CONFIG@ -slice-return main -then-on "Slicing export" -eva -eva-ilevel 16 -eva-show-progress -then-on "default" -eva-ilevel 17 -then -eva-ilevel 48 -*/ -// Test in particular that ilevel is by-project, even though it is an ocaml ref -volatile int v; -int i, j, k, l; -int main () { - do { i = v; } - while (! (0 <= i && i < 8)); - - do { j = v; } - while (! (0 <= j && j < 17)); - - k = j; - if (k == 16) k = 15; - - l = v; - if (v) { - //@ assert 0 <= l <= 4; - } else { - //@ assert 6 <= l <= 9; - } - Frama_C_show_each(l); // Possible problem with cache on offsetmap join - - return i+j+k+l; -} diff --git a/tests/value/octagons-pointers-intermediate.c b/tests/value/octagons-pointers-intermediate.c new file mode 100644 index 0000000000000000000000000000000000000000..624055ae96f6783dc47202f8fc48c29561fd674c --- /dev/null +++ b/tests/value/octagons-pointers-intermediate.c @@ -0,0 +1,49 @@ +/* run.config* + STDOPT: +" -eva-domains equality,octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue -eva-oracle-depth 10" +*/ + +#include <stdint.h> + +typedef struct cmd { + uint16_t cmdLen; + uint8_t cmdCode; +} cmd_t; + +unsigned int const size = 436; +unsigned char buffer[436]; + +volatile char nondet; + +void init () { + for (int i = 0; i < size; i++) { + buffer[i] = nondet; + } +} + +void cmdRead (unsigned char const *cmd, uint16_t cmdLen) { + uint16_t *len = (uint16_t *) cmd; + uint8_t *code = (uint8_t *) (len + 1); + uint32_t *elt1 = (uint32_t *) (code + 1); + uint16_t *elt2 = (uint16_t *) (elt1 + 1); + uint16_t *elt3 = (uint16_t *) (elt2 + 1); + if (cmdLen < sizeof(*code) + sizeof(*elt1) + sizeof(*elt2) + sizeof(*elt3)) + return; + uint8_t c = *code; + uint32_t e1 = *elt1; + uint16_t e2 = *elt2; + uint16_t e3 = *elt3; +} + +void main () { + init (); + unsigned int index = 3; + cmd_t *cmd = (cmd_t *) &buffer[index]; + /*@ loop unroll 1; */ + while ( index + sizeof(cmd->cmdLen) + sizeof(cmd->cmdCode) <= size && + cmd->cmdLen != 0 && + size - index - sizeof(cmd->cmdLen) >= cmd->cmdLen) { + cmdRead(&buffer[index], cmd->cmdLen); + index += cmd->cmdLen + sizeof(cmd->cmdLen); + cmd = (cmd_t *) &buffer[index]; + } +} diff --git a/tests/value/octagons-pointers-simple.c b/tests/value/octagons-pointers-simple.c new file mode 100644 index 0000000000000000000000000000000000000000..13fb7e5e01373438b6e079fdef6a76e62226cb7c --- /dev/null +++ b/tests/value/octagons-pointers-simple.c @@ -0,0 +1,51 @@ +/* run.config* + STDOPT: +"-deterministic -eva-domains equality,octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue -eva-oracle-depth 10" +*/ + +#include <stdint.h> + +typedef struct cmd { + uint16_t cmdLen; + uint8_t cmdCode; +} cmd_t; + +unsigned int const size = 436; +unsigned char buffer[436]; + +volatile char nondet; + +void init () { + for (int i = 0; i < size; i++) { + buffer[i] = nondet; + } +} + +void cmdRead (unsigned char const *cmd, unsigned int cmdLen) { + uint16_t *len = (uint16_t *) cmd; + uint8_t *code = (uint8_t *) (len + 1); + uint32_t *elt1 = (uint32_t *) (code + 1); + uint16_t *elt2 = (uint16_t *) (elt1 + 1); + uint16_t *elt3 = (uint16_t *) (elt2 + 1); + if (cmdLen < sizeof(*code) + sizeof(*elt1) + sizeof(*elt2) + sizeof(*elt3)) + return; + uint8_t c = *code; + uint32_t e1 = *elt1; + uint16_t e2 = *elt2; + uint16_t e3 = *elt3; +} + +void main () { + init (); + unsigned int index = 3; + unsigned int cmdLen; + cmd_t *cmd = (cmd_t *) &buffer[index]; + /*@ loop unroll 1; */ + while ( index + sizeof(cmd->cmdLen) + sizeof(cmd->cmdCode) <= size && + (cmdLen = cmd->cmdLen, cmdLen != 0) && + size - index - sizeof(cmd->cmdLen) >= cmdLen) { + Frama_C_dump_each(); + cmdRead(&buffer[index], cmdLen); + index += cmdLen + sizeof(cmd->cmdLen); + cmd = (cmd_t *) &buffer[index]; + } +} diff --git a/tests/value/octagons-pointers.c b/tests/value/octagons-pointers.c new file mode 100644 index 0000000000000000000000000000000000000000..6eb96783523b29ec75cdb807c294c1069f831bfe --- /dev/null +++ b/tests/value/octagons-pointers.c @@ -0,0 +1,80 @@ +/* run.config* + STDOPT: +"-deterministic -eva-domains equality,octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue -eva-oracle-depth 10" +*/ + +#include <stdint.h> + +typedef struct cmd { + uint16_t cmdLen; + uint8_t cmdCode; +} cmd_t; + +unsigned int const size = 436; +unsigned char buffer[436]; + +volatile char nondet; + +void init () { + for (int i = 0; i < size; i++) { + buffer[i] = nondet; + } +} + +void cmdRead (unsigned char const *cmd) { + uint16_t *len = (uint16_t *) cmd; + uint8_t *code = (uint8_t *) (len + 1); + uint32_t *elt1 = (uint32_t *) (code + 1); // elt1 = cmd + 3 + uint16_t *elt2 = (uint16_t *) (elt1 + 1); + uint16_t *elt3 = (uint16_t *) (elt2 + 1); + if (*len < sizeof(*code) + sizeof(*elt1) + sizeof(*elt2) + sizeof(*elt3)) // cmd->cmdLen >= m + return; + Frama_C_dump_each(); + uint8_t c = *code; + uint32_t e1 = *elt1; + uint16_t e2 = *elt2; + uint16_t e3 = *elt3; +} + +void main () { + init (); + unsigned int index = 3; + cmd_t *cmd = (cmd_t *) &buffer[index]; + /*@ loop unroll 1; */ + while ( index + sizeof(cmd->cmdLen) + sizeof(cmd->cmdCode) <= size && + cmd->cmdLen != 0 && + size - index - sizeof(cmd->cmdLen) >= cmd->cmdLen) { // index <= n - cmd->cmdLen + Frama_C_dump_each(); + cmdRead(&buffer[index]); // cmd = buffer + index + index += cmd->cmdLen + sizeof(cmd->cmdLen); + cmd = (cmd_t *) &buffer[index]; + } +} + +#include "__fc_builtin.h" + +void main2(void) { + int t[10]; + int i = Frama_C_interval(0,9); + int* p = t + i; + + while (p < &t[10]) { + Frama_C_dump_each1(); + *p = 0; + Frama_C_dump_each2(); + p++; + Frama_C_dump_each3(); + } +} + +void main3 () { + int index = 3; + int x = Frama_C_interval(0,100); + /*@ loop unroll 1; */ + while (500 - index >= x) { + Frama_C_dump_each(); + index += x + 4; + Frama_C_dump_each(); + x = Frama_C_interval(0,100); + Frama_C_dump_each(); + } +} diff --git a/tests/value/octagons.c b/tests/value/octagons.c index 7d51ba33e9b0242b54e636178ea71db939b7a960..a9428a90e4e6f4b052e9cde3e4514584a8e6b2f4 100644 --- a/tests/value/octagons.c +++ b/tests/value/octagons.c @@ -1,5 +1,5 @@ /* run.config* - STDOPT: +" -eva-domains octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue" + STDOPT: +"-deterministic -eva-domains octagon -eva-octagon-through-calls -eva-msg-key=d-octagon,-d-cvalue" */ #include <__fc_builtin.h> diff --git a/tests/value/oracle/behaviors2.res.oracle b/tests/value/oracle/behaviors2.res.oracle index bafc5e57b43b62c8f379e4bd48f6f9d8b15b71ad..6393f4f90fe5d5e3d5157491e386633a660d7a79 100644 --- a/tests/value/oracle/behaviors2.res.oracle +++ b/tests/value/oracle/behaviors2.res.oracle @@ -218,14 +218,14 @@ remainder ∈ [--..--] sign ∈ {-1; 0; 1} errmsg[0..19] ∈ [--..--] or UNINITIALIZED - r1 ∈ {0} - r2 ∈ {0} - r3 ∈ {0} - r4 ∈ {1} - r5 ∈ {2} - r6 ∈ {2} - r7 ∈ {2} - r8 ∈ {0; 1} + r1 ∈ {OK} + r2 ∈ {OK} + r3 ∈ {OK} + r4 ∈ {DIVBYZERO} + r5 ∈ {INVALID_PARAMETER} + r6 ∈ {INVALID_PARAMETER} + r7 ∈ {INVALID_PARAMETER} + r8 ∈ {OK; DIVBYZERO} [eva:final-states] Values at end of function test2: a ∈ {1} b ∈ {2} diff --git a/tests/value/oracle/enum.res.oracle b/tests/value/oracle/enum.res.oracle index c65343692b545464ab010a6e10926ed10f81c934..52445e88edf1db1f197815d29402acc5da52dbd5 100644 --- a/tests/value/oracle/enum.res.oracle +++ b/tests/value/oracle/enum.res.oracle @@ -21,8 +21,8 @@ [2] ∈ {36} i[0..1] ∈ {0; 1} [2] ∈ {0} - j ∈ {2} - k ∈ {0} + j ∈ {LAST} + k ∈ {ZERO} [from] Computing for function f [from] Done for function f [from] ====== DEPENDENCIES COMPUTED ====== diff --git a/tests/value/oracle/enum2.res.oracle b/tests/value/oracle/enum2.res.oracle index 1344f4349e7a1a9fc0a7699fb318922b18819ba9..b82181fdbb735edd8146ee8644f4f4e22fbdd95b 100644 --- a/tests/value/oracle/enum2.res.oracle +++ b/tests/value/oracle/enum2.res.oracle @@ -26,7 +26,7 @@ [eva:final-states] Values at end of function enum1_sgn1_inf_sgn0: res ∈ {0} [eva:final-states] Values at end of function f: - y ∈ {2557891634} + y ∈ {E1_SGN1} [eva:final-states] Values at end of function enum1_sgn1_positif: res ∈ {1} [eva:final-states] Values at end of function main: diff --git a/tests/value/oracle/gauges.res.oracle b/tests/value/oracle/gauges.res.oracle index a66e8eeac602b5dbc6fd77605d99074e76b1b212..683d5cd6e3ab18da6c43e6ae0f5f6d51be468471 100644 --- a/tests/value/oracle/gauges.res.oracle +++ b/tests/value/oracle/gauges.res.oracle @@ -343,7 +343,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -403,7 +403,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -462,7 +462,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -521,7 +521,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -586,7 +586,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -647,7 +647,7 @@ # cvalue: __fc_heap_status ∈ [--..--] __fc_random_counter ∈ [--..--] - __fc_rand_max ∈ {32767} + __fc_rand_max ∈ {2147483647} __fc_random48_init ∈ {0} __fc_random48_counter[0..2] ∈ [--..--] __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/value/oracle/if2.res.oracle b/tests/value/oracle/if2.res.oracle index aa0d25b661f5aa644ad27e7dc40e19029d216dc1..ed155b5d81b1877ce127863e2b0487d3fc661b9d 100644 --- a/tests/value/oracle/if2.res.oracle +++ b/tests/value/oracle/if2.res.oracle @@ -3,12 +3,12 @@ [eva] Computing initial state [eva] Initial state computed [eva:initial-state] Values of globals at initialization - G2 ∈ {0} + G2 ∈ {E1} G3 ∈ {75} G4 ∈ {0} R ∈ {0} v ∈ [--..--] - G1 ∈ {0} + G1 ∈ {E1} [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== diff --git a/tests/value/oracle/ilevel.res.oracle b/tests/value/oracle/ilevel.0.res.oracle similarity index 68% rename from tests/value/oracle/ilevel.res.oracle rename to tests/value/oracle/ilevel.0.res.oracle index 042c98daaa39125f33b39a30cbfe8798a9b6d8b4..897c9e808ca3ad9d067d85a82e9051411385263d 100644 --- a/tests/value/oracle/ilevel.res.oracle +++ b/tests/value/oracle/ilevel.0.res.oracle @@ -1,18 +1,18 @@ -[kernel] Parsing ilevel.i (no preprocessing) +[kernel] Parsing ilevel.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 - v ∈ [--..--] + nondet ∈ [--..--] i ∈ {0} j ∈ {0} k ∈ {0} l ∈ {0} -[eva] ilevel.i:9: starting to merge loop iterations -[eva] ilevel.i:12: starting to merge loop iterations -[eva:alarm] ilevel.i:20: Warning: assertion got status unknown. -[eva:alarm] ilevel.i:22: Warning: assertion got status unknown. -[eva] ilevel.i:24: Frama_C_show_each: [0..9] +[eva] ilevel.c:15: starting to merge loop iterations +[eva] ilevel.c:18: starting to merge loop iterations +[eva:alarm] ilevel.c:26: Warning: assertion got status unknown. +[eva:alarm] ilevel.c:28: Warning: assertion got status unknown. +[eva] ilevel.c:30: Frama_C_show_each: [0..9] [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== @@ -43,14 +43,14 @@ [eva] Computing initial state [eva] Initial state computed [eva:initial-state] Values of globals at initialization - v ∈ [--..--] + nondet ∈ [--..--] i ∈ {0} j ∈ {0} k ∈ {0} l ∈ {0} -[eva] ilevel.i:9: starting to merge loop iterations -[eva] ilevel.i:12: starting to merge loop iterations -[eva:alarm] ilevel.i:26: Warning: +[eva] ilevel.c:15: starting to merge loop iterations +[eva] ilevel.c:18: starting to merge loop iterations +[eva:alarm] ilevel.c:32: Warning: signed overflow. assert (int)((int)(i + j) + k) + l ≤ 2147483647; [eva] Recording results for main [eva] done for function main @@ -58,47 +58,44 @@ [eva:final-states] Values at end of function main: i ∈ {0; 1; 2; 3; 4; 5; 6; 7} j ∈ [0..16] - k ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15} + k ∈ [0..15] l ∈ [--..--] __retres ∈ [--..--] [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed [eva:initial-state] Values of globals at initialization - v ∈ [--..--] + nondet ∈ [--..--] i ∈ {0} j ∈ {0} k ∈ {0} l ∈ {0} -[eva] ilevel.i:24: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9} +[eva] ilevel.c:30: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9} [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: i ∈ {0; 1; 2; 3; 4; 5; 6; 7} - j ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16} - k ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15} + j ∈ [0..16] + k ∈ [0..15] l ∈ {0; 1; 2; 3; 4; 6; 7; 8; 9} __retres ∈ [0..47] [eva] Analyzing a complete application starting at main [eva] Computing initial state [eva] Initial state computed [eva:initial-state] Values of globals at initialization - v ∈ [--..--] + nondet ∈ [--..--] i ∈ {0} j ∈ {0} k ∈ {0} l ∈ {0} -[eva] ilevel.i:24: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9} +[eva] ilevel.c:30: Frama_C_show_each: {0; 1; 2; 3; 4; 6; 7; 8; 9} [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: i ∈ {0; 1; 2; 3; 4; 5; 6; 7} - j ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16} - k ∈ {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15} + j ∈ [0..16] + k ∈ [0..15] l ∈ {0; 1; 2; 3; 4; 6; 7; 8; 9} - __retres ∈ - {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; - 19; 20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 30; 31; 32; 33; 34; - 35; 36; 37; 38; 39; 40; 41; 42; 43; 44; 45; 46; 47} + __retres ∈ [0..47] diff --git a/tests/value/oracle/ilevel.1.res.oracle b/tests/value/oracle/ilevel.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..af0704f7b5dc3605bcf5703ca05d7133098127fb --- /dev/null +++ b/tests/value/oracle/ilevel.1.res.oracle @@ -0,0 +1,63 @@ +[kernel] Parsing ilevel.c (with preprocessing) +[eva] Analyzing a complete application starting at large_ilevel +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + nondet ∈ [--..--] + i ∈ {0} + j ∈ {0} + k ∈ {0} + l ∈ {0} +[eva] computing for function Frama_C_interval <- large_ilevel. + Called from ilevel.c:37. +[eva] using specification for function Frama_C_interval +[eva] ilevel.c:37: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function Frama_C_interval <- large_ilevel. + Called from ilevel.c:39. +[eva] ilevel.c:39: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] Recording results for large_ilevel +[eva] done for function large_ilevel +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function large_ilevel: + Frama_C_entropy_source ∈ [--..--] + i_0 ∈ [0..10] + j_0 ∈ [-25..-15] ∪ [0..10] + k_0 ∈ [100..200] + a[0] ∈ {53} + [1] ∈ {17} + [2] ∈ {64} + [3] ∈ {99} + [4] ∈ {25} + [5] ∈ {12} + [6] ∈ {72} + [7] ∈ {81} + [8] ∈ {404} + [9] ∈ {303} + [10] ∈ {-101} + s2 ∈ {40; 41; 42} + s1 ∈ {-101; 12; 17; 25; 53; 64; 72; 81; 99; 303; 404} + x ∈ + {-101} ∪ [-25..-15] ∪ [0..10] + ∪ {12; 17; 25; 40; 41; 42; 53; 64; 72; 81} ∪ [99..127] ∪ [129..200] + ∪ {303; 404} +[from] Computing for function large_ilevel +[from] Computing for function Frama_C_interval <-large_ilevel +[from] Done for function Frama_C_interval +[from] Done for function large_ilevel +[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 large_ilevel: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function large_ilevel: + Frama_C_entropy_source; i_0; j_0; tmp_0; k_0; a[0..10]; s2; tmp_2; + tmp_3; s1; x; tmp_4; tmp_5; tmp_6 +[inout] Inputs for function large_ilevel: + Frama_C_entropy_source; nondet diff --git a/tests/value/oracle/local_slevel.res.oracle b/tests/value/oracle/local_slevel.res.oracle index ed3e146882954d10d8006e8bff555354f887b127..8dfd964a3ce6047ef3a8f0a901faa3d9209f784f 100644 --- a/tests/value/oracle/local_slevel.res.oracle +++ b/tests/value/oracle/local_slevel.res.oracle @@ -78,7 +78,7 @@ [eva] local_slevel.i:37: Frama_C_show_each: {47} [eva] local_slevel.i:37: Frama_C_show_each: {48} [eva] local_slevel.i:37: Frama_C_show_each: {49} -[eva] local_slevel.i:43: Trace partitioning superposing up to 100 states +[eva] local_slevel.i:42: Trace partitioning superposing up to 100 states [eva] local_slevel.i:37: Frama_C_show_each: {50} [eva] local_slevel.i:37: Frama_C_show_each: {51} [eva] local_slevel.i:37: Frama_C_show_each: {52} @@ -129,7 +129,7 @@ [eva] local_slevel.i:37: Frama_C_show_each: {97} [eva] local_slevel.i:37: Frama_C_show_each: {98} [eva] local_slevel.i:37: Frama_C_show_each: {99} -[eva] local_slevel.i:43: Trace partitioning superposing up to 200 states +[eva] local_slevel.i:42: Trace partitioning superposing up to 200 states [eva] Recording results for main2 [eva] Done for function main2 [eva] Recording results for main @@ -185,7 +185,7 @@ void main1(void) while (i < 80) { /*@ ensures \true; assigns v; */ - /*@ slevel 50; */ + /*@ slevel 50; */ ; if (i % 2) v = 1; else v = -1; Frama_C_show_each(v,i,r); v *= v; @@ -251,7 +251,7 @@ void main1(void) while (i < 80) { /*@ ensures \true; assigns v; */ - /*@ slevel 50; */ + /*@ slevel 50; */ ; if (i % 2) v = 1; else v = -1; Frama_C_show_each(v,i,r); v *= v; @@ -317,7 +317,7 @@ void main1(void) while (i < 80) { /*@ ensures \true; assigns v; */ - /*@ slevel 50; */ + /*@ slevel 50; */ ; if (i % 2) v = 1; else v = -1; Frama_C_show_each(v,i,r); v *= v; @@ -446,7 +446,7 @@ void main(void) [eva] local_slevel.i:37: Frama_C_show_each: {47} [eva] local_slevel.i:37: Frama_C_show_each: {48} [eva] local_slevel.i:37: Frama_C_show_each: {49} -[eva] local_slevel.i:43: Trace partitioning superposing up to 100 states +[eva] local_slevel.i:42: Trace partitioning superposing up to 100 states [eva] local_slevel.i:37: Frama_C_show_each: {50} [eva] local_slevel.i:37: Frama_C_show_each: {51} [eva] local_slevel.i:37: Frama_C_show_each: {52} @@ -497,7 +497,7 @@ void main(void) [eva] local_slevel.i:37: Frama_C_show_each: {97} [eva] local_slevel.i:37: Frama_C_show_each: {98} [eva] local_slevel.i:37: Frama_C_show_each: {99} -[eva] local_slevel.i:43: Trace partitioning superposing up to 200 states +[eva] local_slevel.i:42: Trace partitioning superposing up to 200 states [eva] Recording results for main2 [eva] Done for function main2 [eva] Recording results for main diff --git a/tests/value/oracle/multidim.res.oracle b/tests/value/oracle/multidim.res.oracle index 8b800aabbbee8ad467445cbf7bdab413b599d859..063652013480e6f05f3431090a10f35e00de62f9 100644 --- a/tests/value/oracle/multidim.res.oracle +++ b/tests/value/oracle/multidim.res.oracle @@ -186,7 +186,7 @@ more than 1(1000) locations to update in array. Approximating. [eva] multidim.c:145: Frama_C_domain_show_each: - t : # cvalue: [0].typ ∈ {1; 2} or UNINITIALIZED + t : # cvalue: [0].typ ∈ {INT; FLOAT} or UNINITIALIZED {[0].val; [1..999]} ∈ [--..--] or UNINITIALIZED # multidim: [0 .. 999] = { { .typ = {1}, .val.i = {42} } or @@ -250,7 +250,7 @@ t[0..99] ∈ {0} [eva:final-states] Values at end of function main7: Frama_C_entropy_source ∈ [--..--] - t[0].typ ∈ {1; 2} or UNINITIALIZED + t[0].typ ∈ {INT; FLOAT} or UNINITIALIZED {[0].val; [1..999]} ∈ [--..--] or UNINITIALIZED j ∈ [0..999] [eva:final-states] Values at end of function main8: diff --git a/tests/value/oracle/octagons-pointers-intermediate.res.oracle b/tests/value/oracle/octagons-pointers-intermediate.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..f6f6928d4db7af08f6ab5ce3c73d7c426302cd10 --- /dev/null +++ b/tests/value/oracle/octagons-pointers-intermediate.res.oracle @@ -0,0 +1,70 @@ +[kernel] Parsing octagons-pointers-intermediate.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 + size ∈ {436} + buffer[0..435] ∈ {0} + nondet ∈ [--..--] +[eva] computing for function init <- main. + Called from octagons-pointers-intermediate.c:38. +[eva] octagons-pointers-intermediate.c:18: starting to merge loop iterations +[eva] Recording results for init +[eva] Done for function init +[eva] computing for function cmdRead <- main. + Called from octagons-pointers-intermediate.c:45. +[eva] Recording results for cmdRead +[eva] Done for function cmdRead +[eva] computing for function cmdRead <- main. + Called from octagons-pointers-intermediate.c:45. +[eva] Recording results for cmdRead +[eva] Done for function cmdRead +[eva:loop-unroll:partial] octagons-pointers-intermediate.c:47: + loop not completely unrolled +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function cmdRead: + len ∈ {{ &buffer + [3..433] }} + code ∈ {{ &buffer + [5..435] }} + elt1 ∈ {{ &buffer + [6..436] }} + elt2 ∈ {{ &buffer + [10..440] }} + elt3 ∈ {{ &buffer + [12..442] }} + c ∈ [--..--] + e1 ∈ [--..--] + e2 ∈ [--..--] + e3 ∈ [--..--] +[eva:final-states] Values at end of function init: + buffer[0..435] ∈ [--..--] + i ∈ {436} +[eva:final-states] Values at end of function main: + buffer[0..435] ∈ [--..--] + index ∈ [3..436] + cmd ∈ {{ &buffer + [3..436] }} +[from] Computing for function cmdRead +[from] Done for function cmdRead +[from] Computing for function init +[from] Done for function init +[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 cmdRead: + NO EFFECTS +[from] Function init: + buffer[0..435] FROM size; nondet (and SELF) +[from] Function main: + buffer[0..435] FROM size; nondet (and SELF) +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function cmdRead: + len; code; elt1; elt2; elt3; c; e1; e2; e3 +[inout] Inputs for function cmdRead: + buffer[5..435] +[inout] Out (internal) for function init: + buffer[0..435]; i +[inout] Inputs for function init: + size; nondet +[inout] Out (internal) for function main: + buffer[0..435]; index; cmd +[inout] Inputs for function main: + size; buffer[3..435]; nondet diff --git a/tests/value/oracle/octagons-pointers-simple.res.oracle b/tests/value/oracle/octagons-pointers-simple.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..b4ac5a0756733ff58a4a12d5a53b72dca2edf3a6 --- /dev/null +++ b/tests/value/oracle/octagons-pointers-simple.res.oracle @@ -0,0 +1,87 @@ +[kernel] Parsing octagons-pointers-simple.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 + size ∈ {436} + buffer[0..435] ∈ {0} + nondet ∈ [--..--] +[eva] computing for function init <- main. + Called from octagons-pointers-simple.c:38. +[eva] octagons-pointers-simple.c:18: starting to merge loop iterations +[eva] Recording results for init +[eva] Done for function init +[eva] octagons-pointers-simple.c:46: + Frama_C_dump_each: + # octagon: + {[ buffer - cmd ∈ {-3} + cmd->cmdLen - cmdLen ∈ {0} + ]} + ==END OF DUMP== +[eva] computing for function cmdRead <- main. + Called from octagons-pointers-simple.c:47. +[eva] Recording results for cmdRead +[eva] Done for function cmdRead +[eva] octagons-pointers-simple.c:46: + Frama_C_dump_each: + # octagon: + {[ buffer - cmd ∈ [-436..-6] + cmd->cmdLen - cmdLen ∈ {0} + index + cmdLen ∈ [--..434] + cmd->cmdLen + index ∈ [--..434] + ]} + ==END OF DUMP== +[eva] computing for function cmdRead <- main. + Called from octagons-pointers-simple.c:47. +[eva] Recording results for cmdRead +[eva] Done for function cmdRead +[eva:loop-unroll:partial] octagons-pointers-simple.c:49: + loop not completely unrolled +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function cmdRead: + len ∈ {{ &buffer + [3..433] }} + code ∈ {{ &buffer + [5..435] }} + elt1 ∈ {{ &buffer + [6..436] }} + elt2 ∈ {{ &buffer + [10..440] }} + elt3 ∈ {{ &buffer + [12..442] }} + c ∈ [--..--] + e1 ∈ [--..--] + e2 ∈ [--..--] + e3 ∈ [--..--] +[eva:final-states] Values at end of function init: + buffer[0..435] ∈ [--..--] + i ∈ {436} +[eva:final-states] Values at end of function main: + buffer[0..435] ∈ [--..--] + index ∈ [3..436] + cmdLen ∈ [0..65535] + cmd ∈ {{ &buffer + [3..436] }} +[from] Computing for function cmdRead +[from] Done for function cmdRead +[from] Computing for function init +[from] Done for function init +[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 cmdRead: + NO EFFECTS +[from] Function init: + buffer[0..435] FROM size; nondet (and SELF) +[from] Function main: + buffer[0..435] FROM size; nondet (and SELF) +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function cmdRead: + len; code; elt1; elt2; elt3; c; e1; e2; e3 +[inout] Inputs for function cmdRead: + buffer[5..435] +[inout] Out (internal) for function init: + buffer[0..435]; i +[inout] Inputs for function init: + size; nondet +[inout] Out (internal) for function main: + buffer[0..435]; index; cmdLen; cmd +[inout] Inputs for function main: + size; buffer[3..435]; nondet diff --git a/tests/value/oracle/octagons-pointers.res.oracle b/tests/value/oracle/octagons-pointers.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..dcc4c9fa9e70f408240e63200520b112956ebb1c --- /dev/null +++ b/tests/value/oracle/octagons-pointers.res.oracle @@ -0,0 +1,130 @@ +[kernel] Parsing octagons-pointers.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 + size ∈ {436} + buffer[0..435] ∈ {0} + nondet ∈ [--..--] +[eva] computing for function init <- main. + Called from octagons-pointers.c:39. +[eva] octagons-pointers.c:18: starting to merge loop iterations +[eva] Recording results for init +[eva] Done for function init +[eva] octagons-pointers.c:46: + Frama_C_dump_each: + # octagon: + {[ buffer - cmd ∈ {-3} + ]} + ==END OF DUMP== +[eva] computing for function cmdRead <- main. + Called from octagons-pointers.c:47. +[eva] octagons-pointers.c:31: + Frama_C_dump_each: + # octagon: + {[ buffer - cmd ∈ {-3} + buffer - cmd ∈ {-3} + cmd - cmd ∈ {0} + ]} + ==END OF DUMP== +[eva] Recording results for cmdRead +[eva] Done for function cmdRead +[eva] octagons-pointers.c:46: + Frama_C_dump_each: + # octagon: + {[ buffer - cmd ∈ [-436..-6] + cmd->cmdLen + index ∈ [--..434] + ]} + ==END OF DUMP== +[eva] computing for function cmdRead <- main. + Called from octagons-pointers.c:47. +[eva] octagons-pointers.c:31: + Frama_C_dump_each: + # octagon: + {[ buffer - cmd ∈ [-436..-6] + buffer - cmd ∈ [-433..-6] + cmd - cmd ∈ [-430..427] + cmd->cmdLen + index ∈ [--..434] + cmd - len ∈ {0} + buffer - len ∈ [-433..-6] + len - cmd ∈ [-430..427] + len - code ∈ {-2} + buffer - code ∈ [-435..-8] + cmd - code ∈ {-2} + code - cmd ∈ [-428..429] + code - elt1 ∈ {-1} + buffer - elt1 ∈ [-436..-9] + cmd - elt1 ∈ {-3} + len - elt1 ∈ {-3} + elt1 - cmd ∈ [-427..430] + elt1 - elt2 ∈ {-4} + buffer - elt2 ∈ [-440..-13] + cmd - elt2 ∈ {-7} + len - elt2 ∈ {-7} + code - elt2 ∈ {-5} + elt2 - cmd ∈ [-423..434] + elt2 - elt3 ∈ {-2} + buffer - elt3 ∈ [-442..-15] + cmd - elt3 ∈ {-9} + len - elt3 ∈ {-9} + code - elt3 ∈ {-7} + elt1 - elt3 ∈ {-6} + elt3 - cmd ∈ [-421..436] + ]} + ==END OF DUMP== +[eva:alarm] octagons-pointers.c:33: Warning: + out of bounds read. assert \valid_read(elt1); +[eva:alarm] octagons-pointers.c:34: Warning: + out of bounds read. assert \valid_read(elt2); +[eva:alarm] octagons-pointers.c:35: Warning: + out of bounds read. assert \valid_read(elt3); +[eva] Recording results for cmdRead +[eva] Done for function cmdRead +[eva:loop-unroll:partial] octagons-pointers.c:49: loop not completely unrolled +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function cmdRead: + len ∈ {{ &buffer + [3..433] }} + code ∈ {{ &buffer + [5..435] }} + elt1 ∈ {{ &buffer + [6..436] }} + elt2 ∈ {{ &buffer + [10..440] }} + elt3 ∈ {{ &buffer + [12..442] }} + c ∈ [--..--] + e1 ∈ [--..--] + e2 ∈ [--..--] + e3 ∈ [--..--] +[eva:final-states] Values at end of function init: + buffer[0..435] ∈ [--..--] + i ∈ {436} +[eva:final-states] Values at end of function main: + buffer[0..435] ∈ [--..--] + index ∈ [3..436] + cmd ∈ {{ &buffer + [3..436] }} +[from] Computing for function cmdRead +[from] Done for function cmdRead +[from] Computing for function init +[from] Done for function init +[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 cmdRead: + NO EFFECTS +[from] Function init: + buffer[0..435] FROM size; nondet (and SELF) +[from] Function main: + buffer[0..435] FROM size; nondet (and SELF) +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function cmdRead: + len; code; elt1; elt2; elt3; c; e1; e2; e3 +[inout] Inputs for function cmdRead: + buffer[3..435] +[inout] Out (internal) for function init: + buffer[0..435]; i +[inout] Inputs for function init: + size; nondet +[inout] Out (internal) for function main: + buffer[0..435]; index; cmd +[inout] Inputs for function main: + size; buffer[3..435]; nondet diff --git a/tests/value/oracle/octagons.res.oracle b/tests/value/oracle/octagons.res.oracle index 9a12d8aaa3b350f6a15641bb6783d1636521ec2b..918911acb43c4f0d2111992d756dee96b8782448 100644 --- a/tests/value/oracle/octagons.res.oracle +++ b/tests/value/oracle/octagons.res.oracle @@ -218,7 +218,10 @@ Called from octagons.c:196. [eva] Recording results for neg [eva] Done for function neg -[eva] octagons.c:197: Reusing old results for call to neg +[eva] computing for function neg <- interprocedural <- main. + Called from octagons.c:197. +[eva] Recording results for neg +[eva] Done for function neg [eva] computing for function diff <- interprocedural <- main. Called from octagons.c:206. [eva] Recording results for diff @@ -235,6 +238,8 @@ # octagon: {[ a + neg_a ∈ {0} b + neg_b ∈ {0} + p - a ∈ {0} + *p - a1 ∈ {0} ]} ==END OF DUMP== [eva] Recording results for test_non_integer_args diff --git a/tests/value/oracle/partitioning-annots.0.res.oracle b/tests/value/oracle/partitioning-annots.0.res.oracle index ef583a47f12fc77c9189539ef61777c459342e78..aa52873360db70044e939172e2cff1a5bba13fdb 100644 --- a/tests/value/oracle/partitioning-annots.0.res.oracle +++ b/tests/value/oracle/partitioning-annots.0.res.oracle @@ -6,13 +6,13 @@ nondet ∈ [--..--] k ∈ {0} [eva] computing for function test_slevel <- main. - Called from partitioning-annots.c:223. -[eva] partitioning-annots.c:188: starting to merge loop iterations -[eva] partitioning-annots.c:193: starting to merge loop iterations + Called from partitioning-annots.c:278. +[eva] partitioning-annots.c:243: starting to merge loop iterations +[eva] partitioning-annots.c:248: starting to merge loop iterations [eva] Recording results for test_slevel [eva] Done for function test_slevel [eva] computing for function test_unroll <- main. - Called from partitioning-annots.c:224. + Called from partitioning-annots.c:279. [eva:loop-unroll:partial] partitioning-annots.c:26: loop not completely unrolled [eva] partitioning-annots.c:26: starting to merge loop iterations [eva:loop-unroll:partial] partitioning-annots.c:34: loop not completely unrolled @@ -25,7 +25,7 @@ [eva] Recording results for test_unroll [eva] Done for function test_unroll [eva] computing for function test_split <- main. - Called from partitioning-annots.c:225. + Called from partitioning-annots.c:280. [eva] computing for function Frama_C_interval <- test_split <- main. Called from partitioning-annots.c:73. [eva] using specification for function Frama_C_interval @@ -65,7 +65,7 @@ [eva] Recording results for test_split [eva] Done for function test_split [eva] computing for function test_dynamic_split <- main. - Called from partitioning-annots.c:226. + Called from partitioning-annots.c:281. [eva] partitioning-annots.c:95: Warning: this partitioning parameter cannot be evaluated safely on all states [eva] computing for function Frama_C_interval <- test_dynamic_split <- main. @@ -90,13 +90,44 @@ [eva] Recording results for test_dynamic_split [eva] Done for function test_dynamic_split [eva] computing for function test_dynamic_split_predicate <- main. - Called from partitioning-annots.c:227. + Called from partitioning-annots.c:282. [eva] partitioning-annots.c:124: starting to merge loop iterations [eva] Recording results for test_dynamic_split_predicate [eva] Done for function test_dynamic_split_predicate +[eva] computing for function test_splits_post_call <- main. + Called from partitioning-annots.c:283. +[eva] computing for function Frama_C_interval <- test_splits_post_call <- main. + Called from partitioning-annots.c:205. +[eva] partitioning-annots.c:205: + function Frama_C_interval: precondition 'order' got status valid. +[eva] Done for function Frama_C_interval +[eva] computing for function spec <- test_splits_post_call <- main. + Called from partitioning-annots.c:206. +[eva] using specification for function spec +[eva] Done for function spec +[eva] partitioning-annots.c:211: Frama_C_show_each_spec: [-2147483648..-10], ⊥ +[eva] partitioning-annots.c:211: Frama_C_show_each_spec: [10..2147483647], ⊥ +[eva] partitioning-annots.c:211: Frama_C_show_each_spec: {-1}, [-1000..1000] +[eva] computing for function body <- test_splits_post_call <- main. + Called from partitioning-annots.c:212. +[eva] Recording results for body +[eva] Done for function body +[eva] partitioning-annots.c:212: Reusing old results for call to body +[eva] partitioning-annots.c:212: Reusing old results for call to body +[eva] partitioning-annots.c:217: Frama_C_show_each_body: [-510..-10], ⊥ +[eva] partitioning-annots.c:217: Frama_C_show_each_body: [10..510], ⊥ +[eva] partitioning-annots.c:217: Frama_C_show_each_body: {-1}, [-1000..1000] +[eva] Recording results for test_splits_post_call +[eva] Done for function test_splits_post_call [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function body: + i2 ∈ [-500..500] + absolute ∈ [0..500] + state ∈ {-1; 0; 1} + y ∈ [-1000..1000] or UNINITIALIZED + __retres ∈ [-510..510] [eva:final-states] Values at end of function test_dynamic_split: Frama_C_entropy_source ∈ [--..--] a ∈ {0} @@ -117,6 +148,13 @@ k ∈ {0; 1} i ∈ {0; 1} j ∈ {0; 1; 2} +[eva:final-states] Values at end of function test_splits_post_call: + Frama_C_entropy_source ∈ [--..--] + x ∈ [-1000..1000] or UNINITIALIZED + y ∈ [-1000..1000] or UNINITIALIZED + error ∈ [-1000..1000] or UNINITIALIZED + i ∈ [-1000..1000] + r ∈ [-510..510] [eva:final-states] Values at end of function test_unroll: a[0..9] ∈ {42} b[0..9] ∈ {42} @@ -145,6 +183,8 @@ [eva:final-states] Values at end of function main: Frama_C_entropy_source ∈ [--..--] k ∈ {0; 1} +[from] Computing for function body +[from] Done for function body [from] Computing for function test_dynamic_split [from] Computing for function Frama_C_interval <-test_dynamic_split [from] Done for function Frama_C_interval @@ -155,6 +195,10 @@ [from] Done for function test_slevel [from] Computing for function test_split [from] Done for function test_split +[from] Computing for function test_splits_post_call +[from] Computing for function spec <-test_splits_post_call +[from] Done for function spec +[from] Done for function test_splits_post_call [from] Computing for function test_unroll [from] Done for function test_unroll [from] Computing for function main @@ -164,6 +208,12 @@ [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 body: + y FROM nondet; i; p (and SELF) + \result FROM nondet; i +[from] Function spec: + x FROM i + \result FROM i [from] Function test_dynamic_split: Frama_C_entropy_source FROM Frama_C_entropy_source; nondet (and SELF) [from] Function test_dynamic_split_predicate: @@ -173,12 +223,18 @@ [from] Function test_split: Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) k FROM Frama_C_entropy_source +[from] Function test_splits_post_call: + Frama_C_entropy_source FROM Frama_C_entropy_source (and SELF) [from] Function test_unroll: NO EFFECTS [from] Function main: Frama_C_entropy_source FROM Frama_C_entropy_source; nondet (and SELF) k FROM Frama_C_entropy_source [from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function body: + i2; absolute; tmp; state; y; __retres +[inout] Inputs for function body: + nondet [inout] Out (internal) for function test_dynamic_split: Frama_C_entropy_source; a; b [inout] Inputs for function test_dynamic_split: @@ -195,6 +251,10 @@ Frama_C_entropy_source; k; i; j [inout] Inputs for function test_split: Frama_C_entropy_source; k +[inout] Out (internal) for function test_splits_post_call: + Frama_C_entropy_source; x; y; error; i; r +[inout] Inputs for function test_splits_post_call: + Frama_C_entropy_source; nondet [inout] Out (internal) for function test_unroll: a[0..9]; b[0..9]; c[0..19]; d[0..19]; e[0..9]; i; j; i_0; j_0; i_1; i_2; i_3; j_1 diff --git a/tests/value/oracle/partitioning-annots.3.res.oracle b/tests/value/oracle/partitioning-annots.3.res.oracle index 3fe49f8ff9266240c18aac21e67f32978e3992ca..365ff709693100a98812f0b3ee71f2608624ab07 100644 --- a/tests/value/oracle/partitioning-annots.3.res.oracle +++ b/tests/value/oracle/partitioning-annots.3.res.oracle @@ -6,13 +6,13 @@ nondet ∈ [--..--] k ∈ {0} [eva] computing for function Frama_C_interval <- test_history. - Called from partitioning-annots.c:167. + Called from partitioning-annots.c:222. [eva] using specification for function Frama_C_interval -[eva] partitioning-annots.c:167: +[eva] partitioning-annots.c:222: function Frama_C_interval: precondition 'order' got status valid. [eva] Done for function Frama_C_interval -[eva] partitioning-annots.c:173: Frama_C_show_each: {0; 1}, {0; 1} -[eva:alarm] partitioning-annots.c:176: Warning: +[eva] partitioning-annots.c:228: Frama_C_show_each: {0; 1}, {0; 1} +[eva:alarm] partitioning-annots.c:231: Warning: division by zero. assert j ≢ 0; [eva] Recording results for test_history [eva] done for function test_history diff --git a/tests/value/oracle/partitioning-annots.4.res.oracle b/tests/value/oracle/partitioning-annots.4.res.oracle index 793324f2603cfd3fb554a92a29803c88ae31e867..8ad2cdfc8afe43036525234351b1a5baebfff62c 100644 --- a/tests/value/oracle/partitioning-annots.4.res.oracle +++ b/tests/value/oracle/partitioning-annots.4.res.oracle @@ -6,13 +6,13 @@ nondet ∈ [--..--] k ∈ {0} [eva] computing for function Frama_C_interval <- test_history. - Called from partitioning-annots.c:167. + Called from partitioning-annots.c:222. [eva] using specification for function Frama_C_interval -[eva] partitioning-annots.c:167: +[eva] partitioning-annots.c:222: function Frama_C_interval: precondition 'order' got status valid. [eva] Done for function Frama_C_interval -[eva] partitioning-annots.c:173: Frama_C_show_each: {0}, {0} -[eva] partitioning-annots.c:173: Frama_C_show_each: {1}, {1} +[eva] partitioning-annots.c:228: Frama_C_show_each: {0}, {0} +[eva] partitioning-annots.c:228: Frama_C_show_each: {1}, {1} [eva] Recording results for test_history [eva] done for function test_history [eva] ====== VALUES COMPUTED ====== diff --git a/tests/value/oracle/recol.1.res.oracle b/tests/value/oracle/recol.1.res.oracle index 89f1f21dd124e2d9ebfc2e09cc6ccec64f318aa4..23eb96edca7dc95f69bc4907078beeec131dfea0 100644 --- a/tests/value/oracle/recol.1.res.oracle +++ b/tests/value/oracle/recol.1.res.oracle @@ -23,10 +23,10 @@ [eva:final-states] Values at end of function main: s[bits 0 to 15] ∈ {97} [bits 16 to 47] ∈ {776} - [6] ∈ {-103} + [6] ∈ {153} [bits 56 to 71] ∈ {-26736} [bits 72 to 103] ∈ {271697} - [13] ∈ {-104} + [13] ∈ {152} [bits 112 to 127] ∈ {10121} [bits 128 to 159] ∈ {93197600} [20] ∈ {65} @@ -52,8 +52,8 @@ [bits 552 to 583] ∈ {1373000945} [bits 584 to 599] ∈ {21240} [75] ∈ {41} - [76] ∈ {-128} - [77] ∈ {-31} + [76] ∈ {128} + [77] ∈ {225} [bits 624 to 655] ∈ {-832127096} [82] ∈ {25} [83] ∈ {16} diff --git a/tests/value/oracle/statistics.csv b/tests/value/oracle/statistics.csv new file mode 100644 index 0000000000000000000000000000000000000000..f844aeb8ca15700b2e9b58fd5303876925a37bae --- /dev/null +++ b/tests/value/oracle/statistics.csv @@ -0,0 +1,7 @@ +memexec-hits g 3 +memexec-misses g 5 +memexec-misses f 2 +memexec-misses main 1 +partitioning-index-misses 57 +max-widenings f statistics.i:12 1 +iterations f statistics.i:12 8 diff --git a/tests/value/oracle/statistics.res.oracle b/tests/value/oracle/statistics.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9d6258ee598876f6071ef856f29e7393a2de4ab0 --- /dev/null +++ b/tests/value/oracle/statistics.res.oracle @@ -0,0 +1,76 @@ +[kernel] Parsing statistics.i (no 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 f <- main. + Called from statistics.i:18. +[eva] computing for function g <- f <- main. + Called from statistics.i:13. +[eva] Recording results for g +[eva] Done for function g +[eva] statistics.i:12: starting to merge loop iterations +[eva] computing for function g <- f <- main. + Called from statistics.i:13. +[eva] Recording results for g +[eva] Done for function g +[eva] computing for function g <- f <- main. + Called from statistics.i:13. +[eva] Recording results for g +[eva] Done for function g +[eva] computing for function g <- f <- main. + Called from statistics.i:13. +[eva] Recording results for g +[eva] Done for function g +[eva] Recording results for f +[eva] Done for function f +[eva:alarm] statistics.i:19: Warning: + signed overflow. assert -2147483648 ≤ n - 1; +[eva] computing for function f <- main. + Called from statistics.i:19. +[eva] statistics.i:13: Reusing old results for call to g +[eva] statistics.i:13: Reusing old results for call to g +[eva] statistics.i:13: Reusing old results for call to g +[eva] computing for function g <- f <- main. + Called from statistics.i:13. +[eva] Recording results for g +[eva] Done for function g +[eva] Recording results for f +[eva] Done for function f +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function g: + +[eva:final-states] Values at end of function f: + i ∈ [0..2147483647] +[eva:final-states] Values at end of function main: + __retres ∈ {0} +[from] Computing for function g +[from] Done for function g +[from] Computing for function f +[from] Done for function f +[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 g: + NO EFFECTS +[from] Function f: + NO EFFECTS +[from] Function main: + \result FROM \nothing +[from] ====== END OF DEPENDENCIES ====== +[inout] Out (internal) for function g: + \nothing +[inout] Inputs for function g: + \nothing +[inout] Out (internal) for function f: + i +[inout] Inputs for function f: + \nothing +[inout] Out (internal) for function main: + __retres +[inout] Inputs for function main: + \nothing diff --git a/tests/value/oracle/strucval.res.oracle b/tests/value/oracle/strucval.res.oracle index 908dd3c2c463501d61052957b91ce73ca43c9f66..b6030c1596582d9bf85a600b83ccd3db16ca24a8 100644 --- a/tests/value/oracle/strucval.res.oracle +++ b/tests/value/oracle/strucval.res.oracle @@ -12,7 +12,7 @@ [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: - SharedData.FunctionCode ∈ {0} + SharedData.FunctionCode ∈ {BDP_BITE_NORMAL} .MachineNumber ∈ {1456} .[bits 48 to 63] ∈ UNINITIALIZED .Line ∈ {25} diff --git a/tests/value/oracle_apron/octagons-pointers-simple.res.oracle b/tests/value/oracle_apron/octagons-pointers-simple.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..c976f8080e08fd8a1562ddb133889ddac757a32f --- /dev/null +++ b/tests/value/oracle_apron/octagons-pointers-simple.res.oracle @@ -0,0 +1,15 @@ +39a40,53 +> [eva] octagons-pointers-simple.c:43: starting to merge loop iterations +> [eva] octagons-pointers-simple.c:46: +> Frama_C_dump_each: +> # octagon: +> {[ buffer - cmd ∈ [-436..-6] +> cmd->cmdLen - cmdLen ∈ {0} +> index + cmdLen ∈ [--..434] +> cmd->cmdLen + index ∈ [--..434] +> ]} +> ==END OF DUMP== +> [eva] computing for function cmdRead <- main. +> Called from octagons-pointers-simple.c:47. +> [eva] Recording results for cmdRead +> [eva] Done for function cmdRead diff --git a/tests/value/oracle_apron/octagons.res.oracle b/tests/value/oracle_apron/octagons.res.oracle index b6259b0a61145df421dce827edfc493473abffca..1c3d249968164cc4519adfbf3661a2bbabe3a944 100644 --- a/tests/value/oracle_apron/octagons.res.oracle +++ b/tests/value/oracle_apron/octagons.res.oracle @@ -1,16 +1,4 @@ -221c221,224 -< [eva] octagons.c:197: Reusing old results for call to neg ---- -> [eva] computing for function neg <- interprocedural <- main. -> Called from octagons.c:197. -> [eva] Recording results for neg -> [eva] Done for function neg -237a241,244 -> a - b ∈ [-16..16] -> b + neg_a ∈ [-16..16] -> a + neg_b ∈ [-16..16] -> neg_a - neg_b ∈ [-16..16] -366,369c373,376 +371,374c371,374 < a ∈ [-1024..2147483647] < b ∈ [-1023..2147483647] < c ∈ [-1023..2147483647] diff --git a/tests/value/oracle_apron/partitioning-annots.0.res.oracle b/tests/value/oracle_apron/partitioning-annots.0.res.oracle index 94ed9ffca14931983ca8b0fcfd773dae01006fe7..68d268103b83832bb45759df2b7108b8ad474e1e 100644 --- a/tests/value/oracle_apron/partitioning-annots.0.res.oracle +++ b/tests/value/oracle_apron/partitioning-annots.0.res.oracle @@ -1,4 +1,16 @@ -105,106c105,106 +115,116c115,122 +< [eva] partitioning-annots.c:212: Reusing old results for call to body +< [eva] partitioning-annots.c:212: Reusing old results for call to body +--- +> [eva] computing for function body <- test_splits_post_call <- main. +> Called from partitioning-annots.c:212. +> [eva] Recording results for body +> [eva] Done for function body +> [eva] computing for function body <- test_splits_post_call <- main. +> Called from partitioning-annots.c:212. +> [eva] Recording results for body +> [eva] Done for function body +136,137c142,143 < x ∈ [0..44] < y ∈ [0..44] --- diff --git a/tests/value/oracle_apron/partitioning-annots.3.res.oracle b/tests/value/oracle_apron/partitioning-annots.3.res.oracle index d04cebfc945498812ebf2de1f658c5458442d6d8..5a8823d8cc9e5c5d07f57720b06f7c0917f9c17a 100644 --- a/tests/value/oracle_apron/partitioning-annots.3.res.oracle +++ b/tests/value/oracle_apron/partitioning-annots.3.res.oracle @@ -1,3 +1,3 @@ 15,16d14 -< [eva:alarm] partitioning-annots.c:176: Warning: +< [eva:alarm] partitioning-annots.c:231: Warning: < division by zero. assert j ≢ 0; diff --git a/tests/value/oracle_apron/statistics.res.oracle b/tests/value/oracle_apron/statistics.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..9a97de5637c3ca83fe4c2b5547eb7e2616f9bf94 --- /dev/null +++ b/tests/value/oracle_apron/statistics.res.oracle @@ -0,0 +1,17 @@ +32,34c32,43 +< [eva] statistics.i:13: Reusing old results for call to g +< [eva] statistics.i:13: Reusing old results for call to g +< [eva] statistics.i:13: Reusing old results for call to g +--- +> [eva] computing for function g <- f <- main. +> Called from statistics.i:13. +> [eva] Recording results for g +> [eva] Done for function g +> [eva] computing for function g <- f <- main. +> Called from statistics.i:13. +> [eva] Recording results for g +> [eva] Done for function g +> [eva] computing for function g <- f <- main. +> Called from statistics.i:13. +> [eva] Recording results for g +> [eva] Done for function g diff --git a/tests/value/oracle_equality/octagons.res.oracle b/tests/value/oracle_equality/octagons.res.oracle index bf4e1ca8d51e0aaa4c7ec1117686a0c8ee9807b4..3b1ca3ecba8569890b9c9fad8a1d7fe77e4b0226 100644 --- a/tests/value/oracle_equality/octagons.res.oracle +++ b/tests/value/oracle_equality/octagons.res.oracle @@ -2,18 +2,7 @@ < [eva] octagons.c:54: Frama_C_show_each_unreduced_char: [-128..127], [-128..127] --- > [eva] octagons.c:54: Frama_C_show_each_unreduced_char: [-118..114], [6..127] -221c221,224 -< [eva] octagons.c:197: Reusing old results for call to neg ---- -> [eva] computing for function neg <- interprocedural <- main. -> Called from octagons.c:197. -> [eva] Recording results for neg -> [eva] Done for function neg -237a241,243 -> a - b ∈ [-16..16] -> b + neg_a ∈ [-16..16] -> a + neg_b ∈ [-16..16] -353c359 +358c358 < ct ∈ [--..--] or UNINITIALIZED --- > ct ∈ [6..127] or UNINITIALIZED diff --git a/tests/value/oracle_gauges/gauges.res.oracle b/tests/value/oracle_gauges/gauges.res.oracle index bd0f8dbd9eb7433da20ad4403a92494bb6396cb2..89bba971700e381aecb42f0a87e0010a27a5a7d7 100644 --- a/tests/value/oracle_gauges/gauges.res.oracle +++ b/tests/value/oracle_gauges/gauges.res.oracle @@ -135,7 +135,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} @@ -199,7 +199,7 @@ > # cvalue: > __fc_heap_status ∈ [--..--] > __fc_random_counter ∈ [--..--] -> __fc_rand_max ∈ {32767} +> __fc_rand_max ∈ {2147483647} > __fc_random48_init ∈ {0} > __fc_random48_counter[0..2] ∈ [--..--] > __fc_p_random48_counter ∈ {{ &__fc_random48_counter[0] }} diff --git a/tests/value/oracle_gauges/octagons-pointers-intermediate.res.oracle b/tests/value/oracle_gauges/octagons-pointers-intermediate.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..993825158c77e1d611c02be27e37da1414ab72d1 --- /dev/null +++ b/tests/value/oracle_gauges/octagons-pointers-intermediate.res.oracle @@ -0,0 +1,8 @@ +23a24,30 +> [eva] octagons-pointers-intermediate.c:42: starting to merge loop iterations +> [eva] octagons-pointers-intermediate.c:45: +> Reusing old results for call to cmdRead +> [eva] octagons-pointers-intermediate.c:45: +> Reusing old results for call to cmdRead +> [eva] octagons-pointers-intermediate.c:45: +> Reusing old results for call to cmdRead diff --git a/tests/value/oracle_gauges/octagons-pointers-simple.res.oracle b/tests/value/oracle_gauges/octagons-pointers-simple.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..1f0784eedc6dda45bb7958cdb87c4a3553ffd9b4 --- /dev/null +++ b/tests/value/oracle_gauges/octagons-pointers-simple.res.oracle @@ -0,0 +1,32 @@ +39a40,70 +> [eva] octagons-pointers-simple.c:43: starting to merge loop iterations +> [eva] octagons-pointers-simple.c:46: +> Frama_C_dump_each: +> # octagon: +> {[ buffer - cmd ∈ [-436..-6] +> cmd->cmdLen - cmdLen ∈ {0} +> index + cmdLen ∈ [--..434] +> cmd->cmdLen + index ∈ [--..434] +> ]} +> ==END OF DUMP== +> [eva] octagons-pointers-simple.c:47: Reusing old results for call to cmdRead +> [eva] octagons-pointers-simple.c:46: +> Frama_C_dump_each: +> # octagon: +> {[ buffer - cmd ∈ [-436..-6] +> cmd->cmdLen - cmdLen ∈ {0} +> index + cmdLen ∈ [--..434] +> cmd->cmdLen + index ∈ [--..434] +> ]} +> ==END OF DUMP== +> [eva] octagons-pointers-simple.c:47: Reusing old results for call to cmdRead +> [eva] octagons-pointers-simple.c:46: +> Frama_C_dump_each: +> # octagon: +> {[ buffer - cmd ∈ [-436..-6] +> cmd->cmdLen - cmdLen ∈ {0} +> index + cmdLen ∈ [--..434] +> cmd->cmdLen + index ∈ [--..434] +> ]} +> ==END OF DUMP== +> [eva] octagons-pointers-simple.c:47: Reusing old results for call to cmdRead diff --git a/tests/value/oracle_gauges/octagons-pointers.res.oracle b/tests/value/oracle_gauges/octagons-pointers.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..2c58a7bd206f37b42c9c11cda6d577546e1498e6 --- /dev/null +++ b/tests/value/oracle_gauges/octagons-pointers.res.oracle @@ -0,0 +1,26 @@ +83a84,108 +> [eva] octagons-pointers.c:43: starting to merge loop iterations +> [eva] octagons-pointers.c:46: +> Frama_C_dump_each: +> # octagon: +> {[ buffer - cmd ∈ [-436..-6] +> cmd->cmdLen + index ∈ [--..434] +> ]} +> ==END OF DUMP== +> [eva] octagons-pointers.c:47: Reusing old results for call to cmdRead +> [eva] octagons-pointers.c:46: +> Frama_C_dump_each: +> # octagon: +> {[ buffer - cmd ∈ [-436..-6] +> cmd->cmdLen + index ∈ [--..434] +> ]} +> ==END OF DUMP== +> [eva] octagons-pointers.c:47: Reusing old results for call to cmdRead +> [eva] octagons-pointers.c:46: +> Frama_C_dump_each: +> # octagon: +> {[ buffer - cmd ∈ [-436..-6] +> cmd->cmdLen + index ∈ [--..434] +> ]} +> ==END OF DUMP== +> [eva] octagons-pointers.c:47: Reusing old results for call to cmdRead diff --git a/tests/value/oracle_gauges/octagons.res.oracle b/tests/value/oracle_gauges/octagons.res.oracle index 877c9b13068e01e847619bf42b92f3873f3fcb0e..f07f5b7d9bc184727b1db9fd272ec66d12fae701 100644 --- a/tests/value/oracle_gauges/octagons.res.oracle +++ b/tests/value/oracle_gauges/octagons.res.oracle @@ -11,7 +11,7 @@ < [eva] octagons.c:143: Frama_C_show_each_imprecise: [-2147483648..1] --- > [eva] octagons.c:143: Frama_C_show_each_imprecise: [-2468..1] -366,369c358,361 +371,374c363,366 < a ∈ [-1024..2147483647] < b ∈ [-1023..2147483647] < c ∈ [-1023..2147483647] @@ -21,7 +21,7 @@ > b ∈ [-181..1867] > c ∈ [-602..1446] > d ∈ [-190..1874] -371c363 +376c368 < d2 ∈ [-2147483648..1] --- > d2 ∈ [-2468..1] diff --git a/tests/value/oracle_octagon/CruiseControl.res.oracle b/tests/value/oracle_octagon/CruiseControl.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..7c3d8d711cfb271a197c462226160719fc31b075 --- /dev/null +++ b/tests/value/oracle_octagon/CruiseControl.res.oracle @@ -0,0 +1,8 @@ +979c979 +< [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {0; 1} +--- +> [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {1} +1217c1217 +< [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {0; 1} +--- +> [0]._C4_ThrottleCmd._I0_Regul_ON ∈ {1} diff --git a/tests/value/oracle_octagon/builtins_split.res.oracle b/tests/value/oracle_octagon/builtins_split.res.oracle index 4f5a68d6cdb893ccd920cc33c02545f5580bb89d..09146749136af8ba9b8d1975d16dc9d93d042e86 100644 --- a/tests/value/oracle_octagon/builtins_split.res.oracle +++ b/tests/value/oracle_octagon/builtins_split.res.oracle @@ -6,7 +6,8 @@ > [eva] builtins_split.c:104: Call to builtin Frama_C_builtin_split_all > [eva] builtins_split.c:104: Call to builtin Frama_C_builtin_split_all > [eva] builtins_split.c:104: Call to builtin Frama_C_builtin_split_all -75a83,89 +75a83,90 +> [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all > [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all > [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all > [eva] builtins_split.c:112: Call to builtin Frama_C_builtin_split_all diff --git a/tests/value/oracle_octagon/equality.res.oracle b/tests/value/oracle_octagon/equality.res.oracle index b5553e29dbc35c1e9fb26bff458b2b82b0cc9ca6..24564fbdf1425ff856a02a0ec9fe194fbaa53932 100644 --- a/tests/value/oracle_octagon/equality.res.oracle +++ b/tests/value/oracle_octagon/equality.res.oracle @@ -1,3 +1,7 @@ +60c60 +< [eva] equality.c:99: Frama_C_show_each_10_19: [10..42] +--- +> [eva] equality.c:99: Frama_C_show_each_10_19: [10..19] 75,76c75,76 < y ∈ [0..42] or UNINITIALIZED < w ∈ [0..42] or UNINITIALIZED diff --git a/tests/value/oracle_octagon/from_termin.res.oracle b/tests/value/oracle_octagon/from_termin.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..d03d84f92d569928f2f9156ff651c33acd1a291b --- /dev/null +++ b/tests/value/oracle_octagon/from_termin.res.oracle @@ -0,0 +1,2 @@ +9a10 +> [eva] from_termin.i:8: starting to merge loop iterations diff --git a/tests/value/oracle_octagon/gauges.res.oracle b/tests/value/oracle_octagon/gauges.res.oracle index 3bd3c265780ea7b9be6d67f03047adcaca64da7a..a5e47e28258fe4726d31ff83cb80079321750697 100644 --- a/tests/value/oracle_octagon/gauges.res.oracle +++ b/tests/value/oracle_octagon/gauges.res.oracle @@ -1,24 +1,17 @@ -196,197d195 -< [eva:alarm] gauges.c:156: Warning: -< signed overflow. assert -2147483648 ≤ toCopy - 1; -259,260d256 +259,260d258 < [eva:alarm] gauges.c:201: Warning: < signed overflow. assert -2147483648 ≤ numNonZero - 1; -282,286d277 +282,286d279 < [eva] gauges.c:218: Frama_C_show_each: < [eva] gauges.c:218: Frama_C_show_each: < [eva] gauges.c:218: Frama_C_show_each: < [eva:alarm] gauges.c:220: Warning: < signed overflow. assert -2147483648 ≤ n - 1; -767c758 +767c760 < numNonZero ∈ [-2147483648..8] --- > numNonZero ∈ {-1} -778c769 +778c771 < n ∈ [-2147483648..99] --- > n ∈ {-1} -839c830 -< toCopy ∈ [-2147483648..99] ---- -> toCopy ∈ {-1} diff --git a/tests/value/oracle_octagon/incompatible_states.res.oracle b/tests/value/oracle_octagon/incompatible_states.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..426fe5da2c9673132a9b84c5b02e570002c8ede6 --- /dev/null +++ b/tests/value/oracle_octagon/incompatible_states.res.oracle @@ -0,0 +1,4 @@ +58c58 +< t[0] ∈ {0; 1} +--- +> t[0] ∈ {0} diff --git a/tests/value/oracle_octagon/interpol.res.oracle b/tests/value/oracle_octagon/interpol.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..02af213df51d3952ffc2a08c91d655aadd2de281 --- /dev/null +++ b/tests/value/oracle_octagon/interpol.res.oracle @@ -0,0 +1,9 @@ +18,19c18 +< [eva] interpol.c:16: +< Frama_C_show_each_ok: {0; 1; 2; 3; 4; 5; 6}, {-64; -32; -16; -8; -4; -2; -1} +--- +> [eva] interpol.c:16: Frama_C_show_each_ok: {0; 1; 2; 3; 4; 5; 6}, [-64..-1] +24c23 +< d ∈ {-64; -32; -16; -8; -4; -2; -1} or UNINITIALIZED +--- +> d ∈ [-64..-1] or UNINITIALIZED diff --git a/tests/value/oracle_octagon/multidim-relations.res.oracle b/tests/value/oracle_octagon/multidim-relations.res.oracle index b0dec1503d0277d7ef88871cf86e10906cac0e2b..174d88b2cb0958bb6578a57ae620aef2e75a1bad 100644 --- a/tests/value/oracle_octagon/multidim-relations.res.oracle +++ b/tests/value/oracle_octagon/multidim-relations.res.oracle @@ -12,3 +12,7 @@ > [kernel] multidim-relations.c:21: 25a25 > [eva] Recording results for init_array +45d44 +< [eva] Recording results for use_array +47a47 +> [eva] Recording results for use_array diff --git a/tests/value/oracle_octagon/offsetmap.0.res.oracle b/tests/value/oracle_octagon/offsetmap.0.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6bebb89e738e4c6703b3d8b869f9d852e34a9e44 --- /dev/null +++ b/tests/value/oracle_octagon/offsetmap.0.res.oracle @@ -0,0 +1,4 @@ +40d39 +< [eva] Recording results for g +42a42 +> [eva] Recording results for g diff --git a/tests/value/oracle_octagon/offsetmap.1.res.oracle b/tests/value/oracle_octagon/offsetmap.1.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..6bebb89e738e4c6703b3d8b869f9d852e34a9e44 --- /dev/null +++ b/tests/value/oracle_octagon/offsetmap.1.res.oracle @@ -0,0 +1,4 @@ +40d39 +< [eva] Recording results for g +42a42 +> [eva] Recording results for g diff --git a/tests/value/oracle_octagon/partitioning-annots.0.res.oracle b/tests/value/oracle_octagon/partitioning-annots.0.res.oracle index cd64a1b908f4fcd56dac921a50c0bec490216e7e..141d3a1f322385d29fea8cd73951c79d349d8440 100644 --- a/tests/value/oracle_octagon/partitioning-annots.0.res.oracle +++ b/tests/value/oracle_octagon/partitioning-annots.0.res.oracle @@ -1,4 +1,4 @@ -105,106c105,106 +136,137c136,137 < x ∈ [0..44] < y ∈ [0..44] --- diff --git a/tests/value/oracle_octagon/redundant_alarms.res.oracle b/tests/value/oracle_octagon/redundant_alarms.res.oracle new file mode 100644 index 0000000000000000000000000000000000000000..913f8ab9f773d1c9ba23e01b0551932c560dbeaa --- /dev/null +++ b/tests/value/oracle_octagon/redundant_alarms.res.oracle @@ -0,0 +1,2 @@ +46a47 +> [eva] redundant_alarms.c:39: starting to merge loop iterations diff --git a/tests/value/oracle_octagon/relations.res.oracle b/tests/value/oracle_octagon/relations.res.oracle index 74aca336ba48970545ced8311cee9097bd21f1ef..1aba9b820f8395e34b9d9534ab68f1098fd62045 100644 --- a/tests/value/oracle_octagon/relations.res.oracle +++ b/tests/value/oracle_octagon/relations.res.oracle @@ -1,7 +1,68 @@ -80,81c80,82 +34,49d33 +< [eva:alarm] relations.i:41: Warning: +< signed overflow. assert -2147483648 ≤ u[5] - u[0]; +< [eva:alarm] relations.i:41: Warning: +< signed overflow. assert u[5] - u[0] ≤ 2147483647; +< [eva:alarm] relations.i:46: Warning: +< signed overflow. assert -2147483648 ≤ u[10] - u[11]; +< [eva:alarm] relations.i:46: Warning: +< signed overflow. assert u[10] - u[11] ≤ 2147483647; +< [eva:alarm] relations.i:48: Warning: +< signed overflow. assert -2147483648 ≤ u[1] - u[0]; +< [eva:alarm] relations.i:48: Warning: +< signed overflow. assert u[1] - u[0] ≤ 2147483647; +< [eva:alarm] relations.i:52: Warning: +< signed overflow. assert -2147483648 ≤ u[5] - u[1]; +< [eva:alarm] relations.i:52: Warning: +< signed overflow. assert u[5] - u[1] ≤ 2147483647; +60,61c44 +< u[0] ∈ [-2147483648..2147483646] +< [1] ∈ [--..--] +--- +> u[0..1] ∈ [-2147483648..2147483646] +67,78c50,60 +< R1 ∈ [--..--] +< R2 ∈ [--..--] +< R3 ∈ [-2147483648..2147483646] +< R4 ∈ [--..--] +< R5 ∈ [--..--] +< R6 ∈ [--..--] +< R7 ∈ {0; 1} +< A7 ∈ [--..--] +< R8 ∈ {0; 1} +< A8 ∈ [--..--] +< S1 ∈ {-1; 0; 1} +< S2 ∈ {0; 1} +--- +> R1 ∈ {0; 3} +> R2 ∈ {0; 3} +> R3 ∈ {0; 2} +> R4 ∈ {0; 2} +> R5 ∈ {1} +> R6 ∈ {0} +> R7 ∈ {1} +> A7 ∈ {0} +> A8 ∈ {1} +> S1 ∈ {0} +> S2 ∈ {1} +80,81c62,64 < e ∈ [--..--] < f ∈ [--..--] --- > e ∈ {1} > f[bits 0 to 7] ∈ {1; 4} > [bits 8 to 31] ∈ [--..--] +102c85 +< R7 FROM g (and SELF) +--- +> R7 FROM g +104d86 +< R8 FROM g (and SELF) +107c89 +< S2 FROM pCs; S_pCs[0]{.L0; .L1} (and SELF) +--- +> S2 FROM pCs; S_pCs[0]{.L0; .L1} +112c94 +< A7; R8; A8; S1; S2; c; e; f; tmp; tmp_0; S_pCs[0]{.T13; .T; .L8} +--- +> A7; A8; S1; S2; c; e; f; tmp; tmp_0; S_pCs[0]{.T13; .T; .L8} diff --git a/tests/value/oracle_octagon/struct2.res.oracle b/tests/value/oracle_octagon/struct2.res.oracle index 0422f2e21dd0d1c733352d3cab30a7e36443ca16..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/tests/value/oracle_octagon/struct2.res.oracle +++ b/tests/value/oracle_octagon/struct2.res.oracle @@ -1,7 +0,0 @@ -77,80d76 -< accessing out of bounds index. assert 0 ≤ (int)(i + j); -< [eva:alarm] struct2.i:185: Warning: -< accessing out of bounds index. assert (int)(i + j) < 2; -< [eva:alarm] struct2.i:185: Warning: -98d93 -< [scope:rm_asserts] removing 2 assertion(s) diff --git a/tests/value/oracle_octagon/unroll.res.oracle b/tests/value/oracle_octagon/unroll.res.oracle index c82ddd4f31807c175f11f4e55c96313f87a53446..b0b04dfe12a225825d9f1736faa4efc66d5f5b03 100644 --- a/tests/value/oracle_octagon/unroll.res.oracle +++ b/tests/value/oracle_octagon/unroll.res.oracle @@ -1,4 +1,6 @@ -20c20 +14a15 +> [eva] unroll.i:39: starting to merge loop iterations +20c21 < G ∈ [17739..2147483647] --- > G ∈ [17854..2147483647] diff --git a/tests/value/oracle_octagon/unroll_simple.res.oracle b/tests/value/oracle_octagon/unroll_simple.res.oracle index 8a48c42f84b464b622a56e6b0bdf325a1423af5f..0aead1b2497a8c7979e9bfe3c5945cdb38fb4408 100644 --- a/tests/value/oracle_octagon/unroll_simple.res.oracle +++ b/tests/value/oracle_octagon/unroll_simple.res.oracle @@ -1,4 +1,6 @@ -17c17 +11a12 +> [eva] unroll_simple.i:16: starting to merge loop iterations +17c18 < G ∈ [8772..2147483647] --- > G ∈ [8896..2147483647] diff --git a/tests/value/partitioning-annots.c b/tests/value/partitioning-annots.c index d3ab58aaa5069ea02e5298ffff4abd6874bae81b..393b1fe4bbd3e01a353013158fd7fa781ec5b43c 100644 --- a/tests/value/partitioning-annots.c +++ b/tests/value/partitioning-annots.c @@ -162,6 +162,61 @@ void test_loop_split() } } +/*@ + assigns \result, *p \from i; + behavior error: + assumes nondet == 0; + assigns \result, *p \from i; + ensures \result == -1; + ensures \initialized(p) && *p == \old(i); + behavior positive: + assumes nondet > 0; + assigns \result \from i; + ensures \result >= 10; + behavior negative: + assumes nondet < 0; + assigns \result \from i; + ensures \result <= -10; + disjoint behaviors; + complete behaviors; +*/ +int spec(int i, int* p); + +int body(int i, int *p) { + int i2 = i / 2; + int absolute = i2 < 0 ? -i2 : i2; + int state = nondet % 2; + //@ split state; + if (state < 0) + return - 10 - absolute; + if (state > 0) + return 10 + absolute; + *p = i; + return -1; +} + +/* Tests the application of multiple splits according to the return value of a + call, to keep in the caller some state partitioning from the callee. + The splits must be defined after the call, so the state partitioning from the + callee must be kept until all splits are performed. + Tests this whether the function body or a specification is used. */ +void test_splits_post_call (void) { + int x, y, error; + int i = Frama_C_interval(-1000, 1000); + int r = spec(i, &x); + //@ split r < -1; + //@ split r > -1; + if (r == -1) + error = x; // There should be no alarm. + Frama_C_show_each_spec(r, x); // There should be three states. + r = body(i, &y); + //@ split r < -1; + //@ split r > -1; + if (r == -1) + error = y; // There should be no alarm. + Frama_C_show_each_body(r, y); // There should be three states. +} + void test_history() { int i = Frama_C_interval(0,1); @@ -225,4 +280,5 @@ void main(void) test_split(); test_dynamic_split(); test_dynamic_split_predicate(); + test_splits_post_call(); } diff --git a/tests/value/statistics.i b/tests/value/statistics.i new file mode 100644 index 0000000000000000000000000000000000000000..329dbef213c9393b226943744f7d24d1694273d6 --- /dev/null +++ b/tests/value/statistics.i @@ -0,0 +1,20 @@ +/* run.config + LOG: @PTEST_NAME@.csv + STDOPT: +" -eva-statistics-file ./@PTEST_NAME@.csv" +*/ + +/* This test only dump statistics in the default configuration + to avoid oracle duplication. */ + +void g(int i) {} + +void f(int n) { + for (int i = 0 ; i < n ; i++) { + g(i); + } +} + +int main(int n) { + f(n); + f(n-1); +} diff --git a/tools/hdrck/frama-c-hdrck.opam b/tools/hdrck/frama-c-hdrck.opam index 95cd527fb24a67755af49e542304e628191bedea..acd43dffc4a7122b1a70a7ed71d9f1d2835a920b 100644 --- a/tools/hdrck/frama-c-hdrck.opam +++ b/tools/hdrck/frama-c-hdrck.opam @@ -1,7 +1,7 @@ opam-version: "2.0" name: "frama-c-hdrck" synopsis: "Frama-C header check tool" -version: "26.0+dev" +version: "27.0+dev" description:""" Performs all checks related to file headers as required by the Frama-C continuous integration. diff --git a/tools/lint/frama-c-lint.opam b/tools/lint/frama-c-lint.opam index 1965b30ff49e4c3289e1f4e69eda47bdec0fe2cc..08041265966df4bcb34b87e4a768a7faad40342b 100644 --- a/tools/lint/frama-c-lint.opam +++ b/tools/lint/frama-c-lint.opam @@ -1,7 +1,7 @@ opam-version: "2.0" name: "frama-c-lint" synopsis: "Frama-C lint tool" -version: "26.0+dev" +version: "27.0+dev" description:""" Performs all checks related to source code formatting as required by the Frama-C continuous integration. Namely: OCP-indent for ML files, clang-format for E-ACSL