8sa1-gcc/gcc/ada/par-ch6.adb
Bob Duff 88b32fc3a7 g-awk.adb (Default_Session, [...]): Compile this file in Ada 95 mode, because it violates the new rules for AI-318.
2006-10-31  Bob Duff  <duff@adacore.com>
	    Robert Dewar  <dewar@adacore.com>
	    Ed Schonberg  <schonberg@adacore.com>

	* g-awk.adb (Default_Session, Current_Session): Compile this file in
	Ada 95 mode, because it violates the new rules for AI-318.

	* g-awk.ads: Use overloaded subprograms in every case where we used to
	have a default of Current_Session. This makes the code closer to be
	correct for both Ada 95 and 2005.

	* g-moreex.adb (Occurrence): Turn off warnings for illegal-in-Ada-2005
	code, relying on the fact that the compiler generates a warning
	instead of an error in -gnatg mode.

	* lib-xref.ads (Xref_Entity_Letters): Add entry for new
	E_Return_Statement entity kind.
	Add an entry for E_Incomplete_Subtype in Xref_Entity_Letters.

	* par.adb (P_Interface_Type_Definition): Addition of one formal to
	report an error if the reserved word abstract has been previously found.
	(SS_End_Type): Add E_Return for new extended_return_statement syntax.
        
        * par-ch4.adb (P_Aggregate_Or_Paren_Expr): Improve message for
	parenthesized range attribute usage
	(P_Expression_No_Right_Paren): Add missing comment about error recovery.

	* par-ch6.adb (P_Return_Object_Declaration): AI-318: Allow "constant"
	in the syntax for extended_return_statement. This is not in the latest
	RM, but the ARG is expected to issue an AI allowing this.
	(P_Return_Subtype_Indication,P_Return_Subtype_Indication): Remove
	N_Return_Object_Declaration. We now use N_Object_Declaration instead.
	(P_Return_Object_Declaration, P_Return_Subtype_Indication,
	P_Return_Statement): Parse the new syntax for extended_return_statement.

	* par-endh.adb (Check_End, Output_End_Deleted, Output_End_Expected,
	Output_End_Missing): Add error-recovery code for the new
	extended_return_statement syntax; that is, the new E_Return entry on
	the scope stack.

	* s-auxdec-vms_64.ads, s-auxdec.ads (AST_Handler): Change type from
	limited to nonlimited, because otherwise we violate the new Ada 2005
	rules about returning limited types in function Create_AST_Handler in
	s-asthan.adb.

	* sem.adb (Analyze): Add cases for new node kinds
	N_Extended_Return_Statement and N_Return_Object_Declaration.

	* sem_aggr.adb (Aggregate_Constraint_Checks): Verify that component
	type is in the same category as type of context before applying check,
	to prevent anomalies in instantiations.
	(Resolve_Aggregate): Remove test for limited components in aggregates.
	It's unnecessary in Ada 95, because if it has limited components, then
	it must be limited. It's wrong in Ada 2005, because limited aggregates
	are now allowed.
	(Resolve_Record_Aggregate): Move check for limited types later, because
	OK_For_Limited_Init requires its argument to have been resolved.
	(Get_Value): When copying the component default expression for a
	defaulted association in an aggregate, use the sloc of the aggregate
	and not that of the original expression, to prevent spurious
	elaboration errors, when the expression includes function calls.
	(Check_Non_Limited_Type): Correct code for AI-287, extension aggregates
	were missing. We also didn't handle qualified expressions. Now also
	allow function calls. Use new common routine OK_For_Limited_Init.
	(Resolve_Extension_Aggregate): Minor fix to bad error message (started
	with space can upper case letter).

        * sem_ch3.ads, sem_ch3.adb (Create_Constrained_Components): Set
	Has_Static_Discriminants flag
        (Record_Type_Declaration): Diagnose an attempt to declare an interface
        type with discriminants.
        (Process_Range_Expr_In_Decl): Do validity checks on range
	(Build_Discriminant_Constraints): Use updated form of
	Denotes_Discriminant.
	(Process_Subtype): If the subtype is a private subtype whose full view
	is a concurrent subtype, introduce an itype reference to prevent scope
	anomalies in gigi.
	(Build_Derived_Record_Type, Collect_Interface_Primitives,
	Record_Type_Declaration):  The functionality of the subprograms
	Collect_Abstract_Interfaces and Collect_All_Abstract_Interfaces
	is now performed by a single routine.
	(Build_Derived_Record_Type): If the type definition includes an explicit
	indication of limitedness, then the type must be marked as limited here
	to ensure that any access discriminants will not be treated as having
	a local anonymous access type.
	(Check_Abstract_Overriding): Issue a detailed error message when an
	abstract subprogram was not overridden due to incorrect mode of its
	first parameter.
	(Analyze_Private_Extension_Declaration): Add support for the analysis of
	synchronized private extension declarations. Verify that the ancestor is
	a limited or synchronized interface or in the generic case, the ancestor
	is a tagged limited type or synchronized interface and all progenitors
	are either limited or synchronized interfaces.
	Derived_Type_Declaration): Check for presence of private extension when
	dealing with synchronized formal derived types.
	Process_Full_View): Enchance the check done on the usage of "limited" by
	testing whether the private view is synchronized.
	Verify that a synchronized private view is completed by a protected or
	task type.
	(OK_For_Limited_Init_In_05): New function.
	(Analyze_Object_Declaration): Move check for limited types later,
	because OK_For_Limited_Init requires its argument to have been resolved.
	Add -gnatd.l --Use Ada 95 semantics for limited function returns,
	in order to alleviate the upward compatibility introduced by AI-318.
	(Constrain_Corresponding_Record): If the constraint is for a component
	subtype, mark the itype as frozen, to avoid out-of-scope references to
	discriminants in the back-end.
	(Collect_Implemented_Interfaces): Protect the recursive algorithm of
	this subprogram against wrong sources.
	(Get_Discr_Value, Is_Discriminant): Handle properly references to a
	discriminant of limited type completed with a protected type, when the
	discriminant is used to constrain a private component of the type, and
	expansion is disabled.
	(Find_Type_Of_Object): Do not treat a return subtype that is an
	anonymous subtype as a local_anonymous_type, because its accessibility
	level is the return type of the enclosing function.
	(Check_Initialization): In -gnatg mode, turn the error "cannot
	initialize entities of limited type" into a warning.
	(OK_For_Limited_Init): Return true for generated nodes, since it
	sometimes violates the legality rules.
	(Make_Incomplete_Declaration): If the type for which an incomplete
	declaration is created happens to be the currently visible entity,
	preserve the homonym chain when removing it from visibility.
	(Check_Conventions): Add support for Ada 2005 (AI-430): Conventions of
	inherited subprograms.
	(Access_Definition): If this is an access to function that is the return
	type of an access_to_function definition, context is a type declaration
	and the scope of the anonymous type is the current one.
	(Analyze_Subtype_Declaration): Add the defining identifier of a regular
	incomplete subtype to the set of private dependents of the original
	incomplete type.
	(Constrain_Discriminated_Type): Emit an error message whenever an
	incomplete subtype is being constrained.
	(Process_Incomplete_Dependents): Transform an incomplete subtype into a
	corresponding subtype of the full view of the original incomplete type.
	(Check_Incomplete): Properly detect invalid usage of incomplete types
	and subtypes.

