-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

separate (Dictionary)
package body Operator_Is_Visible is

   function Check_Declarations_Are_Visible
     (Name      : SP_Symbols.SP_Symbol;
      Scope     : Dictionary.Scopes;
      Type_Mark : RawDict.Type_Info_Ref)
     return      Boolean
   --# global in CommandLineData.Content;
   --#        in Dictionary.Dict;
   is
      Current_Scope : Dictionary.Scopes;
      The_Package   : RawDict.Package_Info_Ref;
      Is_Visible    : Boolean;

      ------------------------------------------------------------------------------

      function In_Same_Immediate_Package (Inner, Outer : Dictionary.Scopes) return Boolean
      --# global in Dictionary.Dict;
      is
         Current_Scope                : Dictionary.Scopes;
         Current_Region, Outer_Region : Dictionary.Symbol;
      begin
         Current_Scope := Inner;
         Outer_Region  := Dictionary.GetRegion (Outer);
         loop
            Current_Region := Dictionary.GetRegion (Current_Scope);
            exit when Current_Region = Outer_Region
              or else RawDict.GetSymbolDiscriminant (Current_Region) = Dictionary.Package_Symbol;
            Current_Scope := Dictionary.GetEnclosingScope (Current_Scope);
         end loop;
         return Current_Region = Outer_Region;
      end In_Same_Immediate_Package;

   begin -- Check_Declarations_Are_Visible
      case CommandLineData.Content.Language_Profile is
         when CommandLineData.SPARK83 =>
            Is_Visible := In_Same_Immediate_Package (Inner => Scope,
                                                     Outer => Dictionary.Get_Type_Scope (Type_Mark => Type_Mark));
         when CommandLineData.SPARK95_Onwards =>
            Current_Scope := Scope;
            loop
               Is_Visible :=
                 In_Same_Immediate_Package (Inner => Current_Scope,
                                            Outer => Dictionary.Get_Type_Scope (Type_Mark => Type_Mark));
               exit when Is_Visible;
               Current_Scope := Dictionary.GetEnclosingScope (Current_Scope);
               exit when Current_Scope = Dictionary.GlobalScope;
            end loop;
            if not Is_Visible then
               The_Package := Dictionary.Get_Library_Package (Scope => Scope);
               if The_Package /= Dictionary.Get_Predefined_Package_Standard then
                  loop
                     The_Package := RawDict.Get_Package_Parent (The_Package => The_Package);
                     exit when The_Package = RawDict.Null_Package_Info_Ref;
                     Is_Visible :=
                       In_Same_Immediate_Package
                       (Inner => Dictionary.Set_Visibility
                          (The_Visibility => Dictionary.Visible,
                           The_Unit       => RawDict.Get_Package_Symbol (The_Package)),
                        Outer => Dictionary.Get_Type_Scope (Type_Mark => Type_Mark));
                     exit when Is_Visible;
                  end loop;
               end if;
            end if;
      end case;
      return Is_Visible
        and then (((Name = SP_Symbols.equals or else Name = SP_Symbols.not_equal)
                   and then not Dictionary.Type_Is_Limited (Type_Mark => Type_Mark,
                                                            Scope     => Scope))
                  or else ((Name /= SP_Symbols.equals and then Name /= SP_Symbols.not_equal)
                           and then not Dictionary.Type_Is_Private_Here (Type_Mark => Type_Mark,
                                                                         Scope     => Scope)));
   end Check_Declarations_Are_Visible;

   --------------------------------------------------------------------------------

   function Symmetric_Operators_Are_Visible
     (Name      : SP_Symbols.SP_Symbol;
      Type_Mark : RawDict.Type_Info_Ref;
      Scope     : Dictionary.Scopes)
     return      Boolean
   --# global in CommandLineData.Content;
   --#        in Dictionary.Dict;
   is
   begin
      return Type_Mark = Dictionary.Get_Unknown_Type_Mark
        or else Dictionary.Defined_In_Package_Standard (Type_Mark => Type_Mark)
        or else Check_Declarations_Are_Visible (Name      => Name,
                                                Scope     => Scope,
                                                Type_Mark => Type_Mark);
   end Symmetric_Operators_Are_Visible;

   --------------------------------------------------------------------------------

   function Type_Is_Used
     (Name      : SP_Symbols.SP_Symbol;
      Type_Mark : RawDict.Type_Info_Ref;
      Scope     : Dictionary.Scopes)
     return      Boolean
   --# global in CommandLineData.Content;
   --#        in Dictionary.Dict;
   is
      Current_Scope : Dictionary.Scopes;
      The_Package   : RawDict.Package_Info_Ref;
      Region        : Dictionary.Symbol;
      Found         : Boolean;

      --------------------------------------------------------------------------------

      function Is_Used_In_This_Scope (Type_Mark : RawDict.Type_Info_Ref;
                                      Scope     : Dictionary.Scopes) return Boolean
      --# global in Dictionary.Dict;
      is
         Region : Dictionary.Symbol;
         Found  : Boolean;

         --------------------------------------------------------------------------------

         function Is_Used (Type_Mark : RawDict.Type_Info_Ref;
                           Scope     : Dictionary.Scopes) return Boolean
         --# global in Dictionary.Dict;
         is
            Region              : Dictionary.Symbol;
            The_Use_Type_Clause : RawDict.Use_Type_Clause_Info_Ref;
            Result              : Boolean;
         begin
            Region := Dictionary.GetRegion (Scope);
            Result := Dictionary.Is_Used_Locally (Type_Mark => Type_Mark,
                                                  Scope     => Scope);
            if not Result
              and then RawDict.GetSymbolDiscriminant (Region) = Dictionary.Package_Symbol
              and then Dictionary.Get_Visibility (Scope => Scope) = Dictionary.Local then
               The_Use_Type_Clause :=
                 RawDict.Get_Package_Visible_Use_Type_Clauses (The_Package => RawDict.Get_Package_Info_Ref (Item => Region));
               while The_Use_Type_Clause /= RawDict.Null_Use_Type_Clause_Info_Ref
                 and then RawDict.Get_Use_Type_Clause_Type (The_Use_Type_Clause => The_Use_Type_Clause) /= Type_Mark loop
                  The_Use_Type_Clause := RawDict.Get_Next_Use_Type_Clause (The_Use_Type_Clause => The_Use_Type_Clause);
               end loop;
               Result := The_Use_Type_Clause /= RawDict.Null_Use_Type_Clause_Info_Ref;
            end if;
            return Result;
         end Is_Used;

      begin -- Is_Used_In_This_Scope
         Region := Dictionary.GetRegion (Scope);
         case RawDict.GetSymbolDiscriminant (Region) is
            when Dictionary.Package_Symbol =>
               Found := Is_Used (Type_Mark => Type_Mark,
                                 Scope     => Scope);
            when Dictionary.Subprogram_Symbol =>
               Found := Is_Used (Type_Mark => Type_Mark,
                                 Scope     => Scope);
            when Dictionary.Type_Symbol => -- Task/Protected type
               SystemErrors.RT_Assert
                 (C       => Dictionary.Is_Task_Type (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Region))
                    or else Dictionary.Is_Protected_Type (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Region)),
                  Sys_Err => SystemErrors.Invalid_Symbol_Table,
                  Msg     => "in Dictionary.Is_Used_In_This_Scope");
               Found := Is_Used (Type_Mark => Type_Mark,
                                 Scope     => Scope);
            when others =>
               Found := False;
         end case;
         return Found;
      end Is_Used_In_This_Scope;

      --------------------------------------------------------------------------------

      function Type_Exports_Operators (Type_Mark : RawDict.Type_Info_Ref;
                                       Scope     : Dictionary.Scopes) return Boolean
      --# global in CommandLineData.Content;
      --#        in Dictionary.Dict;
      is
      begin
         return not Dictionary.Type_Is_Private_Here (Type_Mark => Type_Mark,
                                                     Scope     => Scope)
           or else (CommandLineData.Ravenscar_Selected and then Dictionary.Is_Predefined_Time_Type (Type_Mark => Type_Mark));
      end Type_Exports_Operators;

   begin -- Type_Is_Used
      case CommandLineData.Content.Language_Profile is
         when CommandLineData.SPARK83 =>
            Found := False;
         when CommandLineData.SPARK95_Onwards =>
            if Dictionary.Defined_In_Package_Standard (Type_Mark => Type_Mark) then  -- can't possible be in a use type clause
               Found := False;
            else
               Current_Scope := Scope;
               loop
                  Found := Is_Used_In_This_Scope (Type_Mark => Type_Mark,
                                                  Scope     => Current_Scope);
                  exit when Found;
                  Region := Dictionary.GetRegion (Current_Scope);

                  exit when RawDict.GetSymbolDiscriminant (Region) = Dictionary.Subprogram_Symbol
                    and then Dictionary.Is_Main_Program
                    (The_Subprogram => RawDict.Get_Subprogram_Info_Ref (Item => Region));
                  Current_Scope := Dictionary.GetEnclosingScope (Current_Scope);
                  exit when Current_Scope = Dictionary.GlobalScope;
               end loop;
               if Current_Scope = Dictionary.GlobalScope then
                  The_Package := Dictionary.Get_Library_Package (Scope => Scope);
                  if The_Package /= Dictionary.Get_Predefined_Package_Standard then
                     loop
                        The_Package := RawDict.Get_Package_Parent (The_Package => The_Package);
                        exit when The_Package = RawDict.Null_Package_Info_Ref;
                        Found :=
                          Is_Used_In_This_Scope
                          (Type_Mark => Type_Mark,
                           Scope     => Dictionary.Set_Visibility
                             (The_Visibility => Dictionary.Visible,
                              The_Unit       => RawDict.Get_Package_Symbol (The_Package)));
                        exit when Found;
                     end loop;
                  end if;
               end if;
            end if;
      end case;
      return Found
        and then (Name = SP_Symbols.equals
                    or else Name = SP_Symbols.not_equal
                    or else Type_Exports_Operators (Type_Mark => Type_Mark,
                                                    Scope     => Scope));
   end Type_Is_Used;

   --------------------------------------------------------------------------------

   function Operator_Is_Renamed
     (Name               : SP_Symbols.SP_Symbol;
      Is_Binary_Operator : Boolean;
      The_Left_Type      : RawDict.Type_Info_Ref;
      The_Right_Type     : RawDict.Type_Info_Ref;
      Scope              : Dictionary.Scopes)
     return               Boolean
   --# global in CommandLineData.Content;
   --#        in Dictionary.Dict;
   is
      Current_Scope : Dictionary.Scopes;
      The_Package   : RawDict.Package_Info_Ref;
      Region        : Dictionary.Symbol;
      Found         : Boolean;

      --------------------------------------------------------------------------------

      function Is_Renamed_In_This_Scope
        (Name               : SP_Symbols.SP_Symbol;
         Is_Binary_Operator : Boolean;
         The_Left_Type      : RawDict.Type_Info_Ref;
         The_Right_Type     : RawDict.Type_Info_Ref;
         Scope              : Dictionary.Scopes)
        return               Boolean
      --# global in Dictionary.Dict;
      is
         Region : Dictionary.Symbol;
         Found  : Boolean;

         --------------------------------------------------------------------------------

         function Search_Renaming_Declarations
           (Name               : SP_Symbols.SP_Symbol;
            Is_Binary_Operator : Boolean;
            The_Left_Type      : RawDict.Type_Info_Ref;
            The_Right_Type     : RawDict.Type_Info_Ref;
            Declarations       : RawDict.Declaration_Info_Ref)
           return               Boolean
         --# global in Dictionary.Dict;
         is
            Current : RawDict.Declaration_Info_Ref;
            Item    : Dictionary.Symbol;
         begin
            Current := Declarations;
            loop
               exit when Current = RawDict.Null_Declaration_Info_Ref;
               Item := RawDict.Get_Declaration_Item (The_Declaration => Current);
               exit when RawDict.GetSymbolDiscriminant (Item) = Dictionary.Operator_Symbol
                 and then RawDict.Get_Operator_Name (The_Operator => RawDict.Get_Operator_Info_Ref (Item => Item)) =
                 Name
                 and then RawDict.Get_Operator_Is_Binary (The_Operator => RawDict.Get_Operator_Info_Ref (Item => Item)) =
                 Is_Binary_Operator
                 and then ((Is_Binary_Operator
                              and then RawDict.Get_Operator_Left_Operand
                              (The_Operator => RawDict.Get_Operator_Info_Ref (Item => Item)) =
                              The_Left_Type
                              and then RawDict.Get_Operator_Right_Operand
                              (The_Operator => RawDict.Get_Operator_Info_Ref (Item => Item)) =
                              The_Right_Type)
                           or else (not Is_Binary_Operator
                                      and then RawDict.Get_Operator_Operand
                                      (The_Operator => RawDict.Get_Operator_Info_Ref (Item => Item)) =
                                      The_Left_Type));
               Current := RawDict.Get_Next_Declaration (The_Declaration => Current);
            end loop;
            return Current /= RawDict.Null_Declaration_Info_Ref;
         end Search_Renaming_Declarations;

         --------------------------------------------------------------------------------

         function Is_Renamed_In_This_Package
           (Name               : SP_Symbols.SP_Symbol;
            Is_Binary_Operator : Boolean;
            The_Left_Type      : RawDict.Type_Info_Ref;
            The_Right_Type     : RawDict.Type_Info_Ref;
            The_Package        : RawDict.Package_Info_Ref;
            The_Visibility     : Dictionary.Visibility)
           return               Boolean
         --# global in Dictionary.Dict;
         is
            Found : Boolean;

            --------------------------------------------------------------------------------

            function Is_Renamed_In_This_Package_Specification
              (Name               : SP_Symbols.SP_Symbol;
               Is_Binary_Operator : Boolean;
               The_Left_Type      : RawDict.Type_Info_Ref;
               The_Right_Type     : RawDict.Type_Info_Ref;
               The_Package        : RawDict.Package_Info_Ref)
              return               Boolean
            --# global in Dictionary.Dict;
            is
            begin
               return Search_Renaming_Declarations
                 (Name               => Name,
                  Is_Binary_Operator => Is_Binary_Operator,
                  The_Left_Type      => The_Left_Type,
                  The_Right_Type     => The_Right_Type,
                  Declarations       => RawDict.Get_Package_Visible_Renaming_Declarations (The_Package => The_Package));
            end Is_Renamed_In_This_Package_Specification;

            --------------------------------------------------------------------------------

            function Is_Renamed_In_This_Package_Body
              (Name               : SP_Symbols.SP_Symbol;
               Is_Binary_Operator : Boolean;
               The_Left_Type      : RawDict.Type_Info_Ref;
               The_Right_Type     : RawDict.Type_Info_Ref;
               The_Package        : RawDict.Package_Info_Ref)
              return               Boolean
            --# global in Dictionary.Dict;
            is
            begin
               return Search_Renaming_Declarations
                 (Name               => Name,
                  Is_Binary_Operator => Is_Binary_Operator,
                  The_Left_Type      => The_Left_Type,
                  The_Right_Type     => The_Right_Type,
                  Declarations       => RawDict.Get_Package_Local_Renaming_Declarations (The_Package => The_Package));
            end Is_Renamed_In_This_Package_Body;

         begin -- Is_Renamed_In_This_Package
            case The_Visibility is
               when Dictionary.Visible | Dictionary.Privat =>
                  Found :=
                    Is_Renamed_In_This_Package_Specification
                    (Name               => Name,
                     Is_Binary_Operator => Is_Binary_Operator,
                     The_Left_Type      => The_Left_Type,
                     The_Right_Type     => The_Right_Type,
                     The_Package        => The_Package);
               when Dictionary.Local =>
                  Found :=
                    Is_Renamed_In_This_Package_Body
                    (Name               => Name,
                     Is_Binary_Operator => Is_Binary_Operator,
                     The_Left_Type      => The_Left_Type,
                     The_Right_Type     => The_Right_Type,
                     The_Package        => The_Package)
                    or else Is_Renamed_In_This_Package_Specification
                    (Name               => Name,
                     Is_Binary_Operator => Is_Binary_Operator,
                     The_Left_Type      => The_Left_Type,
                     The_Right_Type     => The_Right_Type,
                     The_Package        => The_Package);
            end case;
            return Found;
         end Is_Renamed_In_This_Package;

         --------------------------------------------------------------------------------

         function Is_Renamed_In_This_Subprogram
           (Name               : SP_Symbols.SP_Symbol;
            Is_Binary_Operator : Boolean;
            The_Left_Type      : RawDict.Type_Info_Ref;
            The_Right_Type     : RawDict.Type_Info_Ref;
            The_Subprogram     : RawDict.Subprogram_Info_Ref)
           return               Boolean
         --# global in Dictionary.Dict;
         is
         begin
            return Search_Renaming_Declarations
              (Name               => Name,
               Is_Binary_Operator => Is_Binary_Operator,
               The_Left_Type      => The_Left_Type,
               The_Right_Type     => The_Right_Type,
               Declarations       => RawDict.Get_Subprogram_Renaming_Declarations (The_Subprogram => The_Subprogram));
         end Is_Renamed_In_This_Subprogram;

      begin -- Is_Renamed_In_This_Scope
         Region := Dictionary.GetRegion (Scope);
         case RawDict.GetSymbolDiscriminant (Region) is
            when Dictionary.Package_Symbol =>
               Found :=
                 Is_Renamed_In_This_Package
                 (Name               => Name,
                  Is_Binary_Operator => Is_Binary_Operator,
                  The_Left_Type      => The_Left_Type,
                  The_Right_Type     => The_Right_Type,
                  The_Package        => RawDict.Get_Package_Info_Ref (Item => Region),
                  The_Visibility     => Dictionary.Get_Visibility (Scope => Scope));
            when Dictionary.Subprogram_Symbol =>
               Found :=
                 Is_Renamed_In_This_Subprogram
                 (Name               => Name,
                  Is_Binary_Operator => Is_Binary_Operator,
                  The_Left_Type      => The_Left_Type,
                  The_Right_Type     => The_Right_Type,
                  The_Subprogram     => RawDict.Get_Subprogram_Info_Ref (Item => Region));
            when others =>
               Found := False;
         end case;
         return Found;
      end Is_Renamed_In_This_Scope;

   begin -- Operator_Is_Renamed
      Current_Scope := Scope;
      loop
         Found :=
           Is_Renamed_In_This_Scope
           (Name               => Name,
            Is_Binary_Operator => Is_Binary_Operator,
            The_Left_Type      => The_Left_Type,
            The_Right_Type     => The_Right_Type,
            Scope              => Current_Scope);
         exit when Found;
         Region := Dictionary.GetRegion (Current_Scope);
         exit when (RawDict.GetSymbolDiscriminant (Region) = Dictionary.Package_Symbol
                      and then CommandLineData.Content.Language_Profile = CommandLineData.SPARK83)
           or else (RawDict.GetSymbolDiscriminant (Region) = Dictionary.Subprogram_Symbol
                      and then Dictionary.Is_Main_Program (The_Subprogram => RawDict.Get_Subprogram_Info_Ref (Item => Region)));
         Current_Scope := Dictionary.GetEnclosingScope (Current_Scope);
         exit when Current_Scope = Dictionary.GlobalScope;
      end loop;
      if Current_Scope = Dictionary.GlobalScope then
         The_Package := Dictionary.Get_Library_Package (Scope => Scope);
         if The_Package /= Dictionary.Get_Predefined_Package_Standard then
            loop
               The_Package := RawDict.Get_Package_Parent (The_Package => The_Package);
               exit when The_Package = RawDict.Null_Package_Info_Ref;
               Found :=
                 Is_Renamed_In_This_Scope
                 (Name               => Name,
                  Is_Binary_Operator => Is_Binary_Operator,
                  The_Left_Type      => The_Left_Type,
                  The_Right_Type     => The_Right_Type,
                  Scope              => Dictionary.Set_Visibility
                    (The_Visibility => Dictionary.Visible,
                     The_Unit       => RawDict.Get_Package_Symbol (The_Package)));
               exit when Found;
            end loop;
         end if;
      end if;
      return Found;
   end Operator_Is_Renamed;

   --------------------------------------------------------------------------------

   function Unary_Operator_Is_Visible
     (Name      : SP_Symbols.SP_Symbol;
      Type_Mark : RawDict.Type_Info_Ref;
      Scope     : Dictionary.Scopes)
     return      Boolean
   is
   begin
      return Symmetric_Operators_Are_Visible (Name      => Name,
                                              Type_Mark => Type_Mark,
                                              Scope     => Scope)
        or else Type_Is_Used (Name      => Name,
                              Type_Mark => Type_Mark,
                              Scope     => Scope)
        or else Operator_Is_Renamed
        (Name               => Name,
         Is_Binary_Operator => False,
         The_Left_Type      => Type_Mark,
         The_Right_Type     => RawDict.Null_Type_Info_Ref,
         Scope              => Scope);
   end Unary_Operator_Is_Visible;

   --------------------------------------------------------------------------------

   function Binary_Operator_Is_Visible
     (Name           : SP_Symbols.SP_Symbol;
      The_Left_Type  : RawDict.Type_Info_Ref;
      The_Right_Type : RawDict.Type_Info_Ref;
      Scope          : Dictionary.Scopes)
     return           Boolean
   is
      function Is_Directly_Visible
        (Name           : SP_Symbols.SP_Symbol;
         The_Left_Type  : RawDict.Type_Info_Ref;
         The_Right_Type : RawDict.Type_Info_Ref;
         Scope          : Dictionary.Scopes)
        return           Boolean
      --# global in CommandLineData.Content;
      --#        in Dictionary.Dict;
      is
         Is_Visible : Boolean;

         --------------------------------------------------------------------------------

         function Asymmetric_Operators_Are_Visible
           (Name           : SP_Symbols.SP_Symbol;
            The_Left_Type  : RawDict.Type_Info_Ref;
            The_Right_Type : RawDict.Type_Info_Ref;
            Scope          : Dictionary.Scopes)
           return           Boolean
         --# global in CommandLineData.Content;
         --#        in Dictionary.Dict;
         is
            Is_Visible : Boolean;
         begin
            if The_Left_Type = Dictionary.Get_Unknown_Type_Mark
              or else Dictionary.Defined_In_Package_Standard (Type_Mark => The_Left_Type) then
               Is_Visible := The_Right_Type = Dictionary.Get_Unknown_Type_Mark
                 or else Dictionary.Defined_In_Package_Standard (Type_Mark => The_Right_Type)
                 or else Check_Declarations_Are_Visible (Name      => Name,
                                                         Scope     => Scope,
                                                         Type_Mark => The_Right_Type);
            elsif The_Right_Type = Dictionary.Get_Unknown_Type_Mark
              or else Dictionary.Defined_In_Package_Standard (Type_Mark => The_Right_Type) then
               Is_Visible := Check_Declarations_Are_Visible (Name      => Name,
                                                             Scope     => Scope,
                                                             Type_Mark => The_Left_Type);
            else
               Is_Visible := Check_Declarations_Are_Visible (Name      => Name,
                                                             Scope     => Scope,
                                                             Type_Mark => The_Left_Type)
                 and then Check_Declarations_Are_Visible (Name      => Name,
                                                          Scope     => Scope,
                                                          Type_Mark => The_Right_Type);
            end if;
            return Is_Visible;
         end Asymmetric_Operators_Are_Visible;

      begin -- Is_Directly_Visible
         if Name = SP_Symbols.multiply
           and then (Dictionary.Type_Is_Fixed_Point (Type_Mark => The_Left_Type)
                       or else The_Left_Type = Dictionary.Get_Unknown_Type_Mark)
           and then (Dictionary.Type_Is_Fixed_Point (Type_Mark => The_Right_Type)
                       or else The_Right_Type = Dictionary.Get_Unknown_Type_Mark) then
            Is_Visible := True;
         elsif Name = SP_Symbols.divide
           and then (Dictionary.Type_Is_Fixed_Point (Type_Mark => The_Left_Type)
                       or else The_Left_Type = Dictionary.Get_Unknown_Type_Mark)
           and then (Dictionary.Type_Is_Fixed_Point (Type_Mark => The_Right_Type)
                       or else The_Right_Type = Dictionary.Get_Unknown_Type_Mark) then
            Is_Visible := True;
         elsif The_Left_Type = The_Right_Type then
            Is_Visible := Symmetric_Operators_Are_Visible (Name      => Name,
                                                           Type_Mark => The_Left_Type,
                                                           Scope     => Scope);
         else
            Is_Visible :=
              Asymmetric_Operators_Are_Visible
              (Name           => Name,
               The_Left_Type  => The_Left_Type,
               The_Right_Type => The_Right_Type,
               Scope          => Scope);
         end if;
         return Is_Visible;
      end Is_Directly_Visible;

      --------------------------------------------------------------------------------

      function Binary_Operator_Is_Renamed
        (Name           : SP_Symbols.SP_Symbol;
         The_Left_Type  : RawDict.Type_Info_Ref;
         The_Right_Type : RawDict.Type_Info_Ref;
         Scope          : Dictionary.Scopes)
        return           Boolean
      --# global in CommandLineData.Content;
      --#        in Dictionary.Dict;
      is
         Name_To_Look_For : SP_Symbols.SP_Symbol;
      begin
         if Name = SP_Symbols.not_equal then
            Name_To_Look_For := SP_Symbols.equals;
         else
            Name_To_Look_For := Name;
         end if;
         return Operator_Is_Renamed
           (Name               => Name_To_Look_For,
            Is_Binary_Operator => True,
            The_Left_Type      => The_Left_Type,
            The_Right_Type     => The_Right_Type,
            Scope              => Scope);
      end Binary_Operator_Is_Renamed;

   begin -- Binary_Operator_Is_Visible
      return Is_Directly_Visible (Name           => Name,
                                  The_Left_Type  => The_Left_Type,
                                  The_Right_Type => The_Right_Type,
                                  Scope          => Scope)
        or else Type_Is_Used (Name      => Name,
                              Type_Mark => The_Left_Type,
                              Scope     => Scope)
        or else Type_Is_Used (Name      => Name,
                              Type_Mark => The_Right_Type,
                              Scope     => Scope)
        or else Binary_Operator_Is_Renamed
        (Name           => Name,
         The_Left_Type  => The_Left_Type,
         The_Right_Type => The_Right_Type,
         Scope          => Scope);
   end Binary_Operator_Is_Visible;

end Operator_Is_Visible;
