8sa1-gcc/gcc/ada/par-ch13.adb
Arnaud Charlet 78efd71259 [multiple changes]
2011-08-04  Yannick Moy  <moy@adacore.com>

	* par-ch13.adb (Aspect_Specifications_Present): recognize
	"with Identifier'Class =>" as an aspect, so that a meaningful warning
	is issued in Strict mode.
	* par.adb: Fix typos in comments.

2011-08-04  Yannick Moy  <moy@adacore.com>

	* sem_attr.adb (Result): modify error message to take into account Post
	aspect when compiling Ada 2012 (or newer) code.

2011-08-04  Nicolas Roche  <roche@adacore.com>

	* env.c (__gnat_clearenv): Avoid use of dynamic size array in order to
	remove need for GCC exceptions. 

2011-08-04  Vincent Celier  <celier@adacore.com>

	* makeutl.adb (Do_Complete): Call Debug_Output with the name of the
	project, not the source file name.
	* prj.adb (Find_Sources.Look_For_Sources): If the source has been
	excluded, continue looking. This excluded source will only be returned
	if there is no other source with the same base name that is not locally
	removed.

2011-08-04  Ed Schonberg  <schonberg@adacore.com>

	* sem_res.adb (Resolve_Intrinsic_Operator): if the result type is
	private and one of the operands is a real literal, use a qualified
	expression rather than a conversion which is not meaningful to the
	back-end.

From-SVN: r177342
2011-08-04 11:18:12 +02:00

749 lines
23 KiB
Ada

