diff mbox

[Ada] Resolution of references to predefined operators

Message ID 20100622081447.GA9698@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet June 22, 2010, 8:14 a.m. UTC
A reference of the form P."+" is analyzed by verifying that there is a
numeric type defined in P, and then treating both unary and binary operators
as possible interpretation of the node. Subsequent analysis usually is
sufficient to disambiguate the reference. In some complex overloading cases,
the wrong operator may remain as a possible interpretation leading to spurious
errors or crashes. This patch uses the fact that if the context is known to
be a call, it is possible to discard one of the interpretations without any
further type analysis, thus simplifying subsequent resolution.

The following must compile quietly:

procedure Crash_Op_Resolution is
   package Scop is
      type T1 is new Integer;
      function F return T1;
      procedure P1 (X : T1);
      type T2 is new Integer;
      function F return T2;
      procedure P2 (X : T2);
   end Scop;

   package body Scop is
      procedure P (X : T1) is begin null; end;
      procedure P1 (X : T1) is begin null; end;
      function F return T1 is begin return 0; end;
      procedure P (X : T2) is begin null; end;
      procedure P2 (X : T2) is begin null; end;
      function F return T2 is begin return 0; end;
   end Scop;

begin
   Scop.P2 (Scop."+" (Scop.F, Scop.F));
end;

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

2010-06-22  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch8.adb (Add_Implicit_Operator): If the context of the expanded
	name is a call, use the number of actuals to determine whether this is
	a binary or unary operator, rather than relying on later information
	to resolve the overload.
diff mbox

Patch

Index: sem_ch8.adb
===================================================================
--- sem_ch8.adb	(revision 161073)
+++ sem_ch8.adb	(working copy)
@@ -6029,12 +6029,43 @@  package body Sem_Ch8 is
             Change_Selected_Component_To_Expanded_Name (N);
          end if;
 
-         Add_One_Interp (N, Predef_Op, T);
+         --  If the context is an unanalyzed function call, determine whether
+         --  a binary or unary interpretation is required.
 
-         --  For operators with unary and binary interpretations, add both
+         if Nkind (Parent (N)) = N_Indexed_Component then
+            declare
+               Is_Binary_Call : constant Boolean
+                 := Present (Next (First (Expressions (Parent (N)))));
+               Is_Binary_Op   : constant Boolean
+                 := First_Entity (Predef_Op) /= Last_Entity (Predef_Op);
+               Predef_Op2     : constant Entity_Id := Homonym (Predef_Op);
+
+            begin
+               if Is_Binary_Call then
+                  if Is_Binary_Op then
+                     Add_One_Interp (N, Predef_Op, T);
+                  else
+                     Add_One_Interp (N, Predef_Op2, T);
+                  end if;
 
-         if Present (Homonym (Predef_Op)) then
-            Add_One_Interp (N, Homonym (Predef_Op), T);
+               else
+                  if not Is_Binary_Op then
+                     Add_One_Interp (N, Predef_Op, T);
+                  else
+                     Add_One_Interp (N, Predef_Op2, T);
+                  end if;
+               end if;
+            end;
+
+         else
+            Add_One_Interp (N, Predef_Op, T);
+
+            --  For operators with unary and binary interpretations, if
+            --  context is not a call, add both
+
+            if Present (Homonym (Predef_Op)) then
+               Add_One_Interp (N, Homonym (Predef_Op), T);
+            end if;
          end if;
 
          --  The node is a reference to a predefined operator, and