diff mbox series

[Ada] Conformance error on protected subp with anonymous-access-to-tagged formal

Message ID 20220111133207.GA748614@adacore.com
State New
Headers show
Series [Ada] Conformance error on protected subp with anonymous-access-to-tagged formal | expand

Commit Message

Pierre-Marie de Rodat Jan. 11, 2022, 1:32 p.m. UTC
The compiler incorrectly rejected a protected subprogram with a formal
of an anonymous access type that designates a tagged type when the
protected type extends an interface and the formal's designated type (a
different type) is declared immediately within the same scope as the
protected type; an error is issued about the declaration and body not
conforming. This occurs in conjunction with the (nonprotected) wrapper
subprogram created for the protected subprogram, which is declared in
the scope enclosing the protected type. It appears to the compiler that
the type of the access formal of the wrapper subprogram doesn't conform
with the declaration, due to null exclusions being different. The flag
Can_Never_Be_Null gets set on one formal parameter and not the other,
because Check_Controlling_Type sees that the formal's designated type is
declared in the same scope as the wrapper subprogram, and as a result
decides that the access formal is a controlling formal when it really
isn't (so sets Can_Never_Be_Null since controlling access-to-tagged
formals are defined to exclude null).

This problem is fixed by adding a special check in
Check_Controlling_Type to prevent treating formals of
anonymous-access-to-tagged types as controlling when the subprogram has
an associated protected subprogram and the tagged type is not the record
type associated with the protected subprogram's enclosing protected
type.

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

gcc/ada/

	* sem_disp.adb (Check_Controlling_Type): Add test for the case
	where Subp is a subprogram associated with a protected
	subprogram and return Empty, unless Tagged_Type is the
	corresponding record type of the protected type.
diff mbox series

Patch

diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -478,6 +478,29 @@  package body Sem_Disp is
       if No (Tagged_Type) or else Is_Class_Wide_Type (Tagged_Type) then
          return Empty;
 
+      --  In the special case of a protected subprogram of a tagged protected
+      --  type that has a formal of a tagged type (or access formal whose type
+      --  designates a tagged type), such a formal is not controlling unless
+      --  it's of the protected type's corresponding record type. The latter
+      --  can occur for the special wrapper subprograms created for protected
+      --  subprograms. Such subprograms may occur in the same scope where some
+      --  formal's tagged type is declared, and we don't want formals of that
+      --  tagged type being marked as controlling, for one thing because they
+      --  aren't controlling from the language point of view, but also because
+      --  this can cause errors for access formals when conformance is checked
+      --  between the spec and body of the protected subprogram (null-exclusion
+      --  status of the formals may be set differently, which is the case that
+      --  led to adding this check).
+
+      elsif Is_Subprogram (Subp)
+        and then Present (Protected_Subprogram (Subp))
+        and then Ekind (Scope (Protected_Subprogram (Subp))) = E_Protected_Type
+        and then
+          Base_Type (Tagged_Type)
+            /= Corresponding_Record_Type (Scope (Protected_Subprogram (Subp)))
+      then
+         return Empty;
+
       --  The dispatching type and the primitive operation must be defined in
       --  the same scope, except in the case of internal operations and formal
       --  abstract subprograms.