CVS difference for ais/ai-00218.txt

Differences between 1.1 and version 1.2
Log of other versions for file ais/ai-00218.txt

--- ais/ai-00218.txt	1999/03/30 01:46:17	1.1
+++ ais/ai-00218.txt	1999/03/30 02:38:56	1.2
@@ -1,6 +1,6 @@
-!standard 8.3(9-13)                                   99-03-23  EI95-00001/01
+!standard 8.3(9-13)                                   99-03-29  AI95-00218/02
 !standard 6.1(1)
-!class enhancement 99-03-23
+!class amendment 99-03-23
 !status work item 99-03-23
 !status received 99-03-23
 !priority Medium
@@ -9,24 +9,29 @@
 
 !summary
 
-In order to reduce problems with overriding of primitive operations, additional syntax and a pragma is 
-introduced.
+In order to reduce problems with overriding of primitive operations, two
+pragmas are introduced.
 
 !problem
 
-Subtle bugs result from mistakes in the profile of an overriding subprogram. For example:
+Subtle bugs result from mistakes in the profile of an overriding subprogram. For
+example:
 
+with Ada.Finalization;
 package Root is
-    type Root_Type is tagged .;
+    type Root_Type is new Ada.Finalization.Controlled with null record;
     procedure Do_Something (Object : in out Root_Type;
                             Data : in Natural); -- (1)
+    procedure Finalize (Object : in out Root_Type);
 end Root;
 
 with Root;
 package Leaf is
    type Derived_Type is new Root.Root_Type with null record;
    procedure Do_Something (Object : in out Root_Type;
-                           Data : in Boolean); -- (2)
+                           Data : in Boolean); -- (3)
+   procedure Finalise (Object : in out Root_Type); -- (4)
+	-- Note: British spelling of "Finalize".
 end Leaf;
 
 with Leaf;
@@ -34,75 +39,137 @@
      Obj : Leaf.Derived_Type;
 begin
      Leaf.Do_Something (Obj, 10); -- Calls (1).
+     -- Finalization of Obj will call (2).
 end Sample;
 
-Assume the program intended (2) to override (1), but made a subtle declaration error. Because (1) and (2) are 
-not homographs, the declaration of (2) is legal. However, (2) does not override (1), as intended. Therefore, 
-the call in Sample calls the wrong routine. The resulting bug is very difficult to find, especially because the 
-programmer will probably look at this call several times before even thinking that the wrong routine might be 
-called. The bug is even harder to find when the call is dispatching, because the reason that the wrong 
-routine is being called is not obvious. The problem has generated many "bug" reports to compiler writers, 
-including ones from in their own development teams.
-
-The problem also makes maintenance of object-oriented Ada 95 code much more difficult. Consider a 
-maintenance change to the root class which adds a parameter to Do_Something. All extensions of 
-Root_Type that override Do_Something will now silently overload it instead. The change probably will 
+Assume the programmer intended (3) and (4) to override (1) and (2), but made
+subtle declaration errors. Because (1) and (3) are not homographs, the
+declaration of (3) is legal. However, (3) does not override (1), as intended.
+Therefore, the call in Sample calls the wrong routine. Similarly, the
+incorrect declaration of "Finalise" (4) does not override (2). Thus, the
+finalization of Sample.Obj will call the wrong routine.
+
+The resulting bugs are very difficult to find, especially because the
+programmer will probably look at this call several times before even
+thinking that the wrong routine might be called. The bug is even harder to find
+when the call is dispatching or implicit (as it is for Finalize), because the
+reason that the wrong routine is being called is not obvious. In the Finalize
+case, the programmer might even think that the compiler is failing to call
+Finalize at all. These problems have generated many "bug" reports to compiler
+writers, including ones from in their own development teams.
+
+A more serious problem is that it makes maintenance of object-oriented Ada 95
+code much more difficult. Consider a maintenance change to the root class which
+adds a parameter to Do_Something. All extensions of Root_Type that override
+Do_Something will now silently overload it instead. The change probably will
 break all existing code, yet provide no warnings of the problem.
 
-A rarer, but similar problem can occur when a routine accidentally overrides another. In this case, an 
-inappropriate routine may be called via dispatching, and may cause the failure of an abstraction.
+A rarer, but similar problem can occur when a routine accidentally overrides
+another. In this case, an inappropriate routine may be called via dispatching,
+and may cause the failure of an abstraction.
 
-In both of these cases, the Ada compiler is being actively harmful to the programmer, violating the Ada 
-design principles of least surprise.
+In all of these cases, the Ada compiler is being actively harmful to the
+programmer, violating the Ada design principles of least surprise.
 
 !proposal
 
-The problem of accidental overloading rather than overriding can be minimized if the Ada compiler knows 
-when the programmer wishes to override a routine. Similarly, accidental overriding can be minimized if the 
-Ada compiler knows that the programmer has declared all intentional overriding.
+The problem of accidental overloading rather than overriding can be eliminated
+if the Ada compiler knows when the programmer wishes to override a routine.
+Similarly, accidental overriding can be minimized if the Ada compiler knows that
+the programmer has declared all intentional overriding.
+
+Unfortunately, a complete solution to this problem will be incompatible with
+existing Ada 95 code. Therefore, we have to introduce an optional solution which
+applies only when the programmer asks for it.
+
+Thus, we introduce two new pragmas, Explicit_Overriding and Overrides.
+Explicit_Overriding is a configuration pragma which requires explicit marking
+of overriding subprograms. Pragma Overrides is used to mark subprograms that
+are overriding. Unmarked subprograms are new declarations, and may not override
+another routine.
 
