diff options
author | Raphaël AMIARD <amiard@adacore.com> | 2024-08-29 12:43:54 +0200 |
---|---|---|
committer | Marc Poulhiès <dkm@gcc.gnu.org> | 2024-10-08 10:37:13 +0200 |
commit | cee753879cdb61c27dd584fcc4932969fb2cd0be (patch) | |
tree | c91aeb77022ff05a36aea05eb421b5f8d92c0027 /gcc | |
parent | a6fc30b29f2e89057538500bb7cf2e233d4e5e41 (diff) | |
download | gcc-cee753879cdb61c27dd584fcc4932969fb2cd0be.zip gcc-cee753879cdb61c27dd584fcc4932969fb2cd0be.tar.gz gcc-cee753879cdb61c27dd584fcc4932969fb2cd0be.tar.bz2 |
ada: Use semantics from the RFC for declarative items mixed with statements
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ada/doc/gnat_rm/gnat_language_extensions.rst | 52 | ||||
-rw-r--r-- | gcc/ada/gnat_rm.texi | 60 | ||||
-rw-r--r-- | gcc/ada/gnat_ugn.texi | 2 | ||||
-rw-r--r-- | gcc/ada/par-ch11.adb | 3 | ||||
-rw-r--r-- | gcc/ada/par-ch5.adb | 129 | ||||
-rw-r--r-- | 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 b29f23c..af0da98 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 e2686b0..96f35f7 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 9ba8984..7e27b1c 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 8b51fc7..d935b58 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 a245fa1..557aaf1 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 9d502b2..0df0c67 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. |