contracts.adb (Analyze_Object_Contract): Set and restore the SPARK_Mode for both...
authorHristian Kirtchev <kirtchev@adacore.com>
Mon, 26 Oct 2015 15:40:10 +0000 (15:40 +0000)
committerArnaud Charlet <charlet@gcc.gnu.org>
Mon, 26 Oct 2015 15:40:10 +0000 (16:40 +0100)
2015-10-26  Hristian Kirtchev  <kirtchev@adacore.com>

* contracts.adb (Analyze_Object_Contract): Set and restore
the SPARK_Mode for both constants and objects. Factor out the
semantic checks concerning Ghost objects.
* freeze.adb (Freeze_Array_Type): A Ghost array type cannot have a
concurrent component type.
(Freeze_Entity): A Ghost type cannot also be concurrent.
(Freeze_Record_Type): A Ghost record type cannot have a concurrent
component.
* sem_prag.adb (Analyze_Abstract_State): A Ghost abstract
state cannot also be synchronized.
(Check_Ghost_Synchronous): New routine.
* sem_util.adb (Yields_Synchronized_Object): Correct the case
of record components to account for the case where the type has
no component list.

2015-10-26  Hristian Kirtchev  <kirtchev@adacore.com>

* expander.adb (Expand): Expand a single protected declaration.
* exp_ch9.ads, exp_ch9.adb (Expand_N_Single_Protected_Declaration): New
routine.

2015-10-26  Hristian Kirtchev  <kirtchev@adacore.com>

* sem_res.adb (Is_OK_Volatile_Context): A volatile object may appear
in an object declaration as long as it denotes the name.

From-SVN: r229376

gcc/ada/ChangeLog
gcc/ada/contracts.adb
gcc/ada/exp_ch9.adb
gcc/ada/exp_ch9.ads
gcc/ada/expander.adb
gcc/ada/freeze.adb
gcc/ada/sem_prag.adb
gcc/ada/sem_res.adb
gcc/ada/sem_util.adb

index 86893ba18a1d9124fe30ec59afeea8679b83b501..7cafbd88c89346a73abc1c33a0cc229aa61b1e2f 100644 (file)
@@ -1,3 +1,31 @@
+2015-10-26  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * contracts.adb (Analyze_Object_Contract): Set and restore
+       the SPARK_Mode for both constants and objects. Factor out the
+       semantic checks concerning Ghost objects.
+       * freeze.adb (Freeze_Array_Type): A Ghost array type cannot have a
+       concurrent component type.
+       (Freeze_Entity): A Ghost type cannot also be concurrent.
+       (Freeze_Record_Type): A Ghost record type cannot have a concurrent
+       component.
+       * sem_prag.adb (Analyze_Abstract_State): A Ghost abstract
+       state cannot also be synchronized.
+       (Check_Ghost_Synchronous): New routine.
+       * sem_util.adb (Yields_Synchronized_Object): Correct the case
+       of record components to account for the case where the type has
+       no component list.
+
+2015-10-26  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * expander.adb (Expand): Expand a single protected declaration.
+       * exp_ch9.ads, exp_ch9.adb (Expand_N_Single_Protected_Declaration): New
+       routine.
+
+2015-10-26  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * sem_res.adb (Is_OK_Volatile_Context): A volatile object may appear
+       in an object declaration as long as it denotes the name.
+
 2015-10-26  Hristian Kirtchev  <kirtchev@adacore.com>
 
        * sem_ch9.adb (Analyze_Single_Protected_Declaration): The anonymous
index 30318dc63f67d3973c2ed7c6765fa1cc32d6d3d2..2ab91f98fec04a5b85e0b8a5954ec0d1685b00ed 100644 (file)
@@ -648,10 +648,34 @@ package body Contracts is
          end if;
       end if;
 
