A new restriction No_Use_Of_Entity is implemented. The form of this is
pragma Restriction[_Warning]s (No_Use_Of_Entity => NAME), where NAME is
a fully qualified entity name. The effect is to forbid references to
this entity in the main unit, its spec, and any subunits.

The following is compiled with -gnatl -gnatj55

     1. pragma Restrictions
     2.   (No_Use_Of_Entity => Ada.Text_IO.Put_Line);
     3. with Ada.Text_IO; use Ada.Text_IO;
     4. procedure NUOE is
     5. begin
     6.    Put ("Hello");
     7.    Put_Line ("Hello_World!");
           |
        >>> reference to "Put_Line" violates
            restriction No_Use_Of_Entity at line 2

     8. end;

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

2015-01-07  Robert Dewar  <de...@adacore.com>

        * restrict.adb (Check_Restriction_No_Use_Of_Attribute):
        New procedure.
        (OK_No_Use_Of_Entity_Name): New function.
        (Set_Restriction_No_Use_Of_Entity): New procedure.
        * restrict.ads (Check_Restriction_No_Use_Of_Attribute):
        New procedure.
        (OK_No_Use_Of_Entity_Name): New function.
        (Set_Restriction_No_Use_Of_Entity): New procedure.
        * sem_ch8.adb (Find_Direct_Name): Add check for violation of
        No_Use_Of_Entity.
        * sem_prag.adb (Process_Restrictions_Or_Restriction_Warnings):
        Add processing for new restriction No_Use_Of_Entity.

Index: sem_prag.adb
===================================================================
--- sem_prag.adb        (revision 219280)
+++ sem_prag.adb        (working copy)
@@ -8895,13 +8895,26 @@
                   Set_Restriction_No_Use_Of_Attribute (Expr, Warn);
                end if;
 
-            --  Case of No_Use_Of_Entity => fully-qualified-name. Note that the
-            --  parser already processed this case commpletely, including error
-            --  checking and making an entry in the No_Use_Of_Entity table.
+            --  Case of No_Use_Of_Entity => fully-qualified-name
 
             elsif Id = Name_No_Use_Of_Entity then
-               null;
 
+               --  Restriction is only recognized within a configuration
+               --  pragma file, or within a unit of the main extended
+               --  program. Note: the test for Main_Unit is needed to
+               --  properly include the case of configuration pragma files.
+
+               if Current_Sem_Unit = Main_Unit
+                 or else In_Extended_Main_Source_Unit (N)
+               then
+                  if not OK_No_Dependence_Unit_Name (Expr) then
+                     Error_Msg_N ("wrong form for entity name", Expr);
+                  else
+                     Set_Restriction_No_Use_Of_Entity
+                       (Expr, Warn, No_Profile);
+                  end if;
+               end if;
+
             --  Case of No_Use_Of_Pragma => pragma-identifier
 
             elsif Id = Name_No_Use_Of_Pragma then
@@ -8909,7 +8922,6 @@
                  or else not Is_Pragma_Name (Chars (Expr))
                then
                   Error_Msg_N ("unknown pragma name??", Expr);
-
                else
                   Set_Restriction_No_Use_Of_Pragma (Expr, Warn);
                end if;
@@ -14941,7 +14953,7 @@
          -- Independent_Components --
          ----------------------------
 
-         --  pragma Atomic_Components (array_or_record_LOCAL_NAME);
+         --  pragma Independent_Components (array_or_record_LOCAL_NAME);
 
          when Pragma_Independent_Components => Independent_Components : declare
             E_Id : Node_Id;
Index: restrict.adb
===================================================================
--- restrict.adb        (revision 219191)
+++ restrict.adb        (working copy)
@@ -128,6 +128,10 @@
    --  real violation, serious vs non-serious, implicit vs explicit, the second
    --  message giving the profile name if needed, and the location information.
 
+   function Same_Entity (E1, E2 : Node_Id) return Boolean;
+   --  Returns True iff E1 and E2 represent the same entity. Used for handling
+   --  of No_Use_Of_Entity => fully_qualified_ENTITY restriction case.
+
    function Same_Unit (U1, U2 : Node_Id) return Boolean;
    --  Returns True iff U1 and U2 represent the same library unit. Used for
    --  handling of No_Dependence => Unit restriction case.
