aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaphaël AMIARD <amiard@adacore.com>2024-08-29 12:43:54 +0200
committerMarc Poulhiès <dkm@gcc.gnu.org>2024-10-08 10:37:13 +0200
commitcee753879cdb61c27dd584fcc4932969fb2cd0be (patch)
treec91aeb77022ff05a36aea05eb421b5f8d92c0027
parenta6fc30b29f2e89057538500bb7cf2e233d4e5e41 (diff)
downloadgcc-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.
-rw-r--r--gcc/ada/doc/gnat_rm/gnat_language_extensions.rst52
-rw-r--r--gcc/ada/gnat_rm.texi60
-rw-r--r--gcc/ada/gnat_ugn.texi2
-rw-r--r--gcc/ada/par-ch11.adb3
-rw-r--r--gcc/ada/par-ch5.adb129
-rw-r--r--gcc/ada/par.adb2
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.