sem_ch4.adb (Operator_Check): improve error message when both a with_clause and a...
authorEd Schonberg <schonberg@adacore.com>
Mon, 1 Aug 2011 13:33:29 +0000 (13:33 +0000)
committerArnaud Charlet <charlet@gcc.gnu.org>
Mon, 1 Aug 2011 13:33:29 +0000 (15:33 +0200)
2011-08-01  Ed Schonberg  <schonberg@adacore.com>

* sem_ch4.adb (Operator_Check): improve error message when both a
with_clause and a use_clause are needed to make operator usage legal.
* sem_util.ads, sem_util.adb (Unit_Is_Visible): new predicate to
determine whether a compilation unit is visible within an other,
either through a with_clause in the current unit, or a with_clause in
its library unit or one one of its parents.

From-SVN: r177033

gcc/ada/ChangeLog
gcc/ada/sem_ch4.adb
gcc/ada/sem_util.adb
gcc/ada/sem_util.ads

index 3b9ede5f660f71f329913b00b3f6244b9e10fa7e..364abb5730592640c9c34726f1d0b1d2108646fd 100644 (file)
@@ -1,3 +1,12 @@
+2011-08-01  Ed Schonberg  <schonberg@adacore.com>
+
+       * sem_ch4.adb (Operator_Check): improve error message when both a
+       with_clause and a use_clause are needed to make operator usage legal.
+       * sem_util.ads, sem_util.adb (Unit_Is_Visible): new predicate to
+       determine whether a compilation unit is visible within an other,
+       either through a with_clause in the current unit, or a with_clause in
+       its library unit or one one of its parents.
+
 2011-08-01  Ed Schonberg  <schonberg@adacore.com>
 
        * exp_ch5.adb (Expand_N_Iterator_Loop): handle properly an iterator
index 086e3a68a357d11cdaadd36bcc124ee8df70b0dd..af65aea0a21ff6b6cf528a405e8197fa0fd5e90a 100644 (file)
@@ -3222,8 +3222,8 @@ package body Sem_Ch4 is
       if Present (Loop_Parameter_Specification (N)) then
          Iterator :=
            Make_Iteration_Scheme (Loc,
-              Loop_Parameter_Specification =>
-                Loop_Parameter_Specification (N));
+             Loop_Parameter_Specification =>
+               Loop_Parameter_Specification (N));
       else
          Iterator :=
            Make_Iteration_Scheme (Loc,
@@ -5687,8 +5687,22 @@ package body Sem_Ch4 is
                Error_Msg_NE -- CODEFIX
                  ("operator for} is not directly visible!",
                   N, First_Subtype (Candidate_Type));
-               Error_Msg_N -- CODEFIX
-                 ("use clause would make operation legal!",  N);
+
+               declare
+                  U : constant Node_Id :=
+                        Cunit (Get_Source_Unit (Candidate_Type));
+
+               begin
+                  if Unit_Is_Visible (U) then
+                     Error_Msg_N -- CODEFIX
+                       ("use clause would make operation legal!",  N);
+
+                  else
+                     Error_Msg_NE  --  CODEFIX
+                       ("add with_clause and use_clause for&!",
+                          N, Defining_Entity (Unit (U)));
+                  end if;
+               end;
                return;
 
             --  If either operand is a junk operand (e.g. package name), then
index 5fcfd6f786b88e6a216dd63894963e11033a374d..689a04f0980d1ee05bc55d47a0b7e08750558aa2 100644 (file)
@@ -11533,6 +11533,109 @@ package body Sem_Util is
       return N;
    end Unit_Declaration_Node;
 
+   ---------------------
+   -- Unit_Is_Visible --
+   ---------------------
+
+   function Unit_Is_Visible (U : Entity_Id) return Boolean is
+      Curr        : constant Node_Id   := Cunit (Current_Sem_Unit);
+      Curr_Entity : constant Entity_Id := Cunit_Entity (Current_Sem_Unit);
+
+      function Unit_In_Parent_Context (Par_Unit : Node_Id) return Boolean;
+      --  For a child unit, check whether unit appears in a with_clause
+      --  of a parent.
+
+      function Unit_In_Context (Comp_Unit : Node_Id) return Boolean;
+      --  Scan the context clause of one compilation unit looking for a
+      --  with_clause for the unit in question.
+
+      ----------------------------
+      -- Unit_In_Parent_Context --
+      ----------------------------
+
+      function Unit_In_Parent_Context (Par_Unit : Node_Id) return Boolean
+      is
+      begin
+         if Unit_In_Context (Par_Unit) then
+            return True;
+
+         elsif Is_Child_Unit (Defining_Entity (Unit (Par_Unit))) then
+            return Unit_In_Parent_Context (Parent_Spec (Unit (Par_Unit)));
+
+         else
+            return False;
+         end if;
+      end Unit_In_Parent_Context;
+
+      ---------------------
+      -- Unit_In_Context --
+      ---------------------
+
+      function Unit_In_Context (Comp_Unit : Node_Id) return Boolean is
+         Clause : Node_Id;
+
+      begin
+         Clause := First (Context_Items (Comp_Unit));
+         while Present (Clause) loop
+            if Nkind (Clause) = N_With_Clause then
+               if Library_Unit (Clause) = U then
+                  return True;
+
+               --  The with_clause may denote a renaming of the unit we are
+               --  looking for, eg. Text_IO which renames Ada.Text_IO.
+
+               elsif
+                 Renamed_Entity (Entity (Name (Clause)))
+                   = Defining_Entity (Unit (U))
+               then
+                  return True;
+               end if;
+            end if;
+
+            Next (Clause);
+         end loop;
+         return False;
+      end Unit_In_Context;
+
+   begin
+
+      --  The currrent unit is directly visible.
+
+      if Curr = U then
+         return True;
+
+      elsif Unit_In_Context (Curr) then
+         return True;
+
+      --  If the current unit is a body, check the context of the spec.
+
+      elsif Nkind (Unit (Curr)) = N_Package_Body
+        or else
+          (Nkind (Unit (Curr)) = N_Subprogram_Body
+            and then not Acts_As_Spec (Unit (Curr)))
+      then
+
+         if Unit_In_Context (Library_Unit (Curr)) then
+            return True;
+         end if;
+      end if;
+
+      --  If the spec is a child unit, examine the parents.
+
+      if Is_Child_Unit (Curr_Entity) then
+         if Nkind (Unit (Curr)) in N_Unit_Body then
+            return
+              Unit_In_Parent_Context
+                (Parent_Spec (Unit (Library_Unit (Curr))));
+         else
+            return Unit_In_Parent_Context (Parent_Spec (Unit (Curr)));
+         end if;
+
+      else
+         return False;
+      end if;
+   end Unit_Is_Visible;
+
    ------------------------------
    -- Universal_Interpretation --
    ------------------------------
index d892a4c44531188d3efacb8bc792c02f630eb750..df74a1f568931495b0872653f791824624df0411 100644 (file)
@@ -1316,6 +1316,11 @@ package Sem_Util is
    --  it returns the subprogram, task or protected body node for it. The unit
    --  may be a child unit with any number of ancestors.
 
+   function Unit_Is_Visible (U : Entity_Id) return Boolean;
+   --  Determine whether a compilation unit is visible in the current context,
+   --  because there is a with_clause that makes the unit available. Used to
+   --  provide better messages on common visiblity errors on operators.
+
    function Universal_Interpretation (Opnd : Node_Id) return Entity_Id;
    --  Yields Universal_Integer or Universal_Real if this is a candidate