I happened to see somewhere declarations like this:
procedure P (x : in out T'Class) is abstract;
where T is a tagged type. Ouch, isn’t it?
Fortunately, GNAT shows the following message:
warning: abstract subprogram is not dispatching or overriding [-gnatwr]
but only when the switch is enabled.
I am wondering why it is legal Ada in the first place.
You can even write this:
procedure Q is abstract;
It compiles successfully (both GNAT and ObjectAda do it at least) !
Isn’t it a gap in the Ada rules?
Full reproducer here:
package Abstract_Nonsense is
type T is abstract tagged null record;
procedure P (x : in out T'Class) is abstract;
procedure Q is abstract;
end;
-- gnatmake -gnatwr abstract_nonsense.ads:
--
-- abstract_nonsense.ads:5:39: warning: abstract subprogram is not dispatching or overriding [-gnatwr]
-- abstract_nonsense.ads:7:18: warning: abstract subprogram is not dispatching or overriding [-gnatwr]
No, it is designed to be this way and has an important function. Declaring a subprogram abstract hides it. E.g.
type T is new Integer;
function "/" (Left, Rgiht : T) return T is abstract; -- No more "/"
Note a subtle difference. If a primitive subprogram is declared abstract when the tagged type declaration is not frozen that declares an abstract primitive subprogram that must be overridden (implemented) in a concrete derived type.
type T is abstract tagged null record;
procedure P (X : in out T'Class) is abstract; -- Hidden
procedure Q is abstract; -- Hidden
procedure S (X : in out T) is abstract; -- Primitive
Here neither P nor Q are primitive, so declaring abstract hides them. Now consider S:
type U is new T with null record
overriding procedure S (X : in out U); -- Required!
Further
X : U; -- The type U is frozen at this point
procedure S (X : in out U) is abstract; -- Hides the override!
begin
S (X); -- Error, S is declared abstract and hides the primitive S
X.S; -- OK, primitive subprograms are always reachable
3 Likes
Ah, I found the paragraphs:
Ramification: {AI95-00310-01} {AI12-0413-1} If an abstract subprogram is not a dispatching operation of some tagged type, then it cannot be called at all. In Ada 2005, such subprograms are not even considered by name resolution (see 6.4).
{AI95-00310-01} In Ada 2005, abstract primitive subprograms of an untagged type may be used to “undefine” an operation.
{AI95-00251-01} {AI95-00334-01} If the type is abstract or untagged, the implicitly declared subprogram is abstract.
Ramification: Note that it is possible to override a concrete subprogram with an abstract one.
Slight precision, for the laymen among us: we override a concrete subprogram with an abstract one, but only with non-tagged types, or abstract tagged ones. Ok, I learnt something useful !
1 Like