@@ -681,6 +685,98 @@
    end Check_Restriction_No_Use_Of_Attribute;
 
    ----------------------------------------
+   -- Check_Restriction_No_Use_Of_Entity --
+   ----------------------------------------
+
+   procedure Check_Restriction_No_Use_Of_Entity (N : Node_Id) is
+   begin
+      --  Error defence (not clearly necessary, but better safe)
+
+      if No (Entity (N)) then
+         return;
+      end if;
+
+      --  If simple name of entity not flagged with Boolean2 flag, then there
+      --  cannot be a matching entry in the table, so skip the search.
+
+      if Get_Name_Table_Boolean2 (Chars (Entity (N))) = False then
+         return;
+      end if;
+
+      --  Restriction is only recognized within a configuration
+      --  pragma file, or within a unit of the main extended
+      --  program. Note: the test for Main_Unit is needed to
+      --  properly include the case of configuration pragma files.
+
+      if Current_Sem_Unit /= Main_Unit
+        and then not In_Extended_Main_Source_Unit (N)
+      then
+         return;
+      end if;
+
+      --  Here we must search the table
+
+      for J in No_Use_Of_Entity.First .. No_Use_Of_Entity.Last loop
+         declare
+            NE_Ent : NE_Entry renames No_Use_Of_Entity.Table (J);
+            Ent    : Entity_Id;
+            Expr   : Node_Id;
+
+         begin
+            Ent  := Entity (N);
+            Expr := NE_Ent.Entity;
+            loop
+               --  Here if at outer level of entity name in reference
+
+               if Scope (Ent) = Standard_Standard then
+                  if Nkind_In (Expr, N_Identifier, N_Operator_Symbol)
+                    and then Chars (Ent) = Chars (Expr)
+                  then
+                     Error_Msg_Node_1 := N;
+                     Error_Msg_Warn := NE_Ent.Warn;
+                     Error_Msg_Sloc := Sloc (NE_Ent.Entity);
+                     Error_Msg_N
+                       ("<*<reference to & violates restriction "
+                        & "No_Use_Of_Entity #", N);
+                     return;
+
+                  else
+                     goto Continue;
+                  end if;
+
+               --  Here if at outer level of entity name in table
+
+               elsif Nkind_In (Expr, N_Identifier, N_Operator_Symbol) then
+                  goto Continue;
+
+               --  Here if neither at the outer level
+
+               else
+                  pragma Assert (Nkind (Expr) = N_Selected_Component);
+
+                  if Chars (Selector_Name (Expr)) /= Chars (Ent) then
+                     goto Continue;
+                  end if;
+               end if;
+
+               --  Move up a level
+
+               loop
+                  Ent := Scope (Ent);
+                  exit when not Is_Internal_Name (Chars (Ent));
+               end loop;
+
+               Expr := Prefix (Expr);
+
+               --  Entry did not match
+
+               <<Continue>> null;
+            end loop;
+         end;
+      end loop;
+   end Check_Restriction_No_Use_Of_Entity;
+
+   ----------------------------------------
    -- Check_Restriction_No_Use_Of_Pragma --
    ----------------------------------------
 
@@ -864,6 +960,27 @@
       end if;
    end OK_No_Dependence_Unit_Name;
 
+   ------------------------------
+   -- OK_No_Use_Of_Entity_Name --
+   ------------------------------
+
+   function OK_No_Use_Of_Entity_Name (N : Node_Id) return Boolean is
+   begin
+      if Nkind (N) = N_Selected_Component then
+         return
+           OK_No_Use_Of_Entity_Name (Prefix (N))
+             and then
+           OK_No_Use_Of_Entity_Name (Selector_Name (N));
+
+      elsif Nkind_In (N, N_Identifier, N_Operator_Symbol) then
+         return True;
+
+      else
+         Error_Msg_N ("wrong form for entity name for No_Use_Of_Entity", N);
+         return False;
+      end if;
+   end OK_No_Use_Of_Entity_Name;
+
    ----------------------------------
    -- Process_Restriction_Synonyms --
    ----------------------------------