------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- P A R . C H 1 3 --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2011, 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 3, 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 COPYING3. If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- 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
separate (Par)
package body Ch13 is
-- Local functions, used only in this chapter
function P_Component_Clause return Node_Id;
function P_Mod_Clause return Node_Id;
-----------------------------------
-- Aspect_Specifications_Present --
-----------------------------------
function Aspect_Specifications_Present
(Strict : Boolean := Ada_Version < Ada_2012) return Boolean
is
Scan_State : Saved_Scan_State;
Result : Boolean;
begin
-- Definitely must have WITH to consider aspect specs to be present
-- Note that this means that if we have a semicolon, we immediately
-- return False. There is a case in which this is not optimal, namely
-- something like
-- type R is new Integer;
-- with bla bla;
-- where the semicolon is redundant, but scanning forward for it would
-- be too expensive. Instead we pick up the aspect specifications later
-- as a bogus declaration, and diagnose the semicolon at that point.
if Token /= Tok_With then
return False;
end if;
-- Have a WITH, see if it looks like an aspect specification
Save_Scan_State (Scan_State);
Scan; -- past WITH
-- If no identifier, then consider that we definitely do not have an
-- aspect specification.
if Token /= Tok_Identifier then
Result := False;
-- This is where we pay attention to the Strict mode. Normally when we
-- are in Ada 2012 mode, Strict is False, and we consider that we have
-- an aspect specification if the identifier is an aspect name (even if
-- not followed by =>) or the identifier is not an aspect name but is
-- followed by =>. P_Aspect_Specifications will generate messages if the
-- aspect specification is ill-formed.
elsif not Strict then
if Get_Aspect_Id (Token_Name) /= No_Aspect then
Result := True;
else
Scan; -- past identifier
Result := Token = Tok_Arrow;
end if;
-- If earlier than Ada 2012, check for valid aspect identifier (possibly
-- completed with 'CLASS) followed by an arrow, and consider that this
-- is still an aspect specification so we give an appropriate message.
else
if Get_Aspect_Id (Token_Name) = No_Aspect then
Result := False;
else
Scan; -- past aspect name
Result := False;
if Token = Tok_Arrow then
Result := True;
elsif Token = Tok_Apostrophe then
Scan; -- past apostrophe
if Token = Tok_Identifier
and then Token_Name = Name_Class
then
Scan; -- past CLASS
if Token = Tok_Arrow then
Result := True;
end if;
end if;
end if;
if Result then
Restore_Scan_State (Scan_State);
Error_Msg_SC ("|aspect specification is an Ada 2012 feature");
Error_Msg_SC ("\|unit must be compiled with -gnat2012 switch");
return True;
end if;
end if;
end if;
Restore_Scan_State (Scan_State);
return Result;
end Aspect_Specifications_Present;
--------------------------------------------
-- 13.1 Representation Clause (also I.7) --
--------------------------------------------
-- REPRESENTATION_CLAUSE ::=
-- ATTRIBUTE_DEFINITION_CLAUSE
-- | ENUMERATION_REPRESENTATION_CLAUSE
-- | RECORD_REPRESENTATION_CLAUSE
-- | AT_CLAUSE
-- ATTRIBUTE_DEFINITION_CLAUSE ::=
-- for LOCAL_NAME'ATTRIBUTE_DESIGNATOR use EXPRESSION;
-- | for LOCAL_NAME'ATTRIBUTE_DESIGNATOR use NAME;
-- Note: in Ada 83, the expression must be a simple expression
-- AT_CLAUSE ::= for DIRECT_NAME use at EXPRESSION;
-- Note: in Ada 83, the expression must be a simple expression
-- ENUMERATION_REPRESENTATION_CLAUSE ::=
-- for first_subtype_LOCAL_NAME use ENUMERATION_AGGREGATE;
-- ENUMERATION_AGGREGATE ::= ARRAY_AGGREGATE
-- RECORD_REPRESENTATION_CLAUSE ::=
-- for first_subtype_LOCAL_NAME use
-- record [MOD_CLAUSE]
-- {COMPONENT_CLAUSE}
-- end record;
-- Note: for now we allow only a direct name as the local name in the
-- above constructs. This probably needs changing later on ???
-- The caller has checked that the initial token is FOR
-- Error recovery: cannot raise Error_Resync, if an error occurs,
-- the scan is repositioned past the next semicolon.
function P_Representation_Clause return Node_Id is
For_Loc : Source_Ptr;
Name_Node : Node_Id;
Prefix_Node : Node_Id;
Attr_Name : Name_Id;
Identifier_Node : Node_Id;
Rep_Clause_Node : Node_Id;
Expr_Node : Node_Id;
Record_Items : List_Id;
begin
For_Loc := Token_Ptr;
Scan; -- past FOR
-- Note that the name in a representation clause is always a simple
-- name, even in the attribute case, see AI-300 which made this so!
Identifier_Node := P_Identifier (C_Use);
-- Check case of qualified name to give good error message
if Token = Tok_Dot then
Error_Msg_SC
("representation clause requires simple name!");
loop
exit when Token /= Tok_Dot;
Scan; -- past dot
Discard_Junk_Node (P_Identifier);
end loop;
end if;
-- Attribute Definition Clause
if Token = Tok_Apostrophe then
-- Allow local names of the form a'b'.... This enables
-- us to parse class-wide streams attributes correctly.
Name_Node := Identifier_Node;
while Token = Tok_Apostrophe loop
Scan; -- past apostrophe
Identifier_Node := Token_Node;
Attr_Name := No_Name;
if Token = Tok_Identifier then
Attr_Name := Token_Name;
if not Is_Attribute_Name (Attr_Name) then
Signal_Bad_Attribute;
end if;
if Style_Check then
Style.Check_Attribute_Name (False);
end if;
-- Here for case of attribute designator is not an identifier
else
if Token = Tok_Delta then
Attr_Name := Name_Delta;
elsif Token = Tok_Digits then
Attr_Name := Name_Digits;
elsif Token = Tok_Access then
Attr_Name := Name_Access;
else
Error_Msg_AP ("attribute designator expected");
raise Error_Resync;
end if;
if Style_Check then
Style.Check_Attribute_Name (True);
end if;
end if;
-- We come here with an OK attribute scanned, and the
-- corresponding Attribute identifier node stored in Ident_Node.
Prefix_Node := Name_Node;
Name_Node := New_Node (N_Attribute_Reference, Prev_Token_Ptr);
Set_Prefix (Name_Node, Prefix_Node);
Set_Attribute_Name (Name_Node, Attr_Name);
Scan;
end loop;
Rep_Clause_Node := New_Node (N_Attribute_Definition_Clause, For_Loc);
Set_Name (Rep_Clause_Node, Prefix_Node);
Set_Chars (Rep_Clause_Node, Attr_Name);
T_Use;
Expr_Node := P_Expression_No_Right_Paren;
Check_Simple_Expression_In_Ada_83 (Expr_Node);
Set_Expression (Rep_Clause_Node, Expr_Node);
else
TF_Use;
Rep_Clause_Node := Empty;
-- AT follows USE (At Clause)
if Token = Tok_At then
Scan; -- past AT
Rep_Clause_Node := New_Node (N_At_Clause, For_Loc);
Set_Identifier (Rep_Clause_Node, Identifier_Node);
Expr_Node := P_Expression_No_Right_Paren;
Check_Simple_Expression_In_Ada_83 (Expr_Node);
Set_Expression (Rep_Clause_Node, Expr_Node);
-- RECORD follows USE (Record Representation Clause)
elsif Token = Tok_Record then
Record_Items := P_Pragmas_Opt;
Rep_Clause_Node :=
New_Node (N_Record_Representation_Clause, For_Loc);
Set_Identifier (Rep_Clause_Node, Identifier_Node);
Push_Scope_Stack;
Scope.Table (Scope.Last).Etyp := E_Record;
Scope.Table (Scope.Last).Ecol := Start_Column;
Scope.Table (Scope.Last).Sloc := Token_Ptr;
Scan; -- past RECORD
Record_Items := P_Pragmas_Opt;
-- Possible Mod Clause
if Token = Tok_At then
Set_Mod_Clause (Rep_Clause_Node, P_Mod_Clause);
Set_Pragmas_Before (Mod_Clause (Rep_Clause_Node), Record_Items);
Record_Items := P_Pragmas_Opt;
end if;
if No (Record_Items) then
Record_Items := New_List;
end if;
Set_Component_Clauses (Rep_Clause_Node, Record_Items);
-- Loop through component clauses
loop
if Token not in Token_Class_Name then
exit when Check_End;
end if;
Append (P_Component_Clause, Record_Items);
P_Pragmas_Opt (Record_Items);
end loop;
-- Left paren follows USE (Enumeration Representation Clause)
elsif Token = Tok_Left_Paren then
Rep_Clause_Node :=
New_Node (N_Enumeration_Representation_Clause, For_Loc);
Set_Identifier (Rep_Clause_Node, Identifier_Node);
Set_Array_Aggregate (Rep_Clause_Node, P_Aggregate);
-- Some other token follows FOR (invalid representation clause)
else
Error_Msg_SC ("invalid representation clause");
raise Error_Resync;
end if;
end if;
TF_Semicolon;
return Rep_Clause_Node;
exception
when Error_Resync =>
Resync_Past_Semicolon;
return Error;
end P_Representation_Clause;
----------------------
-- 13.1 Local Name --
----------------------
-- Local name is always parsed by its parent. In the case of its use in
-- pragmas, the check for a local name is handled in Par.Prag and allows
-- all the possible forms of local name. For the uses in chapter 13, we
-- currently only allow a direct name, but this should probably change???
---------------------------
-- 13.1 At Clause (I.7) --
---------------------------
-- Parsed by P_Representation_Clause (13.1)
---------------------------------------
-- 13.3 Attribute Definition Clause --
---------------------------------------
-- Parsed by P_Representation_Clause (13.1)
--------------------------------
-- 13.1 Aspect Specification --
--------------------------------
-- ASPECT_SPECIFICATION ::=
-- with ASPECT_MARK [=> ASPECT_DEFINITION] {.
-- ASPECT_MARK [=> ASPECT_DEFINITION] }
-- ASPECT_MARK ::= aspect_IDENTIFIER['Class]
-- ASPECT_DEFINITION ::= NAME | EXPRESSION
-- Error recovery: cannot raise Error_Resync
procedure P_Aspect_Specifications
(Decl : Node_Id;
Semicolon : Boolean := True)
is
Aspects : List_Id;
Aspect : Node_Id;
A_Id : Aspect_Id;
OK : Boolean;
Ptr : Source_Ptr;
begin
-- Check if aspect specification present
if not Aspect_Specifications_Present then
if Semicolon then
TF_Semicolon;
end if;
return;
end if;
-- Aspect Specification is present
Ptr := Token_Ptr;
Scan; -- past WITH
-- Here we have an aspect specification to scan, note that we don;t
-- set the flag till later, because it may turn out that we have no
-- valid aspects in the list.
Aspects := Empty_List;
loop
OK := True;
if Token /= Tok_Identifier then
Error_Msg_SC ("aspect identifier expected");
if Semicolon then
Resync_Past_Semicolon;
end if;
return;
end if;
-- We have an identifier (which should be an aspect identifier)
A_Id := Get_Aspect_Id (Token_Name);
Aspect :=
Make_Aspect_Specification (Token_Ptr,
Identifier => Token_Node);
-- No valid aspect identifier present
if A_Id = No_Aspect then
Error_Msg_SC ("aspect identifier expected");
-- Check bad spelling
for J in Aspect_Id loop
if Is_Bad_Spelling_Of (Token_Name, Aspect_Names (J)) then
Error_Msg_Name_1 := Aspect_Names (J);
Error_Msg_SC -- CODEFIX
("\possible misspelling of%");
exit;
end if;
end loop;
Scan; -- past incorrect identifier
if Token = Tok_Apostrophe then
Scan; -- past '
Scan; -- past presumably CLASS
end if;
if Token = Tok_Arrow then
Scan; -- Past arrow
Set_Expression (Aspect, P_Expression);
OK := False;
elsif Token = Tok_Comma then
OK := False;
else
if Semicolon then
Resync_Past_Semicolon;
end if;
return;
end if;
-- OK aspect scanned
else
Scan; -- past identifier
-- Check for 'Class present
if Token = Tok_Apostrophe then
if not Class_Aspect_OK (A_Id) then
Error_Msg_Node_1 := Identifier (Aspect);
Error_Msg_SC ("aspect& does not permit attribute here");
Scan; -- past apostrophe
Scan; -- past presumed CLASS
OK := False;
else
Scan; -- past apostrophe
if Token /= Tok_Identifier
or else Token_Name /= Name_Class
then
Error_Msg_SC ("Class attribute expected here");
OK := False;
if Token = Tok_Identifier then
Scan; -- past identifier not CLASS
end if;
else
Scan; -- past CLASS
Set_Class_Present (Aspect);
end if;
end if;
end if;
-- Test case of missing aspect definition
if Token = Tok_Comma
or else Token = Tok_Semicolon
or else (not Semicolon and then Token /= Tok_Arrow)
then
if Aspect_Argument (A_Id) /= Optional then
Error_Msg_Node_1 := Aspect;
Error_Msg_AP ("aspect& requires an aspect definition");
OK := False;
end if;
-- Here we have an aspect definition
else
if Token = Tok_Arrow then
Scan; -- past arrow
else
T_Arrow;
OK := False;
end if;
if Aspect_Argument (A_Id) = Name then
Set_Expression (Aspect, P_Name);
else
Set_Expression (Aspect, P_Expression);
end if;
end if;
-- If OK clause scanned, add it to the list
if OK then
Append (Aspect, Aspects);
end if;
if Token = Tok_Comma then
Scan; -- past comma
-- Must be terminator character
else
if Semicolon then
T_Semicolon;
end if;
exit;
end if;
end if;
end loop;
-- Here if aspects present
if Is_Non_Empty_List (Aspects) then
-- If Decl is Empty, we just ignore the aspects (the caller in this
-- case has always issued an appropriate error message).
if Decl = Empty then
null;
-- If Decl is Error, we ignore the aspects, and issue a message
elsif Decl = Error then
Error_Msg ("aspect specifications not allowed here", Ptr);
-- Here aspects are allowed, and we store them
else
Set_Parent (Aspects, Decl);
Set_Aspect_Specifications (Decl, Aspects);
end if;
end if;
end P_Aspect_Specifications;
---------------------------------------------
-- 13.4 Enumeration Representation Clause --
---------------------------------------------
-- Parsed by P_Representation_Clause (13.1)
---------------------------------
-- 13.4 Enumeration Aggregate --
---------------------------------
-- Parsed by P_Representation_Clause (13.1)
------------------------------------------
-- 13.5.1 Record Representation Clause --
------------------------------------------
-- Parsed by P_Representation_Clause (13.1)
------------------------------
-- 13.5.1 Mod Clause (I.8) --
------------------------------
-- MOD_CLAUSE ::= at mod static_EXPRESSION;
-- Note: in Ada 83, the expression must be a simple expression
-- The caller has checked that the initial Token is AT
-- Error recovery: cannot raise Error_Resync
-- Note: the caller is responsible for setting the Pragmas_Before field
function P_Mod_Clause return Node_Id is
Mod_Node : Node_Id;
Expr_Node : Node_Id;
begin
Mod_Node := New_Node (N_Mod_Clause, Token_Ptr);
Scan; -- past AT
T_Mod;
Expr_Node := P_Expression_No_Right_Paren;
Check_Simple_Expression_In_Ada_83 (Expr_Node);
Set_Expression (Mod_Node, Expr_Node);
TF_Semicolon;
return Mod_Node;
end P_Mod_Clause;
------------------------------
-- 13.5.1 Component Clause --
------------------------------
-- COMPONENT_CLAUSE ::=
-- COMPONENT_CLAUSE_COMPONENT_NAME at POSITION
-- range FIRST_BIT .. LAST_BIT;
-- COMPONENT_CLAUSE_COMPONENT_NAME ::=
-- component_DIRECT_NAME
-- | component_DIRECT_NAME'ATTRIBUTE_DESIGNATOR
-- | FIRST_SUBTYPE_DIRECT_NAME'ATTRIBUTE_DESIGNATOR
-- POSITION ::= static_EXPRESSION
-- Note: in Ada 83, the expression must be a simple expression
-- FIRST_BIT ::= static_SIMPLE_EXPRESSION
-- LAST_BIT ::= static_SIMPLE_EXPRESSION
-- Note: the AARM V2.0 grammar has an error at this point, it uses
-- EXPRESSION instead of SIMPLE_EXPRESSION for FIRST_BIT and LAST_BIT
-- Error recovery: cannot raise Error_Resync
function P_Component_Clause return Node_Id is
Component_Node : Node_Id;
Comp_Name : Node_Id;
Expr_Node : Node_Id;
begin
Component_Node := New_Node (N_Component_Clause, Token_Ptr);
Comp_Name := P_Name;
if Nkind (Comp_Name) = N_Identifier
or else Nkind (Comp_Name) = N_Attribute_Reference
then
Set_Component_Name (Component_Node, Comp_Name);
else
Error_Msg_N
("component name must be direct name or attribute", Comp_Name);
Set_Component_Name (Component_Node, Error);
end if;
Set_Sloc (Component_Node, Token_Ptr);
T_At;
Expr_Node := P_Expression_No_Right_Paren;
Check_Simple_Expression_In_Ada_83 (Expr_Node);
Set_Position (Component_Node, Expr_Node);
T_Range;
Expr_Node := P_Expression_No_Right_Paren;
Check_Simple_Expression_In_Ada_83 (Expr_Node);
Set_First_Bit (Component_Node, Expr_Node);
T_Dot_Dot;
Expr_Node := P_Expression_No_Right_Paren;
Check_Simple_Expression_In_Ada_83 (Expr_Node);
Set_Last_Bit (Component_Node, Expr_Node);
TF_Semicolon;
return Component_Node;
end P_Component_Clause;
----------------------
-- 13.5.1 Position --
----------------------
-- Parsed by P_Component_Clause (13.5.1)
-----------------------
-- 13.5.1 First Bit --
-----------------------
-- Parsed by P_Component_Clause (13.5.1)
----------------------
-- 13.5.1 Last Bit --
----------------------
-- Parsed by P_Component_Clause (13.5.1)
--------------------------
-- 13.8 Code Statement --
--------------------------
-- CODE_STATEMENT ::= QUALIFIED_EXPRESSION
-- On entry the caller has scanned the SUBTYPE_MARK (passed in as the
-- single argument, and the scan points to the apostrophe.
-- Error recovery: can raise Error_Resync
function P_Code_Statement (Subtype_Mark : Node_Id) return Node_Id is
Node1 : Node_Id;
begin
Scan; -- past apostrophe
-- If left paren, then we have a possible code statement
if Token = Tok_Left_Paren then
Node1 := New_Node (N_Code_Statement, Sloc (Subtype_Mark));
Set_Expression (Node1, P_Qualified_Expression (Subtype_Mark));
TF_Semicolon;
return Node1;
-- Otherwise we have an illegal range attribute. Note that P_Name
-- ensures that Token = Tok_Range is the only possibility left here.
else -- Token = Tok_Range
Error_Msg_SC ("RANGE attribute illegal here!");
raise Error_Resync;
end if;
end P_Code_Statement;
end Ch13;