A sample of Ada* Programmer Errors John B. Goodenough Wang Institute of Graduate Studies Tyng Road Tyngsboro, ma 01879 March 6, 1986 Interim Draft Ada is a registered trademark of the U. S



Download 75.09 Kb.
Page1/2
Date31.01.2017
Size75.09 Kb.
#12953
  1   2
A Sample of Ada* Programmer Errors John B. Goodenough Wang Institute of Graduate Studies Tyng Road Tyngsboro, MA 01879 March 6, 1986 Interim Draft * Ada is a registered trademark of the U. S. Government (Ada Joint Program Office) Ada Programmer Errors 6-Mar-86 20:03:24 TABLE OF CONTENTS 0.0 different uses of => . . . . . . . . . . . . . . . . . . . . . . . . 1 2.3 illegal use of underscore . . . . . . . . . . . . . . . . . . . . . . 2 2.4.1 -1 is not a literal . . . . . . . . . . . . . . . . . . . . . . . . 2 2.5 one character string literals or character literals . . . . . . . . . 2 2.9 inadvertent use of reserved words . . . . . . . . . . . . . . . . . . 3 3.2 anonymous array types . . . . . . . . . . . . . . . . . . . . . . . . 3 3.2.2 Using non-universal constants in number decls. . . . . . . . . . . 3 3.3.1 types vs. subtypes; strong typing . . . . . . . . . . . . . . . . . 3 3.3.1 Using base type name in type definition . . . . . . . . . . . . . . 4 3.3.1(4) type declarations declare distinct types . . . . . . . . . . . . 4 3.3.2 Attempt to use subtype as private type . . . . . . . . . . . . . . 4 3.5.1 'FIRST of enumeration literal has position number zero . . . . . . 5 3.5.5 'RANGE and 'LENGTH not defined for scalar types . . . . . . . . . . 5 3.5.5 VAL attribute does not depend on rep. clause . . . . . . . . . . . 5 3.5.9 Failure to include range in fixed point declaration . . . . . . . . 5 3.5.9 Fixed point subtype declarations . . . . . . . . . . . . . . . . . 6 3.6 Lower bounds of arrays not always 1 . . . . . . . . . . . . . . . . . 6 3.6 No partially constrained arrays . . . . . . . . . . . . . . . . . . . 6 3.6.2 no numeric operators for array types . . . . . . . . . . . . . . . 6 3.6.3 Length of actual string parameter arguments . . . . . . . . . . . . 7 3.6.3(1) the index subtype for STRING is Integer . . . . . . . . . . . . 7 3.7 No anonymous array types for record components . . . . . . . . . . . 7 3.7(5) no sliding for record component initializations . . . . . . . . . 7 3.7.1 NUMERIC_ERROR for unconstrained record objects . . . . . . . . . . 8 3.8.1 Using an incomplete type prematurely . . . . . . . . . . . . . . . 8 3.9(2) basic declarations not allowed after bodies . . . . . . . . . . . 8 3.9(6) Activating a task whose body has not been elaborated . . . . . . . 9 4.0.3 Using Pointers and .all . . . . . . . . . . . . . . . . . . . . . . 9 4.1.3 Using .all to access whole records . . . . . . . . . . . . . . . . 9 4.3(4) aggregates with only one component . . . . . . . . . . . . . . . . 10 4.3.2 Character literals vs string literals . . . . . . . . . . . . . . . 10 4.3.2 Rules for using others choice . . . . . . . . . . . . . . . . . . . 10 4.4 Can't parenthesize range . . . . . . . . . . . . . . . . . . . . . . 11 4.5.4 precedence of unary minus . . . . . . . . . . . . . . . . . . . . . 11 4.9(8) Size of a record is not static . . . . . . . . . . . . . . . . . . 11 5.2 Failure to use aggregates in assignments . . . . . . . . . . . . . . 11 5.2.1(2) No sliding of array components in record aggregates . . . . . . 12 5.4(2) not all choices can be parenthesized . . . . . . . . . . . . . . . 12 5.4(4) Use of RANGE attribute in loops and case statements . . . . . . . 12 5.5 negative bounds for loop parameters . . . . . . . . . . . . . . . . . 13 6.2 Slices used as actual parameters . . . . . . . . . . . . . . . . . . 13 6.2(2) Incorrect use of formal parameter modes . . . . . . . . . . . . . 14 6.2(5) Assignment to component designated by OUT parameter . . . . . . . 14 6.3 ; instead of IS in subprogram bodies . . . . . . . . . . . . . . . . 14 Ada Programmer Errors 6-Mar-86 20:03:24 6.3(2) Bodies that use IS rather than semicolon . . . . . . . . . . . . . 14 6.3.1(5) can't omit IN in parameter decl if it is present in body . . . . 15 6.3.2(4) dependence on body due to INLINE . . . . . . . . . . . . . . . . 15 6.6(1) Parameter names not considered in overloaded declarations . . . . 15 8.3 visibility of operators . . . . . . . . . . . . . . . . . . . . . . . 16 8.3 visibility rules for operators . . . . . . . . . . . . . . . . . . . 15 8.3(15) Object declaration hides outer procedure declaration . . . . . . 17 8.3(18) Need a use clause to get visibility of operators . . . . . . . . 17 8.4(5) Conflict with a name declared in Standard . . . . . . . . . . . . 18 8.4(6) Effect of USE on generic subprograms . . . . . . . . . . . . . . . 18 8.4(6) Use clause and renamed exceptions . . . . . . . . . . . . . . . . 18 8.5 ignoring constraints in renaming . . . . . . . . . . . . . . . . . . 20 8.5 renaming task entries . . . . . . . . . . . . . . . . . . . . . . . . 19 9.0 Deadlock because of exception propagation . . . . . . . . . . . . . . 20 9.1(4) Can't use task type name in its own body . . . . . . . . . . . . . 21 9.2 Use task types instead of single tasks . . . . . . . . . . . . . . . 21 9.4 Nested task termination and leaving block . . . . . . . . . . . . . . 22 9.4(13) Termination of library tasks . . . . . . . . . . . . . . . . . . 22 9.5 deadlock by mismatched entry indexes . . . . . . . . . . . . . . . . 22 9.6 delay 2.5*minutes is illegal . . . . . . . . . . . . . . . . . . . . 23 9.6(1) Delay statments can be used in the main program . . . . . . . . . 23 9.7.1 evaluation of guards . . . . . . . . . . . . . . . . . . . . . . . 23 9.7.1(6) "fairness" is not guaranteed . . . . . . . . . . . . . . . . . . 23 9.10 delay 0.0 can synchronize an abort . . . . . . . . . . . . . . . . . 24 10.1(6) recompiling a library subprogram body . . . . . . . . . . . . . . 24 10.1.1 A with clause is not like an Include . . . . . . . . . . . . . . . 25 10.1.1 confusion of with and use . . . . . . . . . . . . . . . . . . . . 25 10.2 Spelling SEPARATE correctly . . . . . . . . . . . . . . . . . . . . 25 10.2(5) Overloaded subunits are illegal . . . . . . . . . . . . . . . . . 25 10.2(5) Subunits cannot be operators . . . . . . . . . . . . . . . . . . 26 10.5(3) Failure to use pragma ELABORATE for generic units . . . . . . . . 26 11.4.2 Handling exceptions raised in declarations . . . . . . . . . . . . 27 12.1 Generics are not macros . . . . . . . . . . . . . . . . . . . . . . 28 12.1 No out mode for generic formal objects . . . . . . . . . . . . . . . 27 12.1 no overloaded generic units . . . . . . . . . . . . . . . . . . . . 27 12.1(2) generic subprograms bodies can't be delared with generic parameter 28 14.3 Associating two file variables with a terminal . . . . . . . . . . . 29 14.3 I/O calls in tasks . . . . . . . . . . . . . . . . . . . . . . . . . 28 14.3.5(3) PUT at the end of the program . . . . . . . . . . . . . . . . . 29 14.3.6(3) GET for chars skips line terminators . . . . . . . . . . . . . 29 14.3.7(6) Failing to advance after DATA_ERROR for INTEGER GET . . . . . . 29 14.3.9(6) Failing to advance after DATA_ERROR for ENUM GET . . . . . . . 29 BL 02.03 illegal use of underscore . . . . . . . . . . . . . . . . . . . 2 BL 02.09 inadvertent use of reserved words . . . . . . . . . . . . . . . 3 BL 03.02.02 Using non-universal constants in number decls. . . . . . . . 3 Ada Programmer Errors 6-Mar-86 20:03:24 BL 03.05.09 Fixed point subtype declarations . . . . . . . . . . . . . . 6 BL 04.04 Can't parenthesize range . . . . . . . . . . . . . . . . . . . . 11 BL 06.03 ; instead of IS in subprogram bodies . . . . . . . . . . . . . . 14 BL 06.03(02) Bodies that use IS rather than semicolon . . . . . . . . . . 14 BL 10.02 Spelling SEPARATE correctly . . . . . . . . . . . . . . . . . . 25 BL 10.02(05) Overloaded subunits are illegal . . . . . . . . . . . . . . 25 BL 10.02(05) Subunits cannot be operators . . . . . . . . . . . . . . . . 26 NC 02.05 one character string literals or character literals . . . . . . 2 NC 03.02 anonymous array types . . . . . . . . . . . . . . . . . . . . . 3 NC 03.03.01 types vs. subtypes; strong typing . . . . . . . . . . . . . . 3 NC 03.03.01 Using base type name in type definition . . . . . . . . . . . 4 NC 03.03.01(04) type declarations declare distinct types . . . . . . . . 4 NC 03.03.02 Attempt to use subtype as private type . . . . . . . . . . . 4 NC 03.06 Lower bounds of arrays not always 1 . . . . . . . . . . . . . . 6 NC 03.06 No partially constrained arrays . . . . . . . . . . . . . . . . 6 NC 03.06.03 Length of actual string parameter arguments . . . . . . . . . 7 NC 03.08.01 Using an incomplete type prematurely . . . . . . . . . . . . 8 NC 05.02 Failure to use aggregates in assignments . . . . . . . . . . . . 11 NC 06.02(02) Incorrect use of formal parameter modes . . . . . . . . . . 14 NC 10.01.01 A with clause is not like an Include . . . . . . . . . . . . 25 NC 10.01.01 confusion of with and use . . . . . . . . . . . . . . . . . . 25 NC 12.01 Generics are not macros . . . . . . . . . . . . . . . . . . . . 28 NU 00.00 different uses of => . . . . . . . . . . . . . . . . . . . . . . 1 NU 02.04.01 -1 is not a literal . . . . . . . . . . . . . . . . . . . . . 2 NU 03.05.05 'RANGE and 'LENGTH not defined for scalar types . . . . . . . 5 NU 03.05.09 Failure to include range in fixed point declaration . . . . . 5 NU 03.06.02 no numeric operators for array types . . . . . . . . . . . . 6 NU 03.07 No anonymous array types for record components . . . . . . . . . 7 NU 03.09(02) basic declarations not allowed after bodies . . . . . . . . 8 NU 04.0.03 Using Pointers and .all . . . . . . . . . . . . . . . . . . . 9 NU 04.01.03 Using .all to access whole records . . . . . . . . . . . . . 9 NU 04.03(04) aggregates with only one component . . . . . . . . . . . . . 10 NU 04.03.02 Character literals vs string literals . . . . . . . . . . . . 10 NU 04.05.04 precedence of unary minus . . . . . . . . . . . . . . . . . . 11 NU 05.02.01(02) No sliding of array components in record aggregates . . . 12 NU 05.04(02) not all choices can be parenthesized . . . . . . . . . . . . 12 NU 05.05 negative bounds for loop parameters . . . . . . . . . . . . . . 13 NU 06.03.01(05) can't omit IN in parameter decl if it is present in body 15 NU 06.06(01) Parameter names not considered in overloaded declarations . 15 NU 08.05 renaming task entries . . . . . . . . . . . . . . . . . . . . . 19 NU 12.01 No out mode for generic formal objects . . . . . . . . . . . . . 27 NU 12.01 no overloaded generic units . . . . . . . . . . . . . . . . . . 27 NU 12.01(02) generic subprograms bodies can't be delared with generic par 28 UC 04.03.02 Rules for using others choice . . . . . . . . . . . . . . . . 10 UC 09.07.01 evaluation of guards . . . . . . . . . . . . . . . . . . . . 23 UE 03.05.01 'FIRST of enumeration literal has position number zero . . . 5 UE 03.05.05 VAL attribute does not depend on rep. clause . . . . . . . . 5 UE 03.06.03(01) the index subtype for STRING is Integer . . . . . . . . . 7 Ada Programmer Errors 6-Mar-86 20:03:24 UE 03.07(05) no sliding for record component initializations . . . . . . 7 UE 03.07.01 NUMERIC_ERROR for unconstrained record objects . . . . . . . 8 UE 03.09(06) Activating a task whose body has not been elaborated . . . . 9 UE 04.09(08) Size of a record is not static . . . . . . . . . . . . . . . 11 UE 05.04(04) Use of RANGE attribute in loops and case statements . . . . 12 UE 06.02 Slices used as actual parameters . . . . . . . . . . . . . . . . 13 UE 06.02(05) Assignment to component designated by OUT parameter . . . . 14 UE 06.03.02(04) dependence on body due to INLINE . . . . . . . . . . . . 15 UE 08.03 visibility of operators . . . . . . . . . . . . . . . . . . . . 16 UE 08.03 visibility rules for operators . . . . . . . . . . . . . . . . . 15 UE 08.03(15) Object declaration hides outer procedure declaration . . . . 17 UE 08.03(18) Need a use clause to get visibility of operators . . . . . . 17 UE 08.04(05) Conflict with a name declared in Standard . . . . . . . . . 18 UE 08.04(06) Effect of USE on generic subprograms . . . . . . . . . . . . 18 UE 08.04(06) Use clause and renamed exceptions . . . . . . . . . . . . . 18 UE 08.05 ignoring constraints in renaming . . . . . . . . . . . . . . . . 20 UE 09.0 Deadlock because of exception propagation . . . . . . . . . . . . 20 UE 09.01(04) Can't use task type name in its own body . . . . . . . . . . 21 UE 09.02 Use task types instead of single tasks . . . . . . . . . . . . . 21 UE 09.04 Nested task termination and leaving block . . . . . . . . . . . 22 UE 09.04(13) Termination of library tasks . . . . . . . . . . . . . . . . 22 UE 09.05 deadlock by mismatched entry indexes . . . . . . . . . . . . . . 22 UE 09.06 delay 2.5*minutes is illegal . . . . . . . . . . . . . . . . . . 23 UE 09.06(01) Delay statments can be used in the main program . . . . . . 23 UE 09.07.01(06) "fairness" is not guaranteed . . . . . . . . . . . . . . 23 UE 09.10 delay 0.0 can synchronize an abort . . . . . . . . . . . . . . . 24 UE 10.01(06) recompiling a library subprogram body . . . . . . . . . . . 24 UE 10.05(03) Failure to use pragma ELABORATE for generic units . . . . . 26 UE 11.04.02 Handling exceptions raised in declarations . . . . . . . . . 27 UE 14.03 Associating two file variables with a terminal . . . . . . . . . 29 UE 14.03 I/O calls in tasks . . . . . . . . . . . . . . . . . . . . . . . 28 UE 14.03.05(03) PUT at the end of the program . . . . . . . . . . . . . . 29 UE 14.03.06(03) GET for chars skips line terminators . . . . . . . . . . 29 UE 14.03.07(06) Failing to advance after DATA_ERROR for INTEGER GET . . . 29 UE 14.03.09(06) Failing to advance after DATA_ERROR for ENUM GET . . . . 29 Ada Programmer Errors 6-Mar-86 20:03:24 0 Introduction This document contains a set of errors that have been reported to me after I asked people to tell me about programming errors they have made or observed. Some of the errors have also been found by inspecting vendor error reports, looking at just those error reports where the compiler was correct. I have found that Ada-related programming errors can be usefully classified as follows. These classes are shown in the Table of Contents and for each error. . PERCEIVED NON-UNIFORMITIES (NU) in the language: exceptions to rules that are in the minds of programmers, e.g., . the precedence of unary minus is different from the precedence of other unary operators (although the same as the precedence of binary minus) . NEW CONCEPTS (NC): differences from previously used programming languages that cause confusion, e.g., . each type declaration declares a distinct type . UNAVOIDABLE COMPLEXITIES (UC): complex rules that trip up the everyday programmer, e.g., . rules for use of OTHERS in array aggregates . BLUNDERS (BL): mistakes that are easy to make even though the rules are clear, e.g., . inadvertent use of reserved words as in type Direction is (Forward, Reverse, Up, Down, Left, Right); . UNEXPECTED EFFECTS (UE): unappreciated consequences of rules, leading to subtle bugs in programs, e.g., . effect of attempting to read the sequence 13 16.2 with GET instantiated for type INTEGER. The list of errors, as reported, follows, sorted in Reference Manual order. Ada Programmer Errors 6-Mar-86 20:03:24 1 00.00 ***************************************************************************** !section 00.00 ER-00005 !class NU !topic different uses of => !experience none The students with very little programming experience (usually only Basic) also report an interesting problem. They cannot seem to get the meaning of the compound delemeter arrow (=>) because it is used in so many places... case x is when 1 => ... exception when Constraint_Error => ... A : array (1 .. 10) of integer; begin A := (1 .. 3 => 2, 5 ! 7 => 3, others => 8); text_io.put (file => f, item => "hi john... are you at wang now?"); ***************************************************************************** !section 00.00 ER-00082 !class NU !topic different uses of => John Goodenough has noted in his survey that the use of the => operator tends to cause problems for those who are new to Ada. This is accompanied by a perception that it is used differently in different contexts. I believe this perception is incorrect; the use of the symbol is completely uniform. In general, its use in the form => . Why, then, do people have so much trouble with it? (And I had trouble with it, too, when I first encountered it.) The answer, I maintain, is because the symbol looks like an arrow, and that arrow points in the wrong direction. An arrow looks like an assignment, and we assign values to names, not vice versa. Since <= is not available, I think a direction neutral symbol, perhaps ==, would have been a better choice. It is perhaps too late to make this change now; on the other hand, perhaps later versions of the language could support it as an alternative. Ada Programmer Errors 6-Mar-86 20:03:24 2 02.03 ***************************************************************************** !section 02.03 ER-00023 !class BL !topic illegal use of underscore Invalid Identifiers and Numeric Literals: A__B, A_, _A, 3_, 3__0, 3_.0, 3._0, etc. ***************************************************************************** !section 02.04.01 ER-00083 !class NU !topic -1 is not a literal -1 is not a literal but instead is an expression. Usually this doesn't make any difference, but it does make a difference when you are using a numeric type that has been declared in a package: package P is type My_Integer is range 1..100; end P; X : P.My_Integer := 1; -- okay Y : P.My_Integer := -1; -- illegal The "-" operator is not directly visible because there is no use clause for P. The fact that the operators for My_Integer are not visible is not so confusing when one writes what looks like an expression, e.g.: Z : Boolean := X < Y; -- illegal; "<" not visible At least here it's clear that "<" is being used as an operator. But programmers familiar with other languages are not always used to thinking of -1 as an expression containing an operator. The illegality of Y's initialization expression comes as a shock! ***************************************************************************** !section 02.05 ER-00026 !class NC !topic one character string literals or character literals procedure P is C : Character := 'z'; S : String(1..1); begin S := C; C := S; C := "z"; S := 'z'; end P; Incompatible types problem (easily corrected though). Incorrect use of Ada Programmer Errors 6-Mar-86 20:03:24 3 02.05 quotation characters (easily corrected). ***************************************************************************** !section 02.09 ER-00018 !class BL !topic inadvertent use of reserved words type Greek_Letters is (Alpha, Beta, Gamma, Delta, Epsilon); type Direction is (Forward, Reverse, Up, Down); type Digits is range 0 .. 9; Thou shalt not use the reserved words in vain. ***************************************************************************** !section 03.02 ER-00024 !class NC !topic anonymous array types A1, A2 : array(1 .. 10) of Boolean; . . . A1 := A2; The old anonymous array type problem. ***************************************************************************** !section 03.02.02 ER-00020 !class BL !topic Using non-universal constants in number decls. Var1 : constant Integer := 3; Var2 : constant Integer := 4; Var3 : constant := Var1 + Var2; One cannot convert from a named type to a universal type (its a one-way street only). [Actually, can use Integer'Pos(Var1) + Integer'Pos(Var2). JBG] ***************************************************************************** !section 03.03.01 ER-00004 !class NC !topic types vs. subtypes; strong typing !experience students the most common problem my students tell me about has to do with the difference between base types and subtypes. For example... function factorial (of_n : natural) return natural; type numbers is range 1 .. 10; n : numbers := 3; Ada Programmer Errors 6-Mar-86 20:03:24 4 03.03.01 f : natural; begin f := factorial (n); This will not compile. They seem to think that all integer types should be subtypes of Integer and Integer should contain all possible integer values for a specific implementation. It is the people with Fortran backgrounds who really have trouble with this and strong typing in general. ***************************************************************************** !section 03.03.01 ER-00016 !class NC !topic Using base type name in type definition type I is Integer range 1 .. 10; One cannot create a base type using another base type. Typically three solutions to this problem are: type I is range 1 .. 10; type I is new Integer range 1 .. 10; subtype I is Integer range 1 ..10; ***************************************************************************** !section 03.03.01 (04) ER-00054 !class NC !topic type declarations declare distinct types A programmer wrote: procedure TEST is type A_9 is array (1..9) of CHARACTER; type A_18 is array (1..18) of CHARACTER; A : A_9; B : A_18; begin B := A & A; -- illegal In this case, the programmer forgot that A_9 and A_18 are distinct types and that subtype declarations should be used (or the STRING type). ***************************************************************************** !section 03.03.02 ER-00076 !class NC !topic Attempt to use subtype as private type EXAMPLE: package foo is Ada Programmer Errors 6-Mar-86 20:03:24 5 03.03.02 subtype anything is private; private subtype anything is ... -- Oops! I can't do that. end foo; This is not currently in the language standard, but I suspect that it may be considered as possibility for future versions. Using a subtype as a private type is so intuitive to me, I sometimes find it difficult to work around since it is not part of the language. ***************************************************************************** !section 03.05.01 ER-00030 !class UE !topic 'FIRST of enumeration literal has position number zero some_enumeration_type'POS(same_enumeration_type'FIRST) = 0 ??? Many programmers believe that this expression equals 1, most notably for CHARACTER'POS(CHARACTER'FIRST). This causes many tricky algorithmic problems which take a novice a long time to debug. ***************************************************************************** !section 03.05.05 ER-00009 !class NU !topic 'RANGE and 'LENGTH not defined for scalar types It seems inconsistent that the attributes 'first, 'last, 'range, and 'length apply to arrays, but only 'first and 'last also apply to scalars. ***************************************************************************** !section 03.05.05 ER-00031 !class UE !topic VAL attribute does not depend on rep. clause The VAL attribute works in logical terms. In the presence of a rep. spec., the VAL attribute will not return the value specified in that rep. spec. but will return the position number. ***************************************************************************** !section 03.05.09 ER-00036 !class NU !topic Failure to include range in fixed point declaration type My_Fixed is delta 0.01; A base type of a fixed point type must state an explicit range. Note that floating point base types need not state a range. Ada Programmer Errors 6-Mar-86 20:03:24 6 03.05.09 ***************************************************************************** !section 03.05.09 ER-00037 !class BL !topic Fixed point subtype declarations type My_Fixed is delta 0.1 range 1.0 .. 2.0; subtype Sub_Fixed is My_Fixed delta 0.01 range 0.0 .. 3.0; type My_Float is digits 2 range 1.0 .. 2.0; subtype Sub_Float is My_Float digits 3 range 0.0 .. 3.0; The subtypes will cause CONSTRAINT_ERROR to be raised since they each specify a greater accuracy and range of values than their respective base types. ***************************************************************************** !section 03.06 ER-00033 !class NC !topic No partially constrained arrays type A is array(BOOLEAN, INTEGER range <>) of CHARACTER; One cannot define an array type which has constrained and unconstrained indices mixed. ***************************************************************************** !section 03.06 ER-00077 !class NC !topic Lower bounds of arrays not always 1 EXAMPLE: procedure foo (str: in string) is begin for i in 1..str'length loop str(i) := ' '; end loop; end foo; The correction to this is to use the 'FIRST and 'LAST attributes to dynamically determine the bounds of the array. ***************************************************************************** !section 03.06.02 ER-00010 !class NU !topic no numeric operators for array types It seems inconsistent that the operators NOT, AND, OR, and XOR are implicitly defined on any boolean type or array of boolean types, but the implicit operators for numeric types are not defined for arrays of numeric types. Ada Programmer Errors 6-Mar-86 20:03:24 7 03.06.03 ***************************************************************************** !section 03.06.03 ER-00043 !class NC !topic Length of actual string parameter arguments Whether its due to laziness or misunderstanding I don't know, but I frequently see functions which take strings as arguments using s'last for s'length or less often assuming s'first = 1. ***************************************************************************** !section 03.06.03 (01) ER-00070 !class UE !topic the index subtype for STRING is Integer Consider: subtype Line_Length is Long_Integer range 0..80; X : String (1 .. Line_Length'Last); This is illegal since the LAST attribute returns a result of type Line_Length' Base, which is not the predefined type INTEGER. ***************************************************************************** !section 03.07 ER-00025 !class NU !topic No anonymous array types for record components type R is record . . . Arr : array(1 .. 10) of Boolean; end R; No anonymous array types allowed in a record type. ***************************************************************************** !section 03.07 (05) ER-00080 !class UE !topic no sliding for record component initializations type Rec is record D : String (1..3) := X(3..5); -- C_E end; Constraint_Error gets raised for the default initialization because 3.2.1(16) does not allow an implicit subtype conversion (which would cause the bounds to "slide" to 1..3). Ada Programmer Errors 6-Mar-86 20:03:24 8 03.07.01 ***************************************************************************** !section 03.07.01 ER-00059 !class UE !topic NUMERIC_ERROR for unconstrained record objects Several users reported confusion at receiving NUMERIC_ERROR when allocating an object of type PACKET: type Packet (Size : Positive := 20) is record data : String (1..Size); end record; P : Packet; -- NUMERIC_ERROR raised here An implementation is allowed to raise NUMERIC_ERROR since the amount of space that needs to be allocated for P is Postive'Last characters plus space for the discriminant. In computing Positive'Last + Positive'Size, NUMERIC_ERROR can be raised because the result is greater than Integer'Last (see 11.1(6)). If NUMERIC_ERROR is not raised, STORAGE_ERROR might be, since a lot of space is likely to be occupied by POSITIVE'LAST characters. ***************************************************************************** !section 03.08.01 ER-00021 !class NC !topic Using an incomplete type prematurely type Link; type Node is record . . . Next : Link; end record; type Link is access Node; The incomplete type declaration should be used for Node, not Link. ***************************************************************************** !section 03.09 (02) ER-00044 !class NU !topic basic declarations not allowed after bodies Not listed in your summary was the problem I sent to info-ada of basic-declarations not allowed after later-declarations. I really think this is a source of errors in Ada (even though my original message had the heat turned up to flame level.) Ada Programmer Errors 6-Mar-86 20:03:24 9 03.09(06) ***************************************************************************** !section 03.09 (06) ER-00060 !class UE !topic Activating a task whose body has not been elaborated task type Actor is ... end Actor; type Actor_Ptr is access Actor; actor_Ptrs : array (1..10) of Actor_Ptr := (1..10 => new Actor); -- PROGRAM_ERROR raised here task body Actor is ... end; PROGRAM_ERROR will be raised because the body of Actor has not been elaborated when the allocator is executed. ***************************************************************************** !section 04.0.03 ER-00040 !class NU !topic Using Pointers and .all Also, some programmers still haven't got the difference down between the following two if-then conditions: type Access_R is access R; A1, A2 : Access_R := . . .; if A1 = A2 then . . . end if; vs. if A1.all = A2.all then . . . end if; ***************************************************************************** !section 04.01.03 ER-00039 !class NU !topic Using .all to access whole records type R is record . . . end record; . . . R1, R2 : R; . . . if R1.all = R2.all then . . . end if; The ".all" suffix applies only to access values. When dealing with record objects, simply stating the object without a selected component is equivalent to a ".all" semantics for access values. Ada Programmer Errors 6-Mar-86 20:03:24 10 04.03(04) ***************************************************************************** !section 04.03 (04) ER-00068 !class NU !topic aggregates with only one component An aggregate containing only one component must be given in named notation, even when the context clearly indicates that an aggregate is meant. For example, type Rec is record C : Integer; end record; type Rec_Rec is record I : Integer; D : Rec; end record; X : Rec_Rec := (1, (3)); -- illegal The aggregate for component D must be written as (C => 3). ***************************************************************************** !section 04.03.02 ER-00014 !class NU !topic Character literals vs string literals Another trivial point: for STRINGS (arrays of CHARACTER), notice the difference of use: A_SMALL_STRING : STRING(1..1) := (others => ' '); begin A_SMALL_STRING := " "; ***************************************************************************** !section 04.03.02 ER-00038 !class UC !topic Rules for using others choice type My_Array is array(INTEGER range 1 .. 10) of BOOLEAN; . . . A : My_Array := (1 .. 3 => FALSE, others => TRUE); Cannot use an others clause in the presence of named notation where one or more choices represents a range of values. The tricky rules on the use of an others clause play havic with Ada programmers. Some even get so frustrated as to how/where an others clause can appear that they simply never try to use it. The rules should be made clear to these programmers (described at their own level -- they cannot understand the language of the ARM). Ada Programmer Errors 6-Mar-86 20:03:24 11 04.04 ***************************************************************************** !section 04.04 ER-00015 !class BL !topic Can't parenthesize range C : Character; . . . if C in ('A' .. 'Z') then . . . end if; One cannot parenthesize the range for a membership test. ***************************************************************************** !section 04.05.04 ER-00008 !class NU !topic precedence of unary minus The low precedence of unary minus would surprise those with a math background, I would think. -11 mod 5 is interpreted as -(11 mod 5) which is -1. The other interpretation (-11) mod 5 equals 4. ***************************************************************************** !section 04.09 (08) ER-00045 !class UE !topic Size of a record is not static For an appropriate record type declaration: for FOO'SIZE use 4*SYSTEM.STORAGE_UNIT; for BAR use record COMPONENT at 0 range 0 .. FOO'SIZE-1; -- illegal end record; The use of FOO'SIZE is illegal because FOO'SIZE is non-static; the prefix of the attribute is not a scalar type, as 4.9 requires. ***************************************************************************** !section 05.02 ER-00042 !class NC !topic Failure to use aggregates in assignments Pascal programmers also sometimes write record assignments as a series of field assignments, including the discriminant, instead of writing an aggregate assignment. Ada Programmer Errors 6-Mar-86 20:03:24 12 05.02.01(02) ***************************************************************************** !section 05.02.01 (02) ER-00058 !class NU !topic No sliding of array components in record aggregates type R (D : Natural) is record C : String (1..D); end record; S : String (1..20) := ...; V1 := R(10) := (D => 10, C => S(1..10)); -- ok V2 := R(10) := (D => 10, C => S(4..13)); -- exception The second aggregate raises CONSTRAINT_ERROR because the bounds 4..13 don't match C's bounds of 1..10. This shows that aggregate assignment is not equivalent to component by component assignment, since V2.C := S(4..13); does not raise an exception. ***************************************************************************** !section 05.04 (02) ER-00073 !class NU !topic not all choices can be parenthesized Consider the following case statement: case X is when ('_') => ... when ('/') => ... when ('0'..'9') => ... -- illegal The last choice is illegal because ranges cannot be parenthesized, but simple expressions, such as '_' can be. ***************************************************************************** !section 05.04 (04) ER-00049 !class UE !topic Use of RANGE attribute in loops and case statements Consider the following example: declare A : array (0..2) of INTEGER; begin for I in A'RANGE loop -- where A is an array, of course case I is -- I is NONSTATIC Ada Programmer Errors 6-Mar-86 20:03:24 13 05.04(04) when 0 => ... when 1 => ... when 2 => ... end case; -- missing OTHERS end loop; end; The case statement is illegal because A'RANGE is non-static. Hence, the loop parameter has a non-static subtype, and the choices in the case statement must cover the full range of the index base type, INTEGER. ***************************************************************************** !section 05.05 ER-00078 !class NU !topic negative bounds for loop parameters I have been reluctant to submit to your collection because I am fearful that my contribution would be construed as a vote to alter the language, and in every case I have come across, I feel the language is right and should not be changed. Nevertheless, allow me to throw in the following: for I in -5 .. 5 loop which is a no-no unless you specify the range type (presumably Integer). ***************************************************************************** !section 06.02 ER-00006 !class UE !topic Slices used as actual parameters function string_eq(left, right: string) return boolean is --returns true iff the two string parameters have the same value. begin if left'length /= right'length then return false; end if; for i in left'range loop if left(i) /= right(i) then return false; end if; end loop; return true; end string_eq; The bug in this code is insidious because the routine works fine in most cases. It fails though when the right parameter is a slice such that right'first /= left'first. I think the principle of least surprise would dictate that slice parameters be normalized similar to how they are in slice assignment, although the unconstrained case doesn't apply for assignment. This bug could easily bite anyone not sufficiently immunized from previous bites. Ada Programmer Errors 6-Mar-86 20:03:24 14 06.02(02) ***************************************************************************** !section 06.02 (02) ER-00041 !class NC !topic Incorrect use of formal parameter modes Pascal programmers seem to frequently write to an in-parameter and read from an out-parameter, the error being to use them as local variables (especially for an out-parameter). ***************************************************************************** !section 06.02 (05) ER-00062 !class UE !topic Assignment to component designated by OUT parameter If an OUT parameter has an access type, you are not allowed to assign to any component of the designated object, since such an assignment requires that the value of the OUT parameter be read, and the prefix of selected component cannot be an OUT parameter having an access type [4.1(4)]. ***************************************************************************** !section 06.03 ER-00001 !class BL !topic ; instead of IS in subprogram bodies !experience students Error: using ";" instead of "IS" after procedure headers, especially on the heading of a file. Reason for error: mostly a carry-over from Pascal and Modula-2. Source of error: personal experience learning Ada. Occurance: most likely by programmers still learning Ada. Reason this is a problem: large number of fall-out error messages as the compiler then mis-interprets the entire block structure of the file. The actual error is not even flagged. ***************************************************************************** !section 06.03 (02) ER-00051 !class BL !topic Bodies that use IS rather than semicolon Unhelpful diagnostic messages will usually appear when trying to compile a procedure body where a semicolon has been used in place of the IS: with TEXT_IO; use TEXT_IO; procedure TEST; -- semicolon instead of IS package REAL_IO is new FLOAT_IO (FLOAT); use REAL_IO; Ada Programmer Errors 6-Mar-86 20:03:24 15 06.03(02) begin ... end TEST; ***************************************************************************** !section 06.03.01 (05) ER-00056 !class NU !topic can't omit IN in parameter decl if it is present in body A formal parameter mode IN must be specified explicitly in both the specification and body, or it must be left implicit in both places. ***************************************************************************** !section 06.03.02 (04) ER-00067 !class UE !topic dependence on body due to INLINE Although the use of pragma INLINE does not change the meaning of a program, it can create a dependence on the body of the unit that is being inlined, i.e., after recompilation of an inlined body, an implementation can require that units containing calls to the inlined unit also be recompiled. This sort of dependence on a body can only be imposed if the inlined unit and the calls are compiled together in the same compilation file [10.3(7)]. ***************************************************************************** !section 06.06 (01) ER-00061 !class NU !topic Parameter names not considered in overloaded declarations Consider subtype Switch1 is Positive range 1..10; subtype Switch2 is Positive range 1..25; procedure Set_Switch (First : Switch1); procedure Set_Switch (Second : Switch2); -- illegal The difference in parameter names does not suffice to allow the second declaration as a legal overloading of the first. ***************************************************************************** !section 08.03 ER-00013 !class UE !topic visibility rules for operators I find that scoping rules for user defined types is an error prone "concept" (as opposed to construct). As you pointed out to me once before* according to 8.3(18) an "operator is directly visible if and only if the corresponding operator declaration is directly visible." Yet, it is natural to write something like the following (especially for 1st time users): package pack1 is type int is range 1..1000; end pack1; Ada Programmer Errors 6-Mar-86 20:03:24 16 08.03 with pack1; procedure demo is i: pack1.int := 5; begin . i := i+1; -- illegal . . end demo; I realize that I could use a USE clause or RENAME the "+" operation, but I feel that not using the full name in most situtations is less readable and that both the USE clause & RENAMING are error prone (in fact 1 project here has totally disallowed both) . I would like to set up a project standard where USE clause is only used for command package that are deemed acceptable by project management (e.g., predefined packages and project global definitions). However, if I adopt such a standard I loose any benifit from defining operators and in cases such as the one above I cannot use infixed notation even for predefined operators, unless pack1 is one of my "acceptable" packages. On the other hand, If I allow the use of USE, but require that full names be used (except maybe in specific situations), than I can no longer use the compiler to enforce the full name requirement. Unfortunately, I don't see a clean solution to this problem since redefine the scope of an operator to be extended to the scope of the type(s) that it operates on (for example) would be extremely difficult to define proprely for operators that have parameters of different types. ***************************************************************************** !section 08.03 ER-00022 !class UE !topic visibility of operators package P is type T is (T1, T2); end P; with P; procedure Main is V1, V2 : P.T; begin . . . if V1 = V2 then . . . end if; end Main; One must explicitly import operations from another scope. Best solution is to use a renames in the declarative region of Main: function "="(L, R : in P.T) return Boolean renames P."="; One could also use a "use clause", expanded notation on P."=", or the Pos attribute to convert V1 and V2 to universal_integers so that they could be Ada Programmer Errors 6-Mar-86 20:03:24 17 08.03 compared for equality. All of these solutions are less than desirable. ***************************************************************************** !section 08.03 (15) ER-00071 !class UE !topic Object declaration hides outer procedure declaration Consider: with Text_IO; use Text_IO; procedure XYZ is New_Line : String(1..80); procedure ABC is begin Put (" ... "); New_Line; -- illegal end ABC; ... The call to New_Line is illegal since procedure New_Line is hidden by the outer declaration of the variable New_Line. ***************************************************************************** !section 08.03 (18) ER-00055 !class UE !topic Need a use clause to get visibility of operators An attempt to use = or /= (or any other operator) for a type declared in a library package will not work unless the package has been USEd: package Options_Utility is type Opt2_Values is (All1, Normal); function Opt2_Value (Option_On : Boolean) return Opt2_Values; end Options_Utility; with Options_Utility; procedure Tagging is subtype Opt2_Vals is Options_Utility.Opt2_Values; Options : Options_Utility.Opt2_Values := Opt2_Values.Normal; begin ... if Options_Utility.All1 /= Options then -- illegal The condition is illegal because the /= operator declared in Options_Utility is not directly visible. The subtype declaration does not make an operators visible. Ada Programmer Errors 6-Mar-86 20:03:24 18 08.04(05) ***************************************************************************** !section 08.04 (05) ER-00057 !class UE !topic Conflict with a name declared in Standard Consider package A is type Char_Type is (ASCII, EBCDIC); end A; use A; X : Char_Type := ASCII; -- illegal! Since ASCII is directly visible in STANDARD, the use clause for package A does not make A.ASCII directly visible. Since the declaration of X refers to STANDARD.ASCII instead of A.ASCII, the expression is illegal. ***************************************************************************** !section 08.04 (06) ER-00053 !class UE !topic Effect of USE on generic subprograms with TEXT_IO, INDEXED_MIXED_IO; use TEXT_IO, INDEXED_MIXED_IO; procedure BUG is begin PUT("Testing"); -- undeclared PUT end BUG; INDEXED_MIXED_IO contains a declaration of PUT as a generic procedure. The presence of this non-overloadable declaration means none of the declarations of PUT in TEXT_IO or INDEXED_MIXED_IO are made directly visible. As a design issue, this suggests that a generic unit should never be given the same name as a non-generic unit in another package, if the two are likely to be USEd together. ***************************************************************************** !section 08.04 (06) ER-00066 !class UE !topic Use clause and renamed exceptions Consider package Math_Exceptions is Negative_Argument : exception; end; with Math_Exceptions; package Math_1 is Ada Programmer Errors 6-Mar-86 20:03:24 19 08.04(06) Negative_Argument : exception renames Math_Exceptions.Negative_argument; end; package Math_2 is Negative_Argument : exception renames Math_Exceptions.Negative_argument; end; with Math_1; use Math_1; with Math_2; use Math_2; procedure Check is begin null; exception when Negative_Argument => ... -- illegal Negative_Argument is not visible because exceptions are not overloadable and the declarations in both Math_1 and Math_2 mean the use clauses do not make the declarations of Negative_Argument visible. It is immaterial that both declarations denote the same exception. ***************************************************************************** !section 08.05 ER-00017 !class NU !topic renaming task entries On trying to "hide" tasks in a package body: package P is procedure I_Am_Trying_to_be_a_Task_Entry; end P; package body P is task T is entry E; end T; task body T is begin accept E; end; procedure I_Am_Trying_to_be_a_Task_Entry renames T.E; end P; One solution to this problem (albeit not the best one) is: package P is . . . end P; package body P is . . . procedure I_Am_Trying_to_be_a_Task_Entry is begin T.E; Ada Programmer Errors 6-Mar-86 20:03:24 20 08.05 end; end P; ***************************************************************************** !section 08.05 ER-00027 !class UE !topic ignoring constraints in renaming procedure P is A : Integer; B : Positive renames A; C : Positive; D : Integer renames C; begin B := -10; D := B; end P; Obviously, the user doesn't understand that constraints implied by a type mark on a renaming are ignored and the constraints are that of the actual. Constraint_Error will be raised during the attempt to assign B to D. ***************************************************************************** !section 09.0 ER-00084 !class UE !topic Deadlock because of exception propagation If during the execution of a task, an unexpected exception is raised and is propagated to the task body and not handled, the task is terminated silently. Any tasks that are waiting for calls from this terminated task will wait forever at an accept statement unless the statement has a terminate alternative. This source of deadlock can be very difficult to locate unless the Ada debugger notes that a particular task terminated because of an unhandled exception. Another subtle way to get deadlock is by attempting to propagate an exception out of a frame that has dependent tasks: procedure P is task T is entry E; end T; task body T is ... end T; begin ... some statement raising an exception unexpectedly T.E; end P; Control cannot leave P until dependent task T is terminated, but the task cannot terminate because it is waiting for the entry call T.E, which will never be executed because of the exception. Ada Programmer Errors 6-Mar-86 20:03:24 21 09.0 ***************************************************************************** !section 09.01 (04) ER-00079 !class UE !topic Can't use task type name in its own body One way to look for solutions is to dispatch tasks to look for solutions to subproblems. Each task might want to in turn, dispatch copies of itself to explore a smaller portion of the solution space. Such programs tend to have a structure like the following: package Search is task type Seeker is ... end Seeker; type filter is access Seeker; end Search; package body Search is task body Seeker is begin ... -- dispatch new seeker new_filter := new Seeker; -- illegal end Seeker; end Search; The allocator is illegal within the body of Seeker because the name Seeker cannot be used as a type mark within the body. To get around this rule, declare a subtype in the package body, just before the task body: subtype Seeker_Type is Seeker; and then use the subtype name to activate the new copy of the task: ... new_filter := new Seeker_Type; -- ok now ***************************************************************************** !section 09.02 ER-00087 !class UE !topic Use task types instead of single tasks The amount of storage provided for a task can be specified with a representation clause only if a task type is used. To preserve flexibility, it is best to use task types instead of single task declarations. Ada Programmer Errors 6-Mar-86 20:03:24 22 09.04 ***************************************************************************** !section 09.04 ER-00034 !class UE !topic Nested task termination and leaving block procedure Main is task T is entry E(. . .); end T; task body T is begin loop accept E(. . .) do ... end E; end loop; end T; begin while

Download 75.09 Kb.

Share with your friends:
  1   2




The database is protected by copyright ©ininet.org 2024
send message

    Main page