emery@MITRE-BEDFORD.ARPA (Emery) (05/02/88)
The problem with most portability bugs like this is that it's very hard to capture and machine-analyze the rules, partly because you can't be sure what the programmer really means... In this example, the meaning is obvious, but implementations can do different things: package foo is type t is range -2**31 .. 2**31 -1; -- no problems (assuming 32 bit -- integer types) subtype positive_t is t range 0 .. 2**31 -1; -- here's the problem. -- the expressions in the range declaration -- are of type T. -- 2**31 is not in the allowed range of type -- T, but (2**31 -1) is in the range of T -- the language doesn't require that -- intermediate results be constraint-checked, but -- a compiler can do this. -- bottom line: -- one compiler compiled and ran this code -- without complaint -- another issued a compiler warning that the -- expression would raise constraint_error, and -- the code did raise constraint_error. end foo; Here's another potential bug, but this is hard to catch because of the possible intended meanings: package foo is function incr return integer; type t_rec is i1 : integer := incr; i2 : integer := incr; end t_rec; my_trec : t_rec; end foo; package body foo is count : integer := 0; function incr return integer is begin count := count + 1; return count; end incr; end foo; Now, the order of evaluation of record components is not defined by the language, so you cannot assert that either of the following is true: my_trec.i1 = 1 and my_trec.i2 = 2 -- don't know if my_trec -- was first call to incr! my_trec.i2 = (my_trec.i1 + 1) -- because it very well could -- be that i2 was initialized -- first I am not sure if you can assert the following: abs(my_trec.i1 - my_trec.i2) = 1 -- only true if there can be -- NO calls to incr during -- object initialization by -- anyone else -- I don't THINK the language -- requires this dave emery emery@mitre-bedford.arpa