@@ -1146,6 +1263,30 @@
       end if;
    end Restriction_Msg;
 
+   -----------------
+   -- Same_Entity --
+   -----------------
+
+   function Same_Entity (E1, E2 : Node_Id) return Boolean is
+   begin
+      if Nkind_In (E1, N_Identifier, N_Operator_Symbol)
+           and then
+         Nkind_In (E2, N_Identifier, N_Operator_Symbol)
+      then
+         return Chars (E1) = Chars (E2);
+
+      elsif Nkind_In (E1, N_Selected_Component, N_Expanded_Name)
+              and then
+            Nkind_In (E2, N_Selected_Component, N_Expanded_Name)
+      then
+         return Same_Unit (Prefix (E1), Prefix (E2))
+                  and then
+                Same_Unit (Selector_Name (E1), Selector_Name (E2));
+      else
+         return False;
+      end if;
+   end Same_Entity;
+
    ---------------
    -- Same_Unit --
    ---------------
@@ -1360,6 +1501,54 @@
       No_Dependences.Append ((Unit, Warn, Profile));
    end Set_Restriction_No_Dependence;
 
+   --------------------------------------
+   -- Set_Restriction_No_Use_Of_Entity --
+   --------------------------------------
+
+   procedure Set_Restriction_No_Use_Of_Entity
+     (Entity  : Node_Id;
+      Warn    : Boolean;
+      Profile : Profile_Name := No_Profile)
+   is
+      Nam : Node_Id;
+
+   begin
+      --  Loop to check for duplicate entry
+
+      for J in No_Use_Of_Entity.First .. No_Use_Of_Entity.Last loop
+
+         --  Case of entry already in table
+
+         if Same_Entity (Entity, No_Use_Of_Entity.Table (J).Entity) then
+
+            --  Error has precedence over warning
+
+            if not Warn then
+               No_Use_Of_Entity.Table (J).Warn := False;
+            end if;
+
+            return;
+         end if;
+      end loop;
+
+      --  Entry is not currently in table
+
+      No_Use_Of_Entity.Append ((Entity, Warn, Profile));
+
+      --  Now we need to find the direct name and set Boolean2 flag
+
+      if Nkind_In (Entity, N_Identifier, N_Operator_Symbol) then
+         Nam := Entity;
+
+      else
+         pragma Assert (Nkind (Entity) = N_Selected_Component);
+         Nam := Selector_Name (Entity);
+         pragma Assert (Nkind_In (Nam, N_Identifier, N_Operator_Symbol));
+      end if;
+
+      Set_Name_Table_Boolean2 (Chars (Nam), True);
+   end Set_Restriction_No_Use_Of_Entity;
+
    ------------------------------------------------
    -- Set_Restriction_No_Specification_Of_Aspect --
    ------------------------------------------------
Index: restrict.ads
===================================================================
--- restrict.ads        (revision 219235)
+++ restrict.ads        (working copy)
@@ -273,26 +273,31 @@
    --  Wrapper on Check_Restriction with Msg_Issued, with the out-parameter
    --  being ignored here.
 
+   procedure Check_Restriction_No_Dependence (U : Node_Id; Err : Node_Id);
+   --  Called when a dependence on a unit is created (either implicitly, or by
+   --  an explicit WITH clause). U is a node for the unit involved, and Err is
+   --  the node to which an error will be attached if necessary.
+
+   procedure Check_Restriction_No_Specification_Of_Aspect (N : Node_Id);
+   --  N is the node id for an N_Aspect_Specification. An error message
+   --  (warning) will be issued if a restriction (warning) was previous set
+   --  for this aspect using Set_No_Specification_Of_Aspect.
+
    procedure Check_Restriction_No_Use_Of_Attribute (N : Node_Id);
    --  N is the node of an attribute definition clause. An error message
    --  (warning) will be issued if a restriction (warning) was previously set
    --  for this attribute using Set_No_Use_Of_Attribute.
 
+   procedure Check_Restriction_No_Use_Of_Entity (N : Node_Id);
+   --  N is the node id for an entity reference. An error message (warning)
+   --  will be issued if a restriction (warning) was previous set for this
+   --  entity name using Set_No_Use_Of_Entity.
+
    procedure Check_Restriction_No_Use_Of_Pragma (N : Node_Id);
    --  N is the node of a pragma. An error message (warning) will be issued
    --  if a restriction (warning) was previously set for this pragma using
    --  Set_No_Use_Of_Pragma.
 