+      --  The anonymous object created for a single concurrent type inherits
+      --  the SPARK_Mode from the type. Due to the timing of contract analysis,
+      --  delayed pragmas may be subject to the wrong SPARK_Mode, usually that
+      --  of the enclosing context. To remedy this, restore the original mode
+      --  of the related anonymous object.
+
+      if Is_Single_Concurrent_Object (Obj_Id)
+        and then Present (SPARK_Pragma (Obj_Id))
+      then
+         Restore_Mode := True;
+         Save_SPARK_Mode_And_Set (Obj_Id, Mode);
+      end if;
+
       --  Constant-related checks
 
       if Ekind (Obj_Id) = E_Constant then
 
+         --  Analyze indicator Part_Of
+
+         Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
+
+         --  Check whether the lack of indicator Part_Of agrees with the
+         --  placement of the constant with respect to the state space.
+
+         if No (Prag) then
+            Check_Missing_Part_Of (Obj_Id);
+         end if;
+
          --  A constant cannot be effectively volatile (SPARK RM 7.1.3(4)).
          --  This check is relevant only when SPARK_Mode is on, as it is not
          --  a standard Ada legality rule. Internally-generated constants that
@@ -666,32 +690,10 @@ package body Contracts is
             Error_Msg_N ("constant cannot be volatile", Obj_Id);
          end if;
 
-         Prag := Get_Pragma (Obj_Id, Pragma_Part_Of);
-
-         --  Check whether the lack of indicator Part_Of agrees with the
-         --  placement of the constant with respect to the state space.
-
-         if No (Prag) then
-            Check_Missing_Part_Of (Obj_Id);
-         end if;
-
       --  Variable-related checks
 
       else pragma Assert (Ekind (Obj_Id) = E_Variable);
 
-         --  The anonymous object created for a single concurrent type inherits
-         --  the SPARK_Mode from the type. Due to the timing of contract
-         --  analysis, delayed pragmas may be subject to the wrong SPARK_Mode,
-         --  usually that of the enclosing context. To remedy this, restore the
-         --  original SPARK_Mode of the related variable.
-
-         if Is_Single_Concurrent_Object (Obj_Id)
-           and then Present (SPARK_Pragma (Obj_Id))
-         then
-            Restore_Mode := True;
-            Save_SPARK_Mode_And_Set (Obj_Id, Mode);
-         end if;
-
          --  Analyze all external properties
 
          Prag := Get_Pragma (Obj_Id, Pragma_Async_Readers);
@@ -834,44 +836,42 @@ package body Contracts is
                   & "protected type %"), Obj_Id);
             end if;
          end if;
+      end if;
 
-         if Is_Ghost_Entity (Obj_Id) then
+      --  Common checks
 
-            --  A Ghost object cannot be effectively volatile (SPARK RM 6.9(8))
+      if Comes_From_Source (Obj_Id) and then Is_Ghost_Entity (Obj_Id) then
 
-            if Is_Effectively_Volatile (Obj_Id) then
-               Error_Msg_N ("ghost variable & cannot be volatile", Obj_Id);
+         --  A Ghost object cannot be of a type that yields a synchronized
+         --  object (SPARK RM 6.9(19)).
 
-            --  A Ghost object cannot be imported or exported (SPARK RM 6.9(8))
+         if Yields_Synchronized_Object (Obj_Typ) then
+            Error_Msg_N ("ghost object & cannot be synchronized", Obj_Id);
 
-            elsif Is_Imported (Obj_Id) then
-               Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
+         --  A Ghost object cannot be effectively volatile (SPARK RM 6.9(8) and
+         --  SPARK RM 6.9(19)).
 
-            elsif Is_Exported (Obj_Id) then
-               Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
-            end if;
-         end if;
+         elsif Is_Effectively_Volatile (Obj_Id) then
+            Error_Msg_N ("ghost object & cannot be volatile", Obj_Id);
 