From-SVN: r118273
2006-10-31 18:58:48 +01:00

1501 lines
49 KiB
Ada

------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- P A R . C H 6 --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2006, 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- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
-- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
-- Boston, MA 02110-1301, USA. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
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)
package body Ch6 is
-- Local subprograms, used only in this chapter
function P_Defining_Designator return Node_Id;
function P_Defining_Operator_Symbol return Node_Id;
function P_Return_Object_Declaration return Node_Id;
procedure P_Return_Subtype_Indication (Decl_Node : Node_Id);
-- Decl_Node is a N_Object_Declaration.
-- Set the Null_Exclusion_Present and Object_Definition fields of
-- Decl_Node.
procedure Check_Junk_Semicolon_Before_Return;
-- Check for common error of junk semicolon before RETURN keyword of
-- function specification. If present, skip over it with appropriate
-- error message, leaving Scan_Ptr pointing to the RETURN after. This
-- routine also deals with a possibly misspelled version of Return.
----------------------------------------
-- Check_Junk_Semicolon_Before_Return --
----------------------------------------
procedure Check_Junk_Semicolon_Before_Return is
Scan_State : Saved_Scan_State;
begin
if Token = Tok_Semicolon then
Save_Scan_State (Scan_State);
Scan; -- past the semicolon
if Token = Tok_Return then
Restore_Scan_State (Scan_State);
Error_Msg_SC ("unexpected semicolon ignored");
Scan; -- rescan past junk semicolon
else
Restore_Scan_State (Scan_State);
end if;
elsif Bad_Spelling_Of (Tok_Return) then
null;
end if;
end Check_Junk_Semicolon_Before_Return;
-----------------------------------------------------
-- 6.1 Subprogram (Also 6.3, 8.5.4, 10.1.3, 12.3) --
-----------------------------------------------------
-- This routine scans out a subprogram declaration, subprogram body,
-- subprogram renaming declaration or subprogram generic instantiation.
-- SUBPROGRAM_DECLARATION ::= SUBPROGRAM_SPECIFICATION;
-- ABSTRACT_SUBPROGRAM_DECLARATION ::=
-- SUBPROGRAM_SPECIFICATION is abstract;
-- SUBPROGRAM_SPECIFICATION ::=
-- procedure DEFINING_PROGRAM_UNIT_NAME PARAMETER_PROFILE
-- | function DEFINING_DESIGNATOR PARAMETER_AND_RESULT_PROFILE
-- PARAMETER_PROFILE ::= [FORMAL_PART]
-- PARAMETER_AND_RESULT_PROFILE ::= [FORMAL_PART] return SUBTYPE_MARK
-- SUBPROGRAM_BODY ::=
-- SUBPROGRAM_SPECIFICATION is
-- DECLARATIVE_PART
-- begin
-- HANDLED_SEQUENCE_OF_STATEMENTS
-- end [DESIGNATOR];
-- SUBPROGRAM_RENAMING_DECLARATION ::=
-- SUBPROGRAM_SPECIFICATION renames callable_entity_NAME;
-- SUBPROGRAM_BODY_STUB ::=
-- SUBPROGRAM_SPECIFICATION is separate;
-- GENERIC_INSTANTIATION ::=
-- procedure DEFINING_PROGRAM_UNIT_NAME is
-- new generic_procedure_NAME [GENERIC_ACTUAL_PART];
-- | function DEFINING_DESIGNATOR is
-- new generic_function_NAME [GENERIC_ACTUAL_PART];
-- NULL_PROCEDURE_DECLARATION ::=
-- SUBPROGRAM_SPECIFICATION is null;
-- Null procedures are an Ada 2005 feature. A null procedure declaration
-- is classified as a basic declarative item, but it is parsed here, with
-- other subprogram constructs.
-- The value in Pf_Flags indicates which of these possible declarations
-- is acceptable to the caller:
-- Pf_Flags.Decl Set if declaration OK
-- Pf_Flags.Gins Set if generic instantiation OK
-- Pf_Flags.Pbod Set if proper body OK
-- Pf_Flags.Rnam Set if renaming declaration OK
-- Pf_Flags.Stub Set if body stub OK
-- If an inappropriate form is encountered, it is scanned out but an
-- error message indicating that it is appearing in an inappropriate
-- context is issued. The only possible values for Pf_Flags are those
-- defined as constants in the Par package.
-- The caller has checked that the initial token is FUNCTION, PROCEDURE,
-- NOT or OVERRIDING.
-- Error recovery: cannot raise Error_Resync
function P_Subprogram (Pf_Flags : Pf_Rec) return Node_Id is
Specification_Node : Node_Id;
Name_Node : Node_Id;
Fpart_List : List_Id;
Fpart_Sloc : Source_Ptr;
Result_Not_Null : Boolean := False;
Result_Node : Node_Id;
Inst_Node : Node_Id;
Body_Node : Node_Id;
Decl_Node : Node_Id;
Rename_Node : Node_Id;
Absdec_Node : Node_Id;
Stub_Node : Node_Id;
Fproc_Sloc : Source_Ptr;
Func : Boolean;
Scan_State : Saved_Scan_State;
-- Flags for optional overriding indication. Two flags are needed,
-- to distinguish positive and negative overriding indicators from
-- the absence of any indicator.
Is_Overriding : Boolean := False;
Not_Overriding : Boolean := False;
begin
-- Set up scope stack entry. Note that the Labl field will be set later
SIS_Entry_Active := False;
SIS_Missing_Semicolon_Message := No_Error_Msg;
Push_Scope_Stack;
Scope.Table (Scope.Last).Sloc := Token_Ptr;
Scope.Table (Scope.Last).Etyp := E_Name;
Scope.Table (Scope.Last).Ecol := Start_Column;
Scope.Table (Scope.Last).Lreq := False;
-- Ada2005: scan leading overriding indicator
if Token = Tok_Not then
Scan; -- past NOT
if Token = Tok_Overriding then
Scan; -- past OVERRIDING
Not_Overriding := True;
else
Error_Msg_SC ("OVERRIDING expected!");
end if;
elsif Token = Tok_Overriding then
Scan; -- past OVERRIDING
Is_Overriding := True;
end if;
if (Is_Overriding or else Not_Overriding) then
if Ada_Version < Ada_05 then
Error_Msg_SP (" overriding indicator is an Ada 2005 extension");
Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
-- An overriding indicator is allowed for subprogram declarations,
-- bodies, renamings, stubs, and instantiations.
elsif Pf_Flags /= Pf_Decl_Gins_Pbod_Rnam_Stub then
Error_Msg_SC ("overriding indicator not allowed here!");
elsif Token /= Tok_Function
and then Token /= Tok_Procedure
then
Error_Msg_SC ("FUNCTION or PROCEDURE expected!");
end if;
end if;
Func := (Token = Tok_Function);
Fproc_Sloc := Token_Ptr;
Scan; -- past FUNCTION or PROCEDURE
Ignore (Tok_Type);
Ignore (Tok_Body);
if Func then
Name_Node := P_Defining_Designator;
if Nkind (Name_Node) = N_Defining_Operator_Symbol
and then Scope.Last = 1
then
Error_Msg_SP ("operator symbol not allowed at library level");
Name_Node := New_Entity (N_Defining_Identifier, Sloc (Name_Node));
-- Set name from file name, we need some junk name, and that's
-- as good as anything. This is only approximate, since we do
-- not do anything with non-standard name translations.
Get_Name_String (File_Name (Current_Source_File));
for J in 1 .. Name_Len loop
if Name_Buffer (J) = '.' then
Name_Len := J - 1;
exit;
end if;
end loop;
Set_Chars (Name_Node, Name_Find);
Set_Error_Posted (Name_Node);
end if;
else
Name_Node := P_Defining_Program_Unit_Name;
end if;
Scope.Table (Scope.Last).Labl := Name_Node;
if Token = Tok_Colon then
Error_Msg_SC ("redundant colon ignored");
Scan; -- past colon
end if;
-- Deal with generic instantiation, the one case in which we do not
-- have a subprogram specification as part of whatever we are parsing
if Token = Tok_Is then
Save_Scan_State (Scan_State); -- at the IS
T_Is; -- checks for redundant IS
if Token = Tok_New then
if not Pf_Flags.Gins then
Error_Msg_SC ("generic instantation not allowed here!");
end if;
Scan; -- past NEW
if Func then
Inst_Node := New_Node (N_Function_Instantiation, Fproc_Sloc);
Set_Name (Inst_Node, P_Function_Name);
else
Inst_Node := New_Node (N_Procedure_Instantiation, Fproc_Sloc);
Set_Name (Inst_Node, P_Qualified_Simple_Name);
end if;
Set_Defining_Unit_Name (Inst_Node, Name_Node);
Set_Generic_Associations (Inst_Node, P_Generic_Actual_Part_Opt);
TF_Semicolon;
Pop_Scope_Stack; -- Don't need scope stack entry in this case
if Is_Overriding then
Set_Must_Override (Inst_Node);
elsif Not_Overriding then
Set_Must_Not_Override (Inst_Node);
end if;
return Inst_Node;
else
Restore_Scan_State (Scan_State); -- to the IS
end if;
end if;
-- If not a generic instantiation, then we definitely have a subprogram
-- specification (all possibilities at this stage include one here)
Fpart_Sloc := Token_Ptr;
Check_Misspelling_Of (Tok_Return);
-- Scan formal part. First a special error check. If we have an
-- identifier here, then we have a definite error. If this identifier
-- is on the same line as the designator, then we assume it is the
-- first formal after a missing left parenthesis
if Token = Tok_Identifier
and then not Token_Is_At_Start_Of_Line
then
T_Left_Paren; -- to generate message
Fpart_List := P_Formal_Part;
-- Otherwise scan out an optional formal part in the usual manner
else
Fpart_List := P_Parameter_Profile;
end if;
-- We treat what we have as a function specification if FUNCTION was
-- used, or if a RETURN is present. This gives better error recovery
-- since later RETURN statements will be valid in either case.
Check_Junk_Semicolon_Before_Return;
Result_Node := Error;
if Token = Tok_Return then
if not Func then
Error_Msg ("PROCEDURE should be FUNCTION", Fproc_Sloc);
Func := True;
end if;
Scan; -- past RETURN
Result_Not_Null := P_Null_Exclusion; -- Ada 2005 (AI-231)
-- Ada 2005 (AI-318-02)
if Token = Tok_Access then
if Ada_Version < Ada_05 then
Error_Msg_SC
("anonymous access result type is an Ada 2005 extension");
Error_Msg_SC ("\unit must be compiled with -gnat05 switch");
end if;
Result_Node := P_Access_Definition (Result_Not_Null);
else
Result_Node := P_Subtype_Mark;
No_Constraint;
end if;
else
if Func then
Ignore (Tok_Right_Paren);
TF_Return;
end if;
end if;
if Func then
Specification_Node :=
New_Node (N_Function_Specification, Fproc_Sloc);
Set_Null_Exclusion_Present (Specification_Node, Result_Not_Null);
Set_Result_Definition (Specification_Node, Result_Node);
else
Specification_Node :=
New_Node (N_Procedure_Specification, Fproc_Sloc);
end if;
Set_Defining_Unit_Name (Specification_Node, Name_Node);
Set_Parameter_Specifications (Specification_Node, Fpart_List);
if Is_Overriding then
Set_Must_Override (Specification_Node);
elsif Not_Overriding then
Set_Must_Not_Override (Specification_Node);
end if;
-- Error check: barriers not allowed on protected functions/procedures
if Token = Tok_When then
if Func then
Error_Msg_SC ("barrier not allowed on function, only on entry");
else
Error_Msg_SC ("barrier not allowed on procedure, only on entry");
end if;
Scan; -- past WHEN
Discard_Junk_Node (P_Expression);
end if;
-- Deal with case of semicolon ending a subprogram declaration
if Token = Tok_Semicolon then
if not Pf_Flags.Decl then
T_Is;
end if;
Scan; -- past semicolon
-- If semicolon is immediately followed by IS, then ignore the
-- semicolon, and go process the body.
if Token = Tok_Is then
Error_Msg_SP ("unexpected semicolon ignored");
T_Is; -- ignroe redundant IS's
goto Subprogram_Body;
-- If BEGIN follows in an appropriate column, we immediately
-- commence the error action of assuming that the previous
-- subprogram declaration should have been a subprogram body,
-- i.e. that the terminating semicolon should have been IS.
elsif Token = Tok_Begin
and then Start_Column >= Scope.Table (Scope.Last).Ecol
then
Error_Msg_SP (""";"" should be IS!");
goto Subprogram_Body;
else
goto Subprogram_Declaration;
end if;
-- Case of not followed by semicolon
else
-- Subprogram renaming declaration case
Check_Misspelling_Of (Tok_Renames);
if Token = Tok_Renames then
if not Pf_Flags.Rnam then
Error_Msg_SC ("renaming declaration not allowed here!");
end if;
Rename_Node :=
New_Node (N_Subprogram_Renaming_Declaration, Token_Ptr);
Scan; -- past RENAMES
Set_Name (Rename_Node, P_Name);
Set_Specification (Rename_Node, Specification_Node);
TF_Semicolon;
Pop_Scope_Stack;
return Rename_Node;
-- Case of IS following subprogram specification
elsif Token = Tok_Is then
T_Is; -- ignore redundant Is's
if Token_Name = Name_Abstract then
Check_95_Keyword (Tok_Abstract, Tok_Semicolon);
end if;
-- Deal nicely with (now obsolete) use of <> in place of abstract
if Token = Tok_Box then
Error_Msg_SC ("ABSTRACT expected");
Token := Tok_Abstract;
end if;
-- Abstract subprogram declaration case
if Token = Tok_Abstract then
Absdec_Node :=
New_Node (N_Abstract_Subprogram_Declaration, Token_Ptr);
Set_Specification (Absdec_Node, Specification_Node);
Pop_Scope_Stack; -- discard unneeded entry
Scan; -- past ABSTRACT
TF_Semicolon;
return Absdec_Node;
-- Ada 2005 (AI-248): Parse a null procedure declaration
elsif Token = Tok_Null then
if Ada_Version < Ada_05 then
Error_Msg_SP ("null procedures are an Ada 2005 extension");
Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
end if;
Scan; -- past NULL
if Func then
Error_Msg_SP ("only procedures can be null");
else
Set_Null_Present (Specification_Node);
end if;
TF_Semicolon;
goto Subprogram_Declaration;
-- Check for IS NEW with Formal_Part present and handle nicely
elsif Token = Tok_New then
Error_Msg
("formal part not allowed in instantiation", Fpart_Sloc);
Scan; -- past NEW
if Func then
Inst_Node := New_Node (N_Function_Instantiation, Fproc_Sloc);
else
Inst_Node :=
New_Node (N_Procedure_Instantiation, Fproc_Sloc);
end if;
Set_Defining_Unit_Name (Inst_Node, Name_Node);
Set_Name (Inst_Node, P_Name);
Set_Generic_Associations (Inst_Node, P_Generic_Actual_Part_Opt);
TF_Semicolon;
Pop_Scope_Stack; -- Don't need scope stack entry in this case
return Inst_Node;
else
goto Subprogram_Body;
end if;
-- Here we have a missing IS or missing semicolon, we always guess
-- a missing semicolon, since we are pretty good at fixing up a
-- semicolon which should really be an IS
else
Error_Msg_AP ("missing "";""");
SIS_Missing_Semicolon_Message := Get_Msg_Id;
goto Subprogram_Declaration;
end if;
end if;
-- Processing for subprogram body
<<Subprogram_Body>>
if not Pf_Flags.Pbod then
Error_Msg_SP ("subprogram body not allowed here!");
end if;
-- Subprogram body stub case
if Separate_Present then
if not Pf_Flags.Stub then
Error_Msg_SC ("body stub not allowed here!");
end if;
if Nkind (Name_Node) = N_Defining_Operator_Symbol then
Error_Msg
("operator symbol cannot be used as subunit name",
Sloc (Name_Node));
end if;
Stub_Node :=
New_Node (N_Subprogram_Body_Stub, Sloc (Specification_Node));
Set_Specification (Stub_Node, Specification_Node);
Scan; -- past SEPARATE
Pop_Scope_Stack;
TF_Semicolon;
return Stub_Node;
-- Subprogram body case
else
-- Here is the test for a suspicious IS (i.e. one that looks
-- like it might more properly be a semicolon). See separate
-- section discussing use of IS instead of semicolon in
-- package Parse.
if (Token in Token_Class_Declk
or else
Token = Tok_Identifier)
and then Start_Column <= Scope.Table (Scope.Last).Ecol
and then Scope.Last /= 1
then
Scope.Table (Scope.Last).Etyp := E_Suspicious_Is;
Scope.Table (Scope.Last).S_Is := Prev_Token_Ptr;
end if;
Body_Node :=
New_Node (N_Subprogram_Body, Sloc (Specification_Node));
Set_Specification (Body_Node, Specification_Node);
Parse_Decls_Begin_End (Body_Node);
return Body_Node;
end if;
-- Processing for subprogram declaration
<<Subprogram_Declaration>>
Decl_Node :=
New_Node (N_Subprogram_Declaration, Sloc (Specification_Node));
Set_Specification (Decl_Node, Specification_Node);
-- If this is a context in which a subprogram body is permitted,
-- set active SIS entry in case (see section titled "Handling
-- Semicolon Used in Place of IS" in body of Parser package)
-- Note that SIS_Missing_Semicolon_Message is already set properly.
if Pf_Flags.Pbod then
SIS_Labl := Scope.Table (Scope.Last).Labl;
SIS_Sloc := Scope.Table (Scope.Last).Sloc;
SIS_Ecol := Scope.Table (Scope.Last).Ecol;
SIS_Declaration_Node := Decl_Node;
SIS_Semicolon_Sloc := Prev_Token_Ptr;
SIS_Entry_Active := True;
end if;
Pop_Scope_Stack;
return Decl_Node;
end P_Subprogram;
---------------------------------
-- 6.1 Subprogram Declaration --
---------------------------------
-- Parsed by P_Subprogram (6.1)
------------------------------------------
-- 6.1 Abstract Subprogram Declaration --
------------------------------------------
-- Parsed by P_Subprogram (6.1)
-----------------------------------
-- 6.1 Subprogram Specification --
-----------------------------------
-- SUBPROGRAM_SPECIFICATION ::=
-- procedure DEFINING_PROGRAM_UNIT_NAME PARAMETER_PROFILE
-- | function DEFINING_DESIGNATOR PARAMETER_AND_RESULT_PROFILE
-- PARAMETER_PROFILE ::= [FORMAL_PART]
-- PARAMETER_AND_RESULT_PROFILE ::= [FORMAL_PART] return SUBTYPE_MARK
-- Subprogram specifications that appear in subprogram declarations
-- are parsed by P_Subprogram (6.1). This routine is used in other
-- contexts where subprogram specifications occur.
-- Note: this routine does not affect the scope stack in any way
-- Error recovery: can raise Error_Resync
function P_Subprogram_Specification return Node_Id is
Specification_Node : Node_Id;
Result_Not_Null : Boolean;
Result_Node : Node_Id;
begin
if Token = Tok_Function then
Specification_Node := New_Node (N_Function_Specification, Token_Ptr);
Scan; -- past FUNCTION
Ignore (Tok_Body);
Set_Defining_Unit_Name (Specification_Node, P_Defining_Designator);
Set_Parameter_Specifications
(Specification_Node, P_Parameter_Profile);
Check_Junk_Semicolon_Before_Return;
TF_Return;
Result_Not_Null := P_Null_Exclusion; -- Ada 2005 (AI-231)
-- Ada 2005 (AI-318-02)
if Token = Tok_Access then
if Ada_Version < Ada_05 then
Error_Msg_SC
("anonymous access result type is an Ada 2005 extension");
Error_Msg_SC ("\unit must be compiled with -gnat05 switch");
end if;
Result_Node := P_Access_Definition (Result_Not_Null);
else
Result_Node := P_Subtype_Mark;
No_Constraint;
end if;
Set_Null_Exclusion_Present (Specification_Node, Result_Not_Null);
Set_Result_Definition (Specification_Node, Result_Node);
return Specification_Node;
elsif Token = Tok_Procedure then
Specification_Node := New_Node (N_Procedure_Specification, Token_Ptr);
Scan; -- past PROCEDURE
Ignore (Tok_Body);
Set_Defining_Unit_Name
(Specification_Node, P_Defining_Program_Unit_Name);
Set_Parameter_Specifications
(Specification_Node, P_Parameter_Profile);
return Specification_Node;
else
Error_Msg_SC ("subprogram specification expected");
raise Error_Resync;
end if;
end P_Subprogram_Specification;
---------------------
-- 6.1 Designator --
---------------------
-- DESIGNATOR ::=
-- [PARENT_UNIT_NAME .] IDENTIFIER | OPERATOR_SYMBOL
-- The caller has checked that the initial token is an identifier,
-- operator symbol, or string literal. Note that we don't bother to
-- do much error diagnosis in this routine, since it is only used for
-- the label on END lines, and the routines in package Par.Endh will
-- check that the label is appropriate.
-- Error recovery: cannot raise Error_Resync
function P_Designator return Node_Id is
Ident_Node : Node_Id;
Name_Node : Node_Id;
Prefix_Node : Node_Id;
function Real_Dot return Boolean;
-- Tests if a current token is an interesting period, i.e. is followed
-- by an identifier or operator symbol or string literal. If not, it is
-- probably just incorrect punctuation to be caught by our caller. Note
-- that the case of an operator symbol or string literal is also an
-- error, but that is an error that we catch here. If the result is
-- True, a real dot has been scanned and we are positioned past it,
-- if the result is False, the scan position is unchanged.
--------------
-- Real_Dot --
--------------
function Real_Dot return Boolean is
Scan_State : Saved_Scan_State;
begin
if Token /= Tok_Dot then
return False;
else
Save_Scan_State (Scan_State);
Scan; -- past dot
if Token = Tok_Identifier
or else Token = Tok_Operator_Symbol
or else Token = Tok_String_Literal
then
return True;
else
Restore_Scan_State (Scan_State);
return False;
end if;
end if;
end Real_Dot;
-- Start of processing for P_Designator
begin
Ident_Node := Token_Node;
Scan; -- past initial token
if Prev_Token = Tok_Operator_Symbol
or else Prev_Token = Tok_String_Literal
or else not Real_Dot
then
return Ident_Node;
-- Child name case
else
Prefix_Node := Ident_Node;
-- Loop through child names, on entry to this loop, Prefix contains
-- the name scanned so far, and Ident_Node is the last identifier.
loop
Name_Node := New_Node (N_Selected_Component, Prev_Token_Ptr);
Set_Prefix (Name_Node, Prefix_Node);
Ident_Node := P_Identifier;
Set_Selector_Name (Name_Node, Ident_Node);
Prefix_Node := Name_Node;
exit when not Real_Dot;
end loop;
-- On exit from the loop, Ident_Node is the last identifier scanned,
-- i.e. the defining identifier, and Prefix_Node is a node for the
-- entire name, structured (incorrectly!) as a selected component.
Name_Node := Prefix (Prefix_Node);
Change_Node (Prefix_Node, N_Designator);
Set_Name (Prefix_Node, Name_Node);
Set_Identifier (Prefix_Node, Ident_Node);
return Prefix_Node;
end if;
exception
when Error_Resync =>
while Token = Tok_Dot or else Token = Tok_Identifier loop
Scan;
end loop;
return Error;
end P_Designator;
------------------------------
-- 6.1 Defining Designator --
------------------------------
-- DEFINING_DESIGNATOR ::=
-- DEFINING_PROGRAM_UNIT_NAME | DEFINING_OPERATOR_SYMBOL
-- Error recovery: cannot raise Error_Resync
function P_Defining_Designator return Node_Id is
begin
if Token = Tok_Operator_Symbol then
return P_Defining_Operator_Symbol;
elsif Token = Tok_String_Literal then
Error_Msg_SC ("invalid operator name");
Scan; -- past junk string
return Error;
else
return P_Defining_Program_Unit_Name;
end if;
end P_Defining_Designator;
-------------------------------------
-- 6.1 Defining Program Unit Name --
-------------------------------------
-- DEFINING_PROGRAM_UNIT_NAME ::=
-- [PARENT_UNIT_NAME .] DEFINING_IDENTIFIER
-- Note: PARENT_UNIT_NAME may be present only in 95 mode at the outer level
-- Error recovery: cannot raise Error_Resync
function P_Defining_Program_Unit_Name return Node_Id is
Ident_Node : Node_Id;
Name_Node : Node_Id;
Prefix_Node : Node_Id;
begin
-- Set identifier casing if not already set and scan initial identifier
if Token = Tok_Identifier
and then Identifier_Casing (Current_Source_File) = Unknown
then
Set_Identifier_Casing (Current_Source_File, Determine_Token_Casing);
end if;
Ident_Node := P_Identifier (C_Dot);
Merge_Identifier (Ident_Node, Tok_Return);
-- Normal case (not child library unit name)
if Token /= Tok_Dot then
Change_Identifier_To_Defining_Identifier (Ident_Node);
return Ident_Node;
-- Child library unit name case
else
if Scope.Last > 1 then
Error_Msg_SP ("child unit allowed only at library level");
raise Error_Resync;
elsif Ada_Version = Ada_83 then
Error_Msg_SP ("(Ada 83) child unit not allowed!");
end if;
Prefix_Node := Ident_Node;
-- Loop through child names, on entry to this loop, Prefix contains
-- the name scanned so far, and Ident_Node is the last identifier.
loop
exit when Token /= Tok_Dot;
Name_Node := New_Node (N_Selected_Component, Token_Ptr);
Scan; -- past period
Set_Prefix (Name_Node, Prefix_Node);
Ident_Node := P_Identifier (C_Dot);
Set_Selector_Name (Name_Node, Ident_Node);
Prefix_Node := Name_Node;
end loop;
-- On exit from the loop, Ident_Node is the last identifier scanned,
-- i.e. the defining identifier, and Prefix_Node is a node for the
-- entire name, structured (incorrectly!) as a selected component.
Name_Node := Prefix (Prefix_Node);
Change_Node (Prefix_Node, N_Defining_Program_Unit_Name);
Set_Name (Prefix_Node, Name_Node);
Change_Identifier_To_Defining_Identifier (Ident_Node);
Set_Defining_Identifier (Prefix_Node, Ident_Node);
-- All set with unit name parsed
return Prefix_Node;
end if;
exception
when Error_Resync =>
while Token = Tok_Dot or else Token = Tok_Identifier loop
Scan;
end loop;
return Error;
end P_Defining_Program_Unit_Name;
--------------------------
-- 6.1 Operator Symbol --
--------------------------
-- OPERATOR_SYMBOL ::= STRING_LITERAL
-- Operator symbol is returned by the scanner as Tok_Operator_Symbol
-----------------------------------
-- 6.1 Defining Operator Symbol --
-----------------------------------
-- DEFINING_OPERATOR_SYMBOL ::= OPERATOR_SYMBOL
-- The caller has checked that the initial symbol is an operator symbol
function P_Defining_Operator_Symbol return Node_Id is
Op_Node : Node_Id;
begin
Op_Node := Token_Node;
Change_Operator_Symbol_To_Defining_Operator_Symbol (Op_Node);
Scan; -- past operator symbol
return Op_Node;
end P_Defining_Operator_Symbol;
----------------------------
-- 6.1 Parameter_Profile --
----------------------------
-- PARAMETER_PROFILE ::= [FORMAL_PART]
-- Empty is returned if no formal part is present
-- Error recovery: cannot raise Error_Resync
function P_Parameter_Profile return List_Id is
begin
if Token = Tok_Left_Paren then
Scan; -- part left paren
return P_Formal_Part;
else
return No_List;
end if;
end P_Parameter_Profile;
---------------------------------------
-- 6.1 Parameter And Result Profile --
---------------------------------------
-- Parsed by its parent construct, which uses P_Parameter_Profile to
-- parse the parameters, and P_Subtype_Mark to parse the return type.
----------------------
-- 6.1 Formal part --
----------------------
-- FORMAL_PART ::= (PARAMETER_SPECIFICATION {; PARAMETER_SPECIFICATION})
-- PARAMETER_SPECIFICATION ::=
-- DEFINING_IDENTIFIER_LIST : MODE [NULL_EXCLUSION] SUBTYPE_MARK
-- [:= DEFAULT_EXPRESSION]
-- | DEFINING_IDENTIFIER_LIST : ACCESS_DEFINITION
-- [:= DEFAULT_EXPRESSION]
-- This scans the construct Formal_Part. The caller has already checked
-- that the initial token is a left parenthesis, and skipped past it, so
-- that on entry Token is the first token following the left parenthesis.
-- Error recovery: cannot raise Error_Resync
function P_Formal_Part return List_Id is
Specification_List : List_Id;
Specification_Node : Node_Id;
Scan_State : Saved_Scan_State;
Num_Idents : Nat;
Ident : Nat;
Ident_Sloc : Source_Ptr;
Not_Null_Present : Boolean := False;
Idents : array (Int range 1 .. 4096) of Entity_Id;
-- This array holds the list of defining identifiers. The upper bound
-- of 4096 is intended to be essentially infinite, and we do not even
-- bother to check for it being exceeded.
begin
Specification_List := New_List;
Specification_Loop : loop
begin
if Token = Tok_Pragma then
P_Pragmas_Misplaced;
end if;
Ignore (Tok_Left_Paren);
Ident_Sloc := Token_Ptr;
Idents (1) := P_Defining_Identifier (C_Comma_Colon);
Num_Idents := 1;
Ident_Loop : loop
exit Ident_Loop when Token = Tok_Colon;
-- The only valid tokens are colon and comma, so if we have
-- neither do a bit of investigation to see which is the
-- better choice for insertion.
if Token /= Tok_Comma then
-- Assume colon if IN or OUT keyword found
exit Ident_Loop when Token = Tok_In or else Token = Tok_Out;
-- Otherwise scan ahead
Save_Scan_State (Scan_State);
Look_Ahead : loop
-- If we run into a semicolon, then assume that a
-- colon was missing, e.g. Parms (X Y; ...). Also
-- assume missing colon on EOF (a real disaster!)
-- and on a right paren, e.g. Parms (X Y), and also
-- on an assignment symbol, e.g. Parms (X Y := ..)
if Token = Tok_Semicolon
or else Token = Tok_Right_Paren
or else Token = Tok_EOF
or else Token = Tok_Colon_Equal
then
Restore_Scan_State (Scan_State);
exit Ident_Loop;
-- If we run into a colon, assume that we had a missing
-- comma, e.g. Parms (A B : ...). Also assume a missing
-- comma if we hit another comma, e.g. Parms (A B, C ..)
elsif Token = Tok_Colon
or else Token = Tok_Comma
then
Restore_Scan_State (Scan_State);
exit Look_Ahead;
end if;
Scan;
end loop Look_Ahead;
end if;
-- Here if a comma is present, or to be assumed
T_Comma;
Num_Idents := Num_Idents + 1;
Idents (Num_Idents) := P_Defining_Identifier (C_Comma_Colon);
end loop Ident_Loop;
-- Fall through the loop on encountering a colon, or deciding
-- that there is a missing colon.
T_Colon;
-- If there are multiple identifiers, we repeatedly scan the
-- type and initialization expression information by resetting
-- the scan pointer (so that we get completely separate trees
-- for each occurrence).
if Num_Idents > 1 then
Save_Scan_State (Scan_State);
end if;
-- Loop through defining identifiers in list
Ident := 1;
Ident_List_Loop : loop
Specification_Node :=
New_Node (N_Parameter_Specification, Ident_Sloc);
Set_Defining_Identifier (Specification_Node, Idents (Ident));
Not_Null_Present := P_Null_Exclusion; -- Ada 2005 (AI-231)
if Token = Tok_Access then
Set_Null_Exclusion_Present
(Specification_Node, Not_Null_Present);
if Ada_Version = Ada_83 then
Error_Msg_SC ("(Ada 83) access parameters not allowed");
end if;
Set_Parameter_Type (Specification_Node,
P_Access_Definition (Not_Null_Present));
else
if Token = Tok_In or else Token = Tok_Out then
if Not_Null_Present then
Error_Msg_SC
("ACCESS must be placed after the parameter mode");
end if;
P_Mode (Specification_Node);
Not_Null_Present := P_Null_Exclusion; -- Ada 2005 (AI-231)
end if;
Set_Null_Exclusion_Present
(Specification_Node, Not_Null_Present);
if Token = Tok_Procedure
or else
Token = Tok_Function
then
Error_Msg_SC ("formal subprogram parameter not allowed");
Scan;
if Token = Tok_Left_Paren then
Discard_Junk_List (P_Formal_Part);
end if;
if Token = Tok_Return then
Scan;
Discard_Junk_Node (P_Subtype_Mark);
end if;
Set_Parameter_Type (Specification_Node, Error);
else
Set_Parameter_Type (Specification_Node, P_Subtype_Mark);
No_Constraint;
end if;
end if;
Set_Expression (Specification_Node, Init_Expr_Opt (True));
if Ident > 1 then
Set_Prev_Ids (Specification_Node, True);
end if;
if Ident < Num_Idents then
Set_More_Ids (Specification_Node, True);
end if;
Append (Specification_Node, Specification_List);
exit Ident_List_Loop when Ident = Num_Idents;
Ident := Ident + 1;
Restore_Scan_State (Scan_State);
end loop Ident_List_Loop;
exception
when Error_Resync =>
Resync_Semicolon_List;
end;
if Token = Tok_Semicolon then
Save_Scan_State (Scan_State);
Scan; -- past semicolon
-- If we have RETURN or IS after the semicolon, then assume
-- that semicolon should have been a right parenthesis and exit
if Token = Tok_Is or else Token = Tok_Return then
Error_Msg_SP ("expected "")"" in place of "";""");
exit Specification_Loop;
end if;
-- If we have a declaration keyword after the semicolon, then
-- assume we had a missing right parenthesis and terminate list
if Token in Token_Class_Declk then
Error_Msg_AP ("missing "")""");
Restore_Scan_State (Scan_State);
exit Specification_Loop;
end if;
elsif Token = Tok_Right_Paren then
Scan; -- past right paren
exit Specification_Loop;
-- Special check for common error of using comma instead of semicolon
elsif Token = Tok_Comma then
T_Semicolon;
Scan; -- past comma
-- Special check for omitted separator
elsif Token = Tok_Identifier then
T_Semicolon;
-- If nothing sensible, skip to next semicolon or right paren
else
T_Semicolon;
Resync_Semicolon_List;
if Token = Tok_Semicolon then
Scan; -- past semicolon
else
T_Right_Paren;
exit Specification_Loop;
end if;
end if;
end loop Specification_Loop;
return Specification_List;
end P_Formal_Part;
----------------------------------
-- 6.1 Parameter Specification --
----------------------------------
-- Parsed by P_Formal_Part (6.1)
---------------
-- 6.1 Mode --
---------------
-- MODE ::= [in] | in out | out
-- There is no explicit node in the tree for the Mode. Instead the
-- In_Present and Out_Present flags are set in the parent node to
-- record the presence of keywords specifying the mode.
-- Error_Recovery: cannot raise Error_Resync
procedure P_Mode (Node : Node_Id) is
begin
if Token = Tok_In then
Scan; -- past IN
Set_In_Present (Node, True);
if Style.Mode_In_Check and then Token /= Tok_Out then
Error_Msg_SP ("(style) IN should be omitted");
end if;
end if;
if Token = Tok_Out then
Scan; -- past OUT
Set_Out_Present (Node, True);
end if;
if Token = Tok_In then
Error_Msg_SC ("IN must preceed OUT in parameter mode");
Scan; -- past IN
Set_In_Present (Node, True);
end if;
end P_Mode;
--------------------------
-- 6.3 Subprogram Body --
--------------------------
-- Parsed by P_Subprogram (6.1)
-----------------------------------
-- 6.4 Procedure Call Statement --
-----------------------------------
-- Parsed by P_Sequence_Of_Statements (5.1)
------------------------
-- 6.4 Function Call --
------------------------
-- Parsed by P_Call_Or_Name (4.1)
--------------------------------
-- 6.4 Actual Parameter Part --
--------------------------------
-- Parsed by P_Call_Or_Name (4.1)
--------------------------------
-- 6.4 Parameter Association --
--------------------------------
-- Parsed by P_Call_Or_Name (4.1)
------------------------------------
-- 6.4 Explicit Actual Parameter --
------------------------------------
-- Parsed by P_Call_Or_Name (4.1)
---------------------------
-- 6.5 Return Statement --
---------------------------
-- SIMPLE_RETURN_STATEMENT ::= return [EXPRESSION];
--
-- EXTENDED_RETURN_STATEMENT ::=
-- return DEFINING_IDENTIFIER : [aliased] RETURN_SUBTYPE_INDICATION
-- [:= EXPRESSION] [do
-- HANDLED_SEQUENCE_OF_STATEMENTS
-- end return];
--
-- RETURN_SUBTYPE_INDICATION ::= SUBTYPE_INDICATION | ACCESS_DEFINITION
-- RETURN_STATEMENT ::= return [EXPRESSION];
-- Error recovery: can raise Error_Resync
procedure P_Return_Subtype_Indication (Decl_Node : Node_Id) is
-- Note: We don't need to check Ada_Version here, because this is
-- only called in >= Ada 2005 cases anyway.
Not_Null_Present : constant Boolean := P_Null_Exclusion;
begin
Set_Null_Exclusion_Present (Decl_Node, Not_Null_Present);
if Token = Tok_Access then
Set_Object_Definition
(Decl_Node, P_Access_Definition (Not_Null_Present));
else
Set_Object_Definition
(Decl_Node, P_Subtype_Indication (Not_Null_Present));
end if;
end P_Return_Subtype_Indication;
-- Error recovery: can raise Error_Resync
function P_Return_Object_Declaration return Node_Id is
Return_Obj : Node_Id;
Decl_Node : Node_Id;
begin
Return_Obj := Token_Node;
Change_Identifier_To_Defining_Identifier (Return_Obj);
Decl_Node := New_Node (N_Object_Declaration, Token_Ptr);
Set_Defining_Identifier (Decl_Node, Return_Obj);
Scan; -- past identifier
Scan; -- past :
-- First an error check, if we have two identifiers in a row, a likely
-- possibility is that the first of the identifiers is an incorrectly
-- spelled keyword. See similar check in P_Identifier_Declarations.
if Token = Tok_Identifier then
declare
SS : Saved_Scan_State;
I2 : Boolean;
begin
Save_Scan_State (SS);
Scan; -- past initial identifier
I2 := (Token = Tok_Identifier);
Restore_Scan_State (SS);
if I2
and then
(Bad_Spelling_Of (Tok_Access) or else
Bad_Spelling_Of (Tok_Aliased) or else
Bad_Spelling_Of (Tok_Constant))
then
null;
end if;
end;
end if;
-- We allow "constant" here (as in "return Result : constant
-- T..."). This is not in the latest RM, but the ARG is considering an
-- AI on the subject (see AI05-0015-1), which we expect to be approved.
if Token = Tok_Constant then
Scan; -- past CONSTANT
Set_Constant_Present (Decl_Node);
if Token = Tok_Aliased then
Error_Msg_SC ("ALIASED should be before CONSTANT");
Scan; -- past ALIASED
Set_Aliased_Present (Decl_Node);
end if;
elsif Token = Tok_Aliased then
Scan; -- past ALIASED
Set_Aliased_Present (Decl_Node);
if Token = Tok_Constant then
Scan; -- past CONSTANT
Set_Constant_Present (Decl_Node);
end if;
end if;
P_Return_Subtype_Indication (Decl_Node);
if Token = Tok_Colon_Equal then
Scan; -- past :=
Set_Expression (Decl_Node, P_Expression_No_Right_Paren);
end if;
return Decl_Node;
end P_Return_Object_Declaration;
-- Error recovery: can raise Error_Resync
function P_Return_Statement return Node_Id is
-- The caller has checked that the initial token is RETURN
function Is_Simple return Boolean;
-- Scan state is just after RETURN (and is left that way).
-- Determine whether this is a simple or extended return statement
-- by looking ahead for "identifier :", which implies extended.
---------------
-- Is_Simple --
---------------
function Is_Simple return Boolean is
Scan_State : Saved_Scan_State;
Result : Boolean := True;
begin
if Token = Tok_Identifier then
Save_Scan_State (Scan_State); -- at identifier
Scan; -- past identifier
if Token = Tok_Colon then
Result := False; -- It's an extended_return_statement.
end if;
Restore_Scan_State (Scan_State); -- to identifier
end if;
return Result;
end Is_Simple;
Return_Sloc : constant Source_Ptr := Token_Ptr;
Return_Node : Node_Id;
-- Start of processing for P_Return_Statement
begin
Scan; -- past RETURN
-- Simple_return_statement, no expression, return an N_Return_Statement
-- node with the expression field left Empty.
if Token = Tok_Semicolon then
Scan; -- past ;
Return_Node := New_Node (N_Return_Statement, Return_Sloc);
-- Non-simple case
else
-- Simple_return_statement with expression
-- We avoid trying to scan an expression if we are at an
-- expression terminator since in that case the best error
-- message is probably that we have a missing semicolon.
if Is_Simple then
Return_Node := New_Node (N_Return_Statement, Return_Sloc);
if Token not in Token_Class_Eterm then
Set_Expression (Return_Node, P_Expression_No_Right_Paren);
end if;
-- Extended_return_statement (Ada 2005 only -- AI-318):
else
if Ada_Version < Ada_05 then
Error_Msg_SP
(" extended_return_statement is an Ada 2005 extension");
Error_Msg_SP ("\unit must be compiled with -gnat05 switch");
end if;
Return_Node := New_Node (N_Extended_Return_Statement, Return_Sloc);
Set_Return_Object_Declarations
(Return_Node, New_List (P_Return_Object_Declaration));
if Token = Tok_Do then
Push_Scope_Stack;
Scope.Table (Scope.Last).Etyp := E_Return;
Scope.Table (Scope.Last).Ecol := Start_Column;
Scope.Table (Scope.Last).Sloc := Return_Sloc;
Scan; -- past DO
Set_Handled_Statement_Sequence
(Return_Node, P_Handled_Sequence_Of_Statements);
End_Statements;
-- Do we need to handle Error_Resync here???
end if;
end if;
TF_Semicolon;
end if;
return Return_Node;
end P_Return_Statement;
end Ch6;