diff mbox

[Ada] Better warning for failure to override an abstract operation in an instance

Message ID 20120217135730.GA26792@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Feb. 17, 2012, 1:57 p.m. UTC
An operation declared in the private part of a generic package is overriding
in an instane only if it was overriding in the generic. If an instantiation
fails because a non-abstract type has a remaining abstract inherited operation
it may be because of a failure to override. This patch produces a warning in
this case, that clarifies the resulting error message.

compiling inst.ads must yield:

inst.ads:5:04: instantiation error at gen.ads:7
inst.ads:5:04: type must be declared abstract or "Change" overridden
inst.ads:5:04: "Change" has been inherited at gen.ads:5, instance at line 5
inst.ads:5:04: "Change" has been inherited from subprogram at line 4
inst.ads:5:04: warning: in instantiation at gen.ads:8
inst.ads:5:04: warning: private operation "Change" in generic unit does not
    override any primitive operation of "Der" (RM 12.3 (18))

---
with P1; with Gen;
package Inst is
   type Act is abstract new P1.Root with null record;
   procedure Change (Obj : Act) is abstract;
   package Prob is new Gen (Act);
end Inst;
---
package P1 is
   type Root is abstract tagged null record;
end P1;
---
with P1;
generic
   type Ext is abstract new P1.Root with private;
package Gen is
   type Der is new Ext with private;
private
   type Der is new Ext with null record;
   procedure Change (Obj : Der);
end Gen;

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-02-17  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch6.adb (Is_Non_Overriding_Operation): Add warning if the
	old operation is abstract, the relevant type is not abstract,
	and the new subprogram fails to override.
diff mbox

Patch

Index: sem_ch6.adb
===================================================================
--- sem_ch6.adb	(revision 184330)
+++ sem_ch6.adb	(working copy)
@@ -188,9 +188,9 @@ 
       New_E  : Entity_Id) return Boolean;
    --  Enforce the rule given in 12.3(18): a private operation in an instance
    --  overrides an inherited operation only if the corresponding operation
-   --  was overriding in the generic. This can happen for primitive operations
-   --  of types derived (in the generic unit) from formal private or formal
-   --  derived types.
+   --  was overriding in the generic. This needs to be checked for primitive
+   --  operations of types derived (in the generic unit) from formal private
+   --  or formal derived types.
 
    procedure Make_Inequality_Operator (S : Entity_Id);
    --  Create the declaration for an inequality operator that is implicitly
@@ -7844,6 +7844,22 @@ 
                --  If no match found, then the new subprogram does not
                --  override in the generic (nor in the instance).
 
+               --  If the type in question is not abstract, and the subprogram
+               --  is, this will be an error if the new operation is in the
+               --  private part of the instance. Emit a warning now, which will
+               --  make the subsequent error message easier to understand.
+
+               if not Is_Abstract_Type (F_Typ)
+                 and then Is_Abstract_Subprogram (Prev_E)
+                 and then In_Private_Part (Current_Scope)
+               then
+                  Error_Msg_Node_2 := F_Typ;
+                  Error_Msg_NE
+                    ("private operation& in generic unit does not override " &
+                     "any primitive operation of& (RM 12.3 (18))?",
+                     New_E, New_E);
+               end if;
+
                return True;
             end;
          end if;