-         --  Restore the SPARK_Mode of the enclosing context after all delayed
-         --  pragmas have been analyzed.
+         --  A Ghost object cannot be imported or exported (SPARK RM 6.9(8)).
+         --  One exception to this is the object that represents the dispatch
+         --  table of a Ghost tagged type, as the symbol needs to be exported.
 
-         if Restore_Mode then
-            Restore_SPARK_Mode (Mode);
-         end if;
-      end if;
-
-      --  A ghost object cannot be imported or exported (SPARK RM 6.9(8)). One
-      --  exception to this is the object that represents the dispatch table of
-      --  a Ghost tagged type, as the symbol needs to be exported.
-
-      if Comes_From_Source (Obj_Id) and then Is_Ghost_Entity (Obj_Id) then
-         if Is_Exported (Obj_Id) then
+         elsif Is_Exported (Obj_Id) then
             Error_Msg_N ("ghost object & cannot be exported", Obj_Id);
 
          elsif Is_Imported (Obj_Id) then
             Error_Msg_N ("ghost object & cannot be imported", Obj_Id);
          end if;
       end if;
+
+      --  Restore the SPARK_Mode of the enclosing context after all delayed
+      --  pragmas have been analyzed.
+
+      if Restore_Mode then
+         Restore_SPARK_Mode (Mode);
+      end if;
    end Analyze_Object_Contract;
 
    -----------------------------------
index 00b3b60c55a5957f0c7f18e4ed77408888de6be0..4887c707f69f58c80e1a38f408a5fb1dedb62ae9 100644 (file)
@@ -11388,14 +11388,28 @@ package body Exp_Ch9 is
       end loop;
    end Expand_N_Selective_Accept;
 
+   -------------------------------------------
+   -- Expand_N_Single_Protected_Declaration --
+   -------------------------------------------
+
+   --  A single protected declaration should never be present after semantic
+   --  analysis because it is transformed into a protected type declaration
+   --  and an accompanying anonymous object. This routine ensures that the
+   --  transformation takes place.
+
+   procedure Expand_N_Single_Protected_Declaration (N : Node_Id) is
+   begin
+      raise Program_Error;
+   end Expand_N_Single_Protected_Declaration;
+
    --------------------------------------
    -- Expand_N_Single_Task_Declaration --
    --------------------------------------
 
-   --  Single task declarations should never be present after semantic
-   --  analysis, since we expect them to be replaced by a declaration of an
-   --  anonymous task type, followed by a declaration of the task object. We
-   --  include this routine to make sure that is happening.
+   --  A single task declaration should never be present after semantic
+   --  analysis because it is transformed into a task type declaration and
+   --  an accompanying anonymous object. This routine ensures that the
+   --  transformation takes place.
 
    procedure Expand_N_Single_Task_Declaration (N : Node_Id) is
    begin
index d9fa7d6d7fbf59f39ff8e9f2af62d928a1233905..d49201bfe0dbc221085131f61c057018629c4fb8 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---          Copyright (C) 1992-2014, Free Software Foundation, Inc.         --
+--          Copyright (C) 1992-2015, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -266,12 +266,13 @@ package Exp_Ch9 is
    --  allows these two nodes to be found from the type, without benefit of
    --  further attributes, using Corresponding_Record.
 