-   procedure Check_Restriction_No_Dependence (U : Node_Id; Err : Node_Id);
-   --  Called when a dependence on a unit is created (either implicitly, or by
-   --  an explicit WITH clause). U is a node for the unit involved, and Err is
-   --  the node to which an error will be attached if necessary.
-
-   procedure Check_Restriction_No_Specification_Of_Aspect (N : Node_Id);
-   --  N is the node id for an N_Aspect_Specification. An error message
-   --  (warning) will be issued if a restriction (warning) was previous set
-   --  for this aspect using Set_No_Specification_Of_Aspect.
-
    procedure Check_Elaboration_Code_Allowed (N : Node_Id);
    --  Tests to see if elaboration code is allowed by the current restrictions
    --  settings. This function is called by Gigi when it needs to define an
@@ -356,6 +361,11 @@
    --  pragma Restrictions_Warning, or attribute Restriction_Set. Returns
    --  True if N has the proper form for a unit name, False otherwise.
 
+   function OK_No_Use_Of_Entity_Name (N : Node_Id) return Boolean;
+   --  Used in checking No_Use_Of_Entity argument of pragma Restrictions or
+   --  pragma Restrictions_Warning, or attribute Restriction_Set. Returns
+   --  True if N has the proper form for an entity name, False otherwise.
+
    function Is_In_Hidden_Part_In_SPARK (Loc : Source_Ptr) return Boolean;
    --  Determine if given location is covered by a hidden region range in the
    --  SPARK hides table.
@@ -460,6 +470,18 @@
    --  No_Use_Of_Attribute. Caller has verified that this is a valid attribute
    --  designator.
 
+   procedure Set_Restriction_No_Use_Of_Entity
+     (Entity  : Node_Id;
+      Warn    : Boolean;
+      Profile : Profile_Name := No_Profile);
+   --  Sets given No_Use_Of_Entity restriction in table if not there already.
+   --  Warn is True if from Restriction_Warnings, or for Restrictions if the
+   --  flag Treat_Restrictions_As_Warnings is set. False if from Restrictions
+   --  and this flag is not set. Profile is set to a non-default value if the
+   --  No_Dependence restriction comes from a Profile pragma. This procedure
+   --  also takes care of setting the Boolean2 flag of the simple name for
+   --  the entity  (to optimize table searches).
+
    procedure Set_Restriction_No_Use_Of_Pragma
      (N       : Node_Id;
       Warning : Boolean);
Index: sem_ch8.adb
===================================================================
--- sem_ch8.adb (revision 219280)
+++ sem_ch8.adb (working copy)
@@ -5235,7 +5235,7 @@
          Nvis_Messages;
       end if;
 
-      return;
+      goto Done;
 
       --  Processing for a potentially use visible entry found. We must search
       --  the rest of the homonym chain for two reasons. First, if there is a
@@ -5345,7 +5345,7 @@
                end loop;
 
                Nvis_Messages;
-               return;
+               goto Done;
 
             elsif
               Is_Predefined_File_Name (Unit_File_Name (Current_Sem_Unit))
@@ -5372,7 +5372,7 @@
 
             else
                Nvis_Messages;
-               return;
+               goto Done;
             end if;
          end if;
       end;
@@ -5477,9 +5477,8 @@
            and then Expander_Active
            and then Get_PCS_Name /= Name_No_DSA
          then
-            Rewrite (N,
-              New_Occurrence_Of (Equivalent_Type (E), Sloc (N)));
-            return;
+            Rewrite (N, New_Occurrence_Of (Equivalent_Type (E), Sloc (N)));
+            goto Done;
          end if;
 
          --  Set the entity. Note that the reason we call Set_Entity for the
@@ -5634,6 +5633,11 @@
             end if;
          end if;
       end;
+
+   --  Come here with entity set
+
+   <<Done>>
+      Check_Restriction_No_Use_Of_Entity (N);
    end Find_Direct_Name;
 
    ------------------------

Reply via email to