From: Raphaël AMIARD <ami...@adacore.com> We want to allow statements lists with declarations *and* an exception handler. What follows from this is that declarations declared in the statement list are *not* visible from the exception handler, and that the following code:
declare A : Integer := 12; begin A : Integer := 15; <stmts> exception when others => ... Roughly expands to: declare A : Integer := 12; begin declare A : Integer := 15; begin <stmts> exception when others => ... As such, in the code above, there is no more error triggered for conflicting declarations of `A`. Move "Local declarations without block" into curated extensions Restrict legal local decls in statement lists Only accept object declarations & renamings, as well as use clauses for gcc/ada/ChangeLog: * par-ch11.adb (P_Sequence_Of_Statements): Remove Handled parameter. Always wrap the statements in a block when there are declarations in it. * par-ch5.adb: Adapt call to P_Sequence_Of_Statements Update outdated comment, remove useless `Style_Checks` pragma. (P_Sequence_Of_Statements): Don't emit an error in core extensions mode. Emit an error when a non valid declaration is parsed in sequence of statements. * par.adb: Adapt P_Sequence_Of_Statements' signature * doc/gnat_rm/gnat_language_extensions.rst: Adapt documentation now. * gnat_rm.texi: Regenerate. * gnat_ugn.texi: Regenerate. Tested on x86_64-pc-linux-gnu, committed on master. --- .../doc/gnat_rm/gnat_language_extensions.rst | 52 ++++++- gcc/ada/gnat_rm.texi | 60 +++++++- gcc/ada/gnat_ugn.texi | 2 +- gcc/ada/par-ch11.adb | 3 +- gcc/ada/par-ch5.adb | 129 +++++++++--------- gcc/ada/par.adb | 2 +- 6 files changed, 171 insertions(+), 77 deletions(-) diff --git a/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst b/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst index b29f23c29ef..af0da983049 100644 --- a/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst +++ b/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst @@ -53,9 +53,12 @@ Features activated via ``-gnatX`` or Local Declarations Without Block -------------------------------- -A basic_declarative_item may appear at the place of any statement. -This avoids the heavy syntax of block_statements just to declare -something locally. +A ``basic_declarative_item`` may appear at the place of any statement. This +avoids the heavy syntax of block_statements just to declare something locally. + +The only valid kind of declarations for now are ``object_declaration``, +``object_renaming_declaration``, ``use_package_clause`` and +``use_type_clause``. For example: @@ -69,6 +72,49 @@ For example: X := X + Squared; end if; +.. attention:: + + Note that local declarations in statement lists have their own scope, which + means that: + + 1. Those declarations are not visible from the potential exception handler: + + .. code-block:: ada + + begin + A : Integer + ... + exception + when others => + Put_Line (A'Image) -- ILLEGAL + end; + + 2. The following is legal + + .. code-block:: ada + + declare + A : Integer := 10; + begin + A : Integer := 12; + end; + + because it is roughly expanded into + + .. code-block:: ada + + declare + A : Integer := 10; + begin + declare + A : Integer := 12; + begin + ... + end; + end; + + And as such the second ``A`` declaration is hiding the first one. + Link to the original RFC: https://github.com/AdaCore/ada-spark-rfcs/blob/master/prototyped/rfc-local-vars-without-block.md diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi index e2686b0a2c7..96f35f7edb8 100644 --- a/gcc/ada/gnat_rm.texi +++ b/gcc/ada/gnat_rm.texi @@ -28961,9 +28961,12 @@ Features activated via @code{-gnatX} or @subsection Local Declarations Without Block -A basic_declarative_item may appear at the place of any statement. -This avoids the heavy syntax of block_statements just to declare -something locally. +A @code{basic_declarative_item} may appear at the place of any statement. This +avoids the heavy syntax of block_statements just to declare something locally. + +The only valid kind of declarations for now are @code{object_declaration}, +@code{object_renaming_declaration}, @code{use_package_clause} and +@code{use_type_clause}. For example: @@ -28977,6 +28980,57 @@ if X > 5 then end if; @end example +@cartouche +@quotation Attention +Note that local declarations in statement lists have their own scope, which +means that: + + +@enumerate + +@item +Those declarations are not visible from the potential exception handler: + +@example +begin + A : Integer + ... +exception + when others => + Put_Line (A'Image) -- ILLEGAL +end; +@end example + +@item +The following is legal + +@example +declare + A : Integer := 10; +begin + A : Integer := 12; +end; +@end example + +because it is roughly expanded into + +@example + declare + A : Integer := 10; + begin + declare + A : Integer := 12; + begin + ... + end; + end; + +And as such the second `@w{`}A`@w{`} declaration is hiding the first one. +@end example +@end enumerate +@end quotation +@end cartouche + Link to the original RFC: @indicateurl{https://github.com/AdaCore/ada-spark-rfcs/blob/master/prototyped/rfc-local-vars-without-block.md} diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index 9ba898435f2..7e27b1c503f 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -29695,8 +29695,8 @@ to permit their use in free software. @printindex ge -@anchor{d1}@w{ } @anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ } +@anchor{d1}@w{ } @c %**end of body @bye diff --git a/gcc/ada/par-ch11.adb b/gcc/ada/par-ch11.adb index 8b51fc7e5b3..d935b58807e 100644 --- a/gcc/ada/par-ch11.adb +++ b/gcc/ada/par-ch11.adb @@ -61,8 +61,7 @@ package body Ch11 is Handled_Stmt_Seq_Node := New_Node (N_Handled_Sequence_Of_Statements, Token_Ptr); Set_Statements - (Handled_Stmt_Seq_Node, - P_Sequence_Of_Statements (SS_Extm_Sreq, Handled => True)); + (Handled_Stmt_Seq_Node, P_Sequence_Of_Statements (SS_Extm_Sreq)); if Token = Tok_Exception then Scan; -- past EXCEPTION diff --git a/gcc/ada/par-ch5.adb b/gcc/ada/par-ch5.adb index a245fa1c08b..557aaf1ff68 100644 --- a/gcc/ada/par-ch5.adb +++ b/gcc/ada/par-ch5.adb @@ -23,10 +23,6 @@ -- -- ------------------------------------------------------------------------------ -pragma Style_Checks (All_Checks); --- Turn off subprogram body ordering check. Subprograms are in order by RM --- section rather than alphabetical. - with Sinfo.CN; use Sinfo.CN; separate (Par) @@ -135,8 +131,7 @@ package body Ch5 is -- parsing a statement, then the scan pointer is advanced past the next -- semicolon and the parse continues. - function P_Sequence_Of_Statements - (SS_Flags : SS_Rec; Handled : Boolean := False) return List_Id + function P_Sequence_Of_Statements (SS_Flags : SS_Rec) return List_Id is Statement_Required : Boolean := SS_Flags.Sreq; -- This flag indicates if a subsequent statement (other than a pragma) @@ -221,32 +216,57 @@ package body Ch5 is -- Start of processing for P_Sequence_Of_Statements begin - -- In Ada 2022, we allow declarative items to be mixed with - -- statements. The loop below alternates between calling - -- P_Declarative_Items to parse zero or more declarative items, - -- and parsing a statement. + -- When extensions are active, we allow declarative items to be mixed + -- with statements. The loop below alternates between calling + -- P_Declarative_Items to parse zero or more declarative items, and + -- parsing a statement. loop Ignore (Tok_Semicolon); declare Num_Statements : constant Nat := List_Length (Statement_List); + Decl : Node_Id; begin P_Declarative_Items (Statement_List, Declare_Expression => False, In_Spec => False, In_Statements => True); -- Use the length of the list to determine whether we parsed - -- any declarative items. If so, it's an error unless language - -- extensions are enabled. + -- any declarative items. if List_Length (Statement_List) > Num_Statements then + Decl := Pick (Statement_List, Num_Statements + 1); + + -- If so, it's an error unless language extensions are enabled. + if All_Errors_Mode or else No (Decl_Loc) then - Decl_Loc := Sloc (Pick (Statement_List, Num_Statements + 1)); + Decl_Loc := Sloc (Decl); Error_Msg_GNAT_Extension - ("declarations mixed with statements", - Sloc (Pick (Statement_List, Num_Statements + 1))); + ("declarations mixed with statements", Sloc (Decl), + Is_Core_Extension => True); + + end if; + + -- Check every declaration added to the list, to see whether + -- it's part of the allowed subset of declarations. Only check + -- that if core extensions are allowed. + + if Core_Extensions_Allowed then + while Present (Decl) loop + if not (Nkind (Decl) in + N_Object_Declaration | N_Object_Renaming_Declaration | + N_Use_Type_Clause | N_Use_Package_Clause | + N_Representation_Clause) + then + Error_Msg + ("Declaration kind not allowed in statements lists", + Sloc (Decl)); + end if; + + Next (Decl); + end loop; end if; end if; end; @@ -937,12 +957,9 @@ package body Ch5 is exit when SS_Flags.Unco; end loop; - -- If there are no declarative items in the list, or if the list is part - -- of a handled sequence of statements, we just return the list. - -- Otherwise, we wrap the list in a block statement, so the declarations - -- will have a proper scope. In the Handled case, it would be wrong to - -- wrap, because we want the code before and after "begin" to be in the - -- same scope. Example: + -- If there are declarative items in the list, we always wrap it in a + -- block, so that anything declared in a statement list is not visible + -- from the exception handlers. Example: -- -- if ... then -- use Some_Package; @@ -958,17 +975,25 @@ package body Ch5 is -- end; -- end if; -- - -- But we don't wrap this: + -- This: -- -- declare -- X : Integer; -- begin -- X : Integer; -- - -- Otherwise, we would fail to detect the error (conflicting X's). - -- Similarly, if a representation clause appears in the statement - -- part, we don't want it to appear more nested than the declarative - -- part -- that would cause an unwanted error. + -- is transformed into this: + -- + -- declare + -- X : Integer; + -- begin + -- declare + -- X : Integer; + -- begin + -- ... + -- + -- We hence don't try to detect this case, even though it can be + -- confusing to users, and might possibly deserve a warning. if Present (Decl_Loc) then -- Forbid labels and declarative items from coexisting. Otherwise, @@ -983,47 +1008,17 @@ package body Ch5 is Error_Msg ("label in same list as declarative item", Label_Loc); end if; - -- Forbid exception handlers and declarative items from - -- coexisting. Example: - -- - -- X : Integer := 123; - -- procedure P is - -- begin - -- X : Integer := 456; - -- exception - -- when Cain => - -- Put(X); - -- end P; - -- - -- It was proposed that in the handler, X should refer to the outer - -- X, but that's just confusing. - - if Token = Tok_Exception then - Error_Msg - ("declarative item in statements conflicts with " & - "exception handler below", - Decl_Loc); - Error_Msg - ("exception handler conflicts with " & - "declarative item in statements above", - Token_Ptr); - end if; - - if Handled then - return Statement_List; - else - declare - Loc : constant Source_Ptr := Sloc (First (Statement_List)); - Block : constant Node_Id := - Make_Block_Statement - (Loc, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements - (Loc, Statements => Statement_List)); - begin - return New_List (Block); - end; - end if; + declare + Loc : constant Source_Ptr := Sloc (First (Statement_List)); + Block : constant Node_Id := + Make_Block_Statement + (Loc, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements + (Loc, Statements => Statement_List)); + begin + return New_List (Block); + end; else return Statement_List; end if; diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb index 9d502b23bc6..0df0c67daeb 100644 --- a/gcc/ada/par.adb +++ b/gcc/ada/par.adb @@ -886,7 +886,7 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is -- Used in loop constructs and quantified expressions. function P_Sequence_Of_Statements - (SS_Flags : SS_Rec; Handled : Boolean := False) return List_Id; + (SS_Flags : SS_Rec) return List_Id; -- SS_Flags indicates the acceptable termination tokens; see body for -- details. Handled is true if we are parsing a handled sequence of -- statements. -- 2.43.0