-   procedure Expand_N_Requeue_Statement          (N : Node_Id);
-   procedure Expand_N_Selective_Accept           (N : Node_Id);
-   procedure Expand_N_Single_Task_Declaration    (N : Node_Id);
-   procedure Expand_N_Task_Body                  (N : Node_Id);
-   procedure Expand_N_Task_Type_Declaration      (N : Node_Id);
-   procedure Expand_N_Timed_Entry_Call           (N : Node_Id);
+   procedure Expand_N_Requeue_Statement            (N : Node_Id);
+   procedure Expand_N_Selective_Accept             (N : Node_Id);
+   procedure Expand_N_Single_Protected_Declaration (N : Node_Id);
+   procedure Expand_N_Single_Task_Declaration      (N : Node_Id);
+   procedure Expand_N_Task_Body                    (N : Node_Id);
+   procedure Expand_N_Task_Type_Declaration        (N : Node_Id);
+   procedure Expand_N_Timed_Entry_Call             (N : Node_Id);
 
    procedure Expand_Protected_Body_Declarations
      (N       : Node_Id;
index 2d9b6d964acfa7bd3bc59586e7402a486f85b247..4aa20d6f41b6e810d9e7d7b83a6abca5b5538a92 100644 (file)
@@ -432,6 +432,9 @@ package body Expander is
                when N_Selective_Accept =>
                   Expand_N_Selective_Accept (N);
 
+               when N_Single_Protected_Declaration =>
+                  Expand_N_Single_Protected_Declaration (N);
+
                when N_Single_Task_Declaration =>
                   Expand_N_Single_Task_Declaration (N);
 
@@ -471,7 +474,7 @@ package body Expander is
                when N_Variant_Part =>
                   Expand_N_Variant_Part (N);
 
-                  --  For all other node kinds, no expansion activity required
+               --  For all other node kinds, no expansion activity required
 
                when others =>
                   null;
index e09fbd20239ceea3393068dbb3321fdf253d9d2d..59a49ced0ae9509bc29811d310a523f91a7dd53d 100644 (file)
@@ -2806,6 +2806,15 @@ package body Freeze is
          then
             Set_Alignment (Arr, Alignment (Component_Type (Arr)));
          end if;
+
+         --  A Ghost type cannot have a component of protected or task type
+         --  (SPARK RM 6.9(19)).
+
+         if Is_Ghost_Entity (Arr) and then Is_Concurrent_Type (Ctyp) then
+            Error_Msg_N
+              ("ghost array type & cannot have concurrent component type",
+               Arr);
+         end if;
       end Freeze_Array_Type;
 
       -------------------------------
@@ -4341,6 +4350,25 @@ package body Freeze is
                   Next_Component (Comp);
                end loop;
             end if;
+
+            --  A Ghost type cannot have a component of protected or task type
+            --  (SPARK RM 6.9(19)).
+
+            if Is_Ghost_Entity (Rec) then
+               Comp := First_Component (Rec);
+               while Present (Comp) loop
+                  if Comes_From_Source (Comp)
+                    and then Is_Concurrent_Type (Etype (Comp))
+                  then
+                     Error_Msg_Name_1 := Chars (Rec);
+                     Error_Msg_N
+                       ("component & of ghost type % cannot be concurrent",
+                        Comp);
+                  end if;
+
+                  Next_Component (Comp);
+               end loop;
+            end if;
          end if;
 
          --  Make sure that if we have an iterator aspect, then we have
@@ -5091,12 +5119,19 @@ package body Freeze is
             end if;
          end;
 
-         --  A Ghost type cannot be effectively volatile (SPARK RM 6.9(8))
+         if Is_Ghost_Entity (E) then
 
-         if Is_Ghost_Entity (E)
-           and then Is_Effectively_Volatile (E)
-         then
-            Error_Msg_N ("ghost type & cannot be volatile", E);
+            --  A Ghost type cannot be concurrent (SPARK RM 6.9(19)). Verify
+            --  this legality rule first to five a finer-grained diagnostic.
+
+            if Is_Concurrent_Type (E) then
+               Error_Msg_N ("ghost type & cannot be concurrent", E);
+
+            --  A Ghost type cannot be effectively volatile (SPARK RM 6.9(8))
+
+            elsif Is_Effectively_Volatile (E) then
+               Error_Msg_N ("ghost type & cannot be volatile", E);
+            end if;
          end if;
 
          --  Deal with special cases of freezing for subtype
index a8998cc78cf32c478cca0e4c7e7472b72544b15f..17544f0cb810edc21e9a4c122e3338e7bb5b96b4 100644 (file)
@@ -10068,6 +10068,11 @@ package body Sem_Prag is
                --  Opt is not a duplicate property and sets the flag Status.
                --  (SPARK RM 7.1.4(2))
 
+               procedure Check_Ghost_Synchronous;
+               --  Ensure that the abstract state is not subject to both Ghost
+               --  and Synchronous simple options. Emit an error if this is the
+               --  case.
+
                procedure Create_Abstract_State
                  (Nam     : Name_Id;
                   Decl    : Node_Id;
@@ -10320,6 +10325,20 @@ package body Sem_Prag is
                   Status := True;
                end Check_Duplicate_Property;
 
+               -----------------------------
+               -- Check_Ghost_Synchronous --
+               -----------------------------
+
+               procedure Check_Ghost_Synchronous is
+               begin
+                  --  A synchronized abstract state cannot be Ghost and vice
+                  --  versa (SPARK RM 6.9(19)).
+
+                  if Ghost_Seen and Synchronous_Seen then
+                     SPARK_Msg_N ("synchronized state cannot be ghost", State);
+                  end if;
+               end Check_Ghost_Synchronous;
+
                ---------------------------
                -- Create_Abstract_State --
                ---------------------------
@@ -10464,6 +10483,7 @@ package body Sem_Prag is
 
                         elsif Chars (Opt) = Name_Ghost then
                            Check_Duplicate_Option (Opt, Ghost_Seen);
+                           Check_Ghost_Synchronous;
 
                            if Present (State_Id) then
                               Set_Is_Ghost_Entity (State_Id);
@@ -10473,6 +10493,7 @@ package body Sem_Prag is
 
                         elsif Chars (Opt) = Name_Synchronous then
                            Check_Duplicate_Option (Opt, Synchronous_Seen);
+                           Check_Ghost_Synchronous;
 
                         --  Option Part_Of without an encapsulating state is
                         --  illegal (SPARK RM 7.1.4(9)).
index d2963f73e7cf6edc223b1dc25e2f9ebffc8cee8e..d3312e2d84c1c89e840790ae1ed9090e37e78f3d 100644 (file)
@@ -6993,6 +6993,13 @@ package body Sem_Res is
                return True;
             end if;
 
+         --  The volatile object acts as the name of a renaming declaration
+
+         elsif Nkind (Context) = N_Object_Renaming_Declaration
+           and then Name (Context) = Obj_Ref
+         then
+            return True;
+
          --  The volatile object appears as an actual parameter in a call to an
          --  instance of Unchecked_Conversion whose result is renamed.
 
index 8e33f4c403630cd8b2a4a3e1bd4460c0a289e741..d8567c59e7ff069490464ba50c48bdcd73071965 100644 (file)
@@ -20121,7 +20121,8 @@ package body Sem_Util is
    --------------------------------
 
    function Yields_Synchronized_Object (Typ : Entity_Id) return Boolean is
-      Id : Entity_Id;
+      Has_Sync_Comp : Boolean := False;
+      Id            : Entity_Id;
 
    begin
       --  An array type yields a synchronized object if its component type
@@ -20154,10 +20155,15 @@ package body Sem_Util is
          Id := First_Entity (Typ);
          while Present (Id) loop
             if Comes_From_Source (Id) then
-               if Ekind (Id) = E_Component
-                 and then not Yields_Synchronized_Object (Etype (Id))
-               then
-                  return False;
+               if Ekind (Id) = E_Component then
+                  if Yields_Synchronized_Object (Etype (Id)) then
+                     Has_Sync_Comp := True;
+
+                  --  The component does not yield a synchronized object
+
+                  else
+                     return False;
+                  end if;
 
                elsif Ekind (Id) = E_Discriminant
                  and then Present (Expression (Parent (Id)))
@@ -20181,7 +20187,7 @@ package body Sem_Util is
          --  If we get here, then all discriminants lack default values and all
          --  components are of a type that yields a synchronized object.
 
-         return True;
+         return Has_Sync_Comp;
 
       --  A synchronized interface type yields a synchronized object by default