diff mbox

[Ada] Missing detection of illegally placed pragma Assert

Message ID 20170123120806.GA90963@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Jan. 23, 2017, 12:08 p.m. UTC
This patch modifies the parsing of protected and task definitions to detect
illegal placement of pragmas Assert and Debug within the protected or task
item lists.

------------
-- Source --
------------

--  synch_pragmas.ads

package Synch_Pragmas is
   protected PO is
      pragma Assert (PO'Size > 0);                                   --  Error
      procedure P;
      pragma Assert (PO'Size > 0);                                   --  Error
   private
      pragma Assert (PO'Size > 0);                                   --  Error
      function F return Boolean;
      pragma Assert (PO'Size > 0);                                   --  Error
      Comp : Integer;
      pragma Assert (PO'Size > 0);                                   --  Error
   end PO;

   protected type PT is
      pragma Assert (PT'Size > 0);                                   --  Error
      procedure P;
      pragma Assert (PT'Size > 0);                                   --  Error
   private
      pragma Assert (PT'Size > 0);                                   --  Error
      function F return Boolean;
      pragma Assert (PT'Size > 0);                                   --  Error
      Comp : Integer;
      pragma Assert (PT'Size > 0);                                   --  Error
   end PT;

   task TO is
      pragma Assert (TO'Size > 0);                                   --  Error
      entry E;
      pragma Assert (TO'Size > 0);                                   --  Error
   private
      pragma Assert (TO'Size > 0);                                   --  Error
      entry E2;
      pragma Assert (TO'Size > 0);                                   --  Error
   end TO;

   task type TT is
      pragma Assert (TT'Size > 0);                                   --  Error
      entry E;
      pragma Assert (TT'Size > 0);                                   --  Error
   private
      pragma Assert (TT'Size > 0);                                   --  Error
      entry E2;
      pragma Assert (TT'Size > 0);                                   --  Error
   end TT;
end Synch_Pragmas;

----------------------------
-- Compilation and output --
----------------------------

$ gcc -c synch_pragmas.ads
synch_pragmas.ads:3:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:5:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:7:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:9:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:11:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:15:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:17:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:19:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:21:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:23:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:27:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:29:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:31:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:33:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:37:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:39:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:41:07: pragma "Assert" must be in declaration/statement
  context
synch_pragmas.ads:43:07: pragma "Assert" must be in declaration/statement
  context

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

2017-01-23  Hristian Kirtchev  <kirtchev@adacore.com>

	* par-ch9.adb (P_Protected_Definition): Parse
	any optional and potentially illegal pragmas which appear in
	a protected operation declaration list.
	(P_Task_Items): Parse
	any optional and potentially illegal pragmas which appear in a
	task item list.
diff mbox

Patch

Index: par-ch9.adb
===================================================================
--- par-ch9.adb	(revision 244773)
+++ par-ch9.adb	(working copy)
@@ -338,10 +338,10 @@ 
          Decl_Sloc := Token_Ptr;
 
          if Token = Tok_Pragma then
-            Append (P_Pragma, Items);
+            P_Pragmas_Opt (Items);
 
-         --  Ada 2005 (AI-397): Reserved words NOT and OVERRIDING
-         --  may begin an entry declaration.
+         --  Ada 2005 (AI-397): Reserved words NOT and OVERRIDING may begin an
+         --  entry declaration.
 
          elsif Token = Tok_Entry
            or else Token = Tok_Not
@@ -350,8 +350,9 @@ 
             Append (P_Entry_Declaration, Items);
 
          elsif Token = Tok_For then
-            --  Representation clause in task declaration. The only rep
-            --  clause which is legal in a protected is an address clause,
+
+            --  Representation clause in task declaration. The only rep clause
+            --  which is legal in a protected declaration is an address clause,
             --  so that is what we try to scan out.
 
             Item_Node := P_Representation_Clause;
@@ -617,8 +618,10 @@ 
    --  Error recovery: cannot raise Error_Resync
 
    function P_Protected_Definition return Node_Id is
-      Def_Node  : Node_Id;
-      Item_Node : Node_Id;
+      Def_Node   : Node_Id;
+      Item_Node  : Node_Id;
+      Priv_Decls : List_Id;
+      Vis_Decls  : List_Id;
 
    begin
       Def_Node := New_Node (N_Protected_Definition, Token_Ptr);
@@ -631,33 +634,63 @@ 
 
       --  Loop to scan visible declarations (protected operation declarations)
 
-      Set_Visible_Declarations (Def_Node, New_List);
+      Vis_Decls := New_List;
+      Set_Visible_Declarations (Def_Node, Vis_Decls);
 
+      --  Flag and discard all pragmas which cannot appear in the protected
+      --  definition. Note that certain pragmas are still allowed as long as
+      --  they apply to entries, entry families, or protected subprograms.
+
+      P_Pragmas_Opt (Vis_Decls);
+
       loop
          Item_Node := P_Protected_Operation_Declaration_Opt;
+
+         if Present (Item_Node) then
+            Append (Item_Node, Vis_Decls);
+         end if;
+
+         P_Pragmas_Opt (Vis_Decls);
+
          exit when No (Item_Node);
-         Append (Item_Node, Visible_Declarations (Def_Node));
       end loop;
 
       --  Deal with PRIVATE part (including graceful handling of multiple
       --  PRIVATE parts).
 
       Private_Loop : while Token = Tok_Private loop
-         if No (Private_Declarations (Def_Node)) then
-            Set_Private_Declarations (Def_Node, New_List);
+         Priv_Decls := Private_Declarations (Def_Node);
+
+         if Present (Priv_Decls) then
+            Error_Msg_SC ("duplicate private part");
          else
-            Error_Msg_SC ("duplicate private part");
+            Priv_Decls := New_List;
+            Set_Private_Declarations (Def_Node, Priv_Decls);
          end if;
 
          Scan; -- past PRIVATE
 
+         --  Flag and discard all pragmas which cannot appear in the protected
+         --  definition. Note that certain pragmas are still allowed as long as
+         --  they apply to entries, entry families, or protected subprograms.
+
+         P_Pragmas_Opt (Priv_Decls);
+
          Declaration_Loop : loop
             if Token = Tok_Identifier then
-               P_Component_Items (Private_Declarations (Def_Node));
+               P_Component_Items (Priv_Decls);
+               P_Pragmas_Opt (Priv_Decls);
+
             else
                Item_Node := P_Protected_Operation_Declaration_Opt;
+
+               if Present (Item_Node) then
+                  Append (Item_Node, Priv_Decls);
+               end if;
+
+               P_Pragmas_Opt (Priv_Decls);
+
                exit Declaration_Loop when No (Item_Node);
-               Append (Item_Node, Private_Declarations (Def_Node));
             end if;
          end loop Declaration_Loop;
       end loop Private_Loop;