From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!news.szaf.org!news.enyo.de!.POSTED!not-for-mail From: Florian Weimer Newsgroups: comp.lang.ada Subject: Re: SPARK and integer arithmetic Date: Sun, 18 Sep 2016 20:01:23 +0200 Message-ID: <87twddw0i4.fsf@mid.deneb.enyo.de> References: <87poo1a57p.fsf@mid.deneb.enyo.de> Mime-Version: 1.0 Content-Type: text/plain X-Trace: news.enyo.de 1474221683 16821 192.168.18.20 (18 Sep 2016 18:01:23 GMT) X-Complaints-To: news@enyo.de Cancel-Lock: sha1:dZmI3/+SLz8KwXRWjDJMwCY4fas= Xref: news.eternal-september.org comp.lang.ada:31807 Date: 2016-09-18T20:01:23+02:00 List-Id: * Simon Wright: > $ gnatprove -P sum > Phase 1 of 2: generation of Global contracts ... > Phase 2 of 2: flow analysis and proof ... > sum.ads:8:14: medium: postcondition might fail, cannot prove Add'Result = A + B (e.g. when A = 0 and Add'Result = -1 and B = 1) Nice, that certainly looks more polished. If I drop the pre-condition, I get a report about a failed overflow check, which is what I expect: sum.adb:8:16: medium: overflow check might fail (e.g. when A = -2147483648 and B = -1) I've tried to model some of the things I'm actually dealing with (this comes from the glibc dynamic linker). package Sum with SPARK_Mode is type Address is mod 2**32; -- Used to model non-wrapping arithmetic. type Address_Integer is range 0 .. Address'Last; -- Approximation of struct link_map. type Link_Map is record L_Addr : Address; -- In the original, these fields are actually nested in an -- array. P_Vaddr : Address; P_Memsz : Address; end record with Dynamic_Predicate => Address_Integer (L_Addr) + Address_Integer (P_Vaddr) + Address_Integer (P_Memsz) <= Address_Integer'Last + 1; function Address_Inside_Object (L : Link_Map; Addr : Address) return Boolean with Post => Address_Inside_Object'Result = ((L.L_Addr <= Addr) and (Address_Integer (Addr) < (Address_Integer (L.L_Addr) + Address_Integer (L.P_Vaddr) + Address_Integer (L.P_Memsz)))); end Sum; package body Sum with SPARK_Mode is -- Ada translation of _dl_addr_inside_object (without the loop -- over l_phnum). function Address_Inside_Object (L : Link_Map; Addr : Address) return Boolean is Reladdr : constant Address := Addr - L.L_Addr; begin -- reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz return Reladdr - L.P_Vaddr < L.P_Memsz; end Address_Inside_Object; end Sum; I use this project file in an attempt to activate a configuration pragma file, also shown below. project Sum is for Source_Dirs use ("."); package Compiler is for Local_Configuration_Pragmas use "gnat.adc"; end Compiler; end Sum; -- gnat.adc pragma Overflow_Mode (General => Strict, Assertions => Eliminated); The intent is that I can write unbounded integer arithmetic in predicates and post-conditions. Not too surprisingly, gnatprove can't deal with this (I've already been told it's beyond alt-ergo, and Z3 can only brute-force it). But perhaps there is a way to express the unbounded arithmetic so that there is less work left for the prover? The intent is to show that the transformation found in the original sources is right. It is related to the usual technique to eliminate one comparison from an interval check. More background is here: