unreachable code removed by the compiler

Discussions related to Visual Prolog
Gildas Menier
VIP Member
Posts: 78
Joined: 8 Jun 2004 23:01

unreachable code removed by the compiler

Unread post by Gildas Menier » 29 Nov 2008 17:08

7.2 is a nice jump (most of the troubles I had with 7.103 are gone ;) )

The type checker is an interesting feature - very tricky : updating SCS for 7.2 (sorry, I cannot stand msglayer's logic) I found something disturbing :

This is my previous code for one predicate (so far ok for 7.1) :

Code: Select all

predicates     receive: (binary D) -> binary determ (i).     clauses         receive(D) = BinRes :-                  try                     Nb = wsrecv( mySocket,  D,  binary::getSize(D), 0),                     if (Nb<0) then                         if not( wSAEWOULDBLOCK = wsagetlasterror()) then isRunning := false end if,                         setError() % pb                     else                         if (Nb=0) then isRunning := false, close, fail  % the connexion has been closed by the peer                         else                             BinRes = binary::createAtomic(Nb), % only keep the incoming data % NV72                             memory::copy(uncheckedconvert(pointer, BinRes), uncheckedConvert(pointer, D), Nb)                         end if                     end if                     catch _Err do  if not( wSAEWOULDBLOCK = wsagetlasterror()) then isRunning := false end if, setError() end try          .%
The compiler complains about the first 'if (Nb<0) then' test and states that 'Due to the range of the involved domains this test always fails'.

Code: Select all

        wsrecv: (socket_d Socket, binary Bin, integer Length, integer Flags) -> integer language c as "_vp_recv".

wsrecv returns an integer, so my first guess is that Nb should be an integer and could be negative, so the test seems legal to me.


Anyway, the compiler decides to discard the error management code in the 'then' part (with a polite warning that I understand as 'hey Gildas, your code is messy ;) let me fix it ') . No error is detected and the compiler produces a code that won't manage any error (given by a negative integer value as output from wsrecv).

A guess : Obviously, because of the use of Nb in createAtomic and memory::copy, the compiler assumed that Nb should be a byteCount or something positive (even if it is guarded by the if/then/else parts to avoid an implicit convertion of a negative Nb).

Just a coarse test shows this guess could be a good one : adding math::abs(Nb) in the last part quietes the optimizer and no code is removed :

Code: Select all

predicates     receive: (binary D) -> binary determ (i).     clauses         receive(D) = BinRes :-                  try                     Nb = wsrecv( mySocket,  D,  binary::getSize(D), 0),                     if (Nb<0) then                         if not( wSAEWOULDBLOCK = wsagetlasterror()) then isRunning := false end if,                         setError() % pb                     else                         if (Nb=0) then isRunning := false, close, fail  % the connexion has been closed by the peer                         else                             BinRes = binary::createAtomic(math::abs(Nb)), % only keep the incoming data % NV72                             memory::copy(uncheckedconvert(pointer, BinRes), uncheckedConvert(pointer, D), math::abs(Nb))                         end if                     end if                     catch _Err do  if not( wSAEWOULDBLOCK = wsagetlasterror()) then isRunning := false end if, setError() end try          .%
Since the initial code was 'incorrectly corrected' and fixed by the optimizer (and detected as warning), I suggest that the 'due to...' + '...code removed by the compiler' become both 'error' and no 'warning' anymore (or let the user choose a warning level parameter)

best regards

Gildas

Gildas Menier
VIP Member
Posts: 78
Joined: 8 Jun 2004 23:01

Unread post by Gildas Menier » 29 Nov 2008 17:45

another tricky one :

Code: Select all

 if ((P-lfen)>=0) then PosLeft = P-lfen else PosLeft = 0 end if,
P is a charCount, lfen is an integer fact.

This line triggers a 'due to...'+'unreachable...' and discards 'PosLeft=0' (P-lfen seems to always be >=0)

but :

Code: Select all

if (P>=lfen) then PosLeft = P-lfen else PosLeft = 0 end if,
is ok (no complaining). So P-lfen>=0 is not the same as P>=lfen.

Gildas
Attachments
i1.jpg
i1.jpg (19.23 KiB) Viewed 3277 times
i2.jpg
i2.jpg (17.58 KiB) Viewed 3277 times

User avatar
Thomas Linder Puls
VIP Member
Posts: 2444
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls » 29 Nov 2008 20:16

This particular warning it described in the wiki article: Warning c666: Due to the range of the involved domain this test always succeeds

Take a look at this code, and especially notice the use of tryConvert

Code: Select all

class predicates     receive: (binary D) -> binary determ (i). clauses     receive(D) = BinRes :-         try             RC = wsrecv(mySocket, D, binary::getSize(D), 0),             if Nb = tryConvert(byteCount, RC) then                 if Nb = 0 then                     isRunning := false,                     close,                     fail                 else                     BinRes = binary::createAtomic(Nb),                     memory::copy(uncheckedconvert(pointer, BinRes), uncheckedConvert(pointer, D), Nb)                 end if,             else                 onError()             end if         catch _Err do             onError()         end try.   class predicates     onError : () failure. clauses     onError() :-         if not(wSAEWOULDBLOCK = wsagetlasterror()) then             isRunning := false         end if,         setError().
Likewise here:

Code: Select all

if PosLeft = tryConvert(charCount, P-lfen) then else     PosLeft = 0 end if,
Regards Thomas Linder Puls
PDC

Gildas Menier
VIP Member
Posts: 78
Joined: 8 Jun 2004 23:01

Unread post by Gildas Menier » 29 Nov 2008 21:42

Interesting.

I think there should be much more than a warning here : the fix applied by the compiler - discarding a piece of code - may be inapropriate for the general case. A great care must be provided by the programmer to deal with this - and it may change the way of designing code.

Finding that a-b>0 is different from a>b; that a type may been shrunk to a more specific 'subtype' (for code optimization's sake) urges for very carefull scanning of code (I do agree with Kari's view).

I still think this warning is much more than a common warning : its real meaning finds its place between pinpointing a mistake of the programmer and a possible misunderstanding/mishandling of the code by the compiler.

I will anyway consider this warning as a 'red alert' in the code :)

Thomas, thank you for the answer/reference.

Regards

Gildas

Gildas Menier
VIP Member
Posts: 78
Joined: 8 Jun 2004 23:01

Unread post by Gildas Menier » 29 Nov 2008 22:19

... found something in the compiler's help to make some warnings behave as errors /warnings{...}.
:D

Gildas

Post Reply