-Unfortunately, a complete solution to this problem with be incompatible with existing Ada 95 code. 
-Therefore, we have to introduce an optional solution which applies only when the programmer asks for it.
+!wording
 
-Therefore, we introduce additional syntax and a pragma.
+Add to 8.3 after paragraph 1:
 
-!wording
+The form of a pragma Explicit_Overriding is as follows:
 
-Replace paragraph 2 of section 6.1 by:
+pragma Explicit_Overriding;
 
-overriding_subprogram_declaration ::= subprogram_specification declare new;
+The form of a pragma Overrides is as follows:
 
-subprogram_declaration ::= subprogram_specification; | overriding_subprogram_declaration
+pragma Overrides [(subprogram_name)];
 
-Add to 8.3 after paragraph 1:
+Add to 8.3 after paragraph 26:
 
-The form of a pragma Explicit_Overriding is as follows:
+Pragma Explicit_Overriding is a configuration pragma.
 
-pragma Explicit_Overriding (type_name);
+Pragma Overrides applies to the preceding subprogram_declaration. Pragma
+Overrides shall immediately follow the subprogram_declaration to which it
+applies, separated only by space_characters, format_effectors, and comments.
+The optional subprogram_name of a pragma Overrides shall be the same as the
+name of the subprogram_declaration to which it applies.
 
-Add to 8.3 after paragraph 26:
+A subprogram_declaration to which pragma Overrides applies shall override the
+implicit declaration of a primitive subprogram.
 
-The type_name in a pragma Explicit_Overriding must name a type already declared in the same declarative 
-part.
+For a primitive subprogram inherited in a unit to which a pragma
+Explicit_Overriding applies, an overriding explicit declaration shall be
+a subprogram_declaration to which pragma Overrides applies.
 
-An explicit declaration of an overriding_subprogram_declaration is illegal if it does not override the implicit 
-declaration of a primitive subprogram.
+!example
 
-For a primitive subprogram inherited by a type to which a pragma Explicit_Overriding applies, an overriding 
-explicit declaration shall be an overriding_subprogram_declaration.
+Here is our original example using the new pragmas.
 
-!discussion
+pragma Explicit_Overriding;
 
-We add the new syntax in such a way that all of the rules about subprogram_declarations need not be 
-changed.
+with Root;
+package Leaf is
+   type Derived_Type is new Root.Root_Type with null record;
+   procedure Do_Something (Object : in out Root_Type;
+                           Data : in Boolean); pragma Overrides; -- Error:
+   procedure Finalise (Object : in out Root_Type); pragma Overrides; -- Error:
+	-- Note: British spelling of "Finalize".
+end Leaf;
+
+The declarations of Do_Something and Finalise will now cause errors. The
+problem will immediately be pointed out to the programmer.
+
+!discussion
 
-We looked at a pragma instead of a syntax change, but it runs into problems with overloading. The main 
-program is that for a constructor, it is common to intentionally add an overloading of the constructor. If we 
-have pragma Is_Overriding (Create); such a overloading for Create would be illegal. Using a non-
-overloading interpretation of the identifier would be different than for all other Ada pragmas which take 
-subprogram identifiers. The alternative of using a "must follow" rule and no identifier in the pragma is also 
-unpleasant, since no other language defined pragmas work this way. It also would make it easy for the 
-pragma to get separated from the declaration during cut-and-paste operations, leading to various errors.
+We need to add two pragmas in order that we can have override checking even
+when no overriding subprograms are declared. This checking will prevent
+accidental overriding.
+
+Requiring the explicit declaration of overriding is used in some other
+programming languages, most notably Eiffel. They also have noticed this
+problem.
+
+This additional checking still could allow an error to occur. The problem
+could still occur if there existed two or more overloaded inherited routines,
+and the user overrode the wrong one. However, this would be extremely rare,
+as it is normally the case that all of the inherited routines with a
+single name are overridden as a group.
+
+We considered adding syntax rather than defining pragma Overrides. Syntax was
+determined to be too heavyweight a solution for an amendment. One idea
+considered using existing keywords was: subprogram_specification is not new;
+These ideas were not considered satisfactory; it was felt that proper systax
+would need a new reserved word "overriding" or "redefined". That is much too
+heavy to introduce at this time. A pragma solution also has
+the advantage that compilers can implement it, and users can use it, even
+before most compilers support it. If a compiler has not yet implemented the
+pragmas, it will ignore them, and will accept any legal program (along with
+some that would be illegal if the pragmas were accepted).
+
+Pragma Overrides was defined in such a way that it can be treated almost as
+a part of the subprogram declaration. This eases the implementation, as a
+compiler can determine what kind of declaration it is processing before it
+starts doing so. (Without this rule, an implementation must postpone error
+messages until it reaches the next declaration. Since the next declaration
+could be almost anything, this would provide a distributed overhead.)
+In addition, it is important that this pragma is not accidentially
+separated from the subprogram declaration.
 
 !appendix
 

Questions? Ask the ACAA Technical Agent