aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/aspects.ads5
-rw-r--r--gcc/ada/contracts.adb18
-rw-r--r--gcc/ada/contracts.ads2
-rw-r--r--gcc/ada/einfo-utils.adb1
-rw-r--r--gcc/ada/einfo-utils.ads1
-rw-r--r--gcc/ada/exp_prag.adb41
-rw-r--r--gcc/ada/exp_prag.ads4
-rw-r--r--gcc/ada/inline.adb2
-rw-r--r--gcc/ada/par-prag.adb1
-rw-r--r--gcc/ada/sem_ch12.adb3
-rw-r--r--gcc/ada/sem_ch13.adb28
-rw-r--r--gcc/ada/sem_prag.adb429
-rw-r--r--gcc/ada/sem_prag.ads8
-rw-r--r--gcc/ada/sem_util.adb1
-rw-r--r--gcc/ada/sem_util.ads1
-rw-r--r--gcc/ada/sinfo.ads4
-rw-r--r--gcc/ada/snames.ads-tmpl2
17 files changed, 538 insertions, 13 deletions
diff --git a/gcc/ada/aspects.ads b/gcc/ada/aspects.ads
index 36957d4..6670b64 100644
--- a/gcc/ada/aspects.ads
+++ b/gcc/ada/aspects.ads
@@ -96,6 +96,7 @@ package Aspects is
Aspect_Dynamic_Predicate,
Aspect_Effective_Reads, -- GNAT
Aspect_Effective_Writes, -- GNAT
+ Aspect_Exceptional_Cases, -- GNAT
Aspect_Extensions_Visible, -- GNAT
Aspect_External_Name,
Aspect_External_Tag,
@@ -389,6 +390,7 @@ package Aspects is
Aspect_Dynamic_Predicate => Expression,
Aspect_Effective_Reads => Optional_Expression,
Aspect_Effective_Writes => Optional_Expression,
+ Aspect_Exceptional_Cases => Expression,
Aspect_Extensions_Visible => Optional_Expression,
Aspect_External_Name => Expression,
Aspect_External_Tag => Expression,
@@ -496,6 +498,7 @@ package Aspects is
Aspect_Dynamic_Predicate => False,
Aspect_Effective_Reads => False,
Aspect_Effective_Writes => False,
+ Aspect_Exceptional_Cases => False,
Aspect_Exclusive_Functions => False,
Aspect_Extensions_Visible => False,
Aspect_External_Name => False,
@@ -653,6 +656,7 @@ package Aspects is
Aspect_Effective_Reads => Name_Effective_Reads,
Aspect_Effective_Writes => Name_Effective_Writes,
Aspect_Elaborate_Body => Name_Elaborate_Body,
+ Aspect_Exceptional_Cases => Name_Exceptional_Cases,
Aspect_Exclusive_Functions => Name_Exclusive_Functions,
Aspect_Export => Name_Export,
Aspect_Extensions_Visible => Name_Extensions_Visible,
@@ -981,6 +985,7 @@ package Aspects is
Aspect_Disable_Controlled => Never_Delay,
Aspect_Effective_Reads => Never_Delay,
Aspect_Effective_Writes => Never_Delay,
+ Aspect_Exceptional_Cases => Never_Delay,
Aspect_Export => Never_Delay,
Aspect_Extensions_Visible => Never_Delay,
Aspect_Ghost => Never_Delay,
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index b0a0ab20..c85df0f 100644
--- a/gcc/ada/contracts.adb
+++ b/gcc/ada/contracts.adb
@@ -104,8 +104,9 @@ package body Contracts is
procedure Expand_Subprogram_Contract (Body_Id : Entity_Id);
-- Expand the contracts of a subprogram body and its correspoding spec (if
-- any). This routine processes all [refined] pre- and postconditions as
- -- well as Contract_Cases, Subprogram_Variant, invariants and predicates.
- -- Body_Id denotes the entity of the subprogram body.
+ -- well as Contract_Cases, Exceptional_Cases, Subprogram_Variant,
+ -- invariants and predicates. Body_Id denotes the entity of the
+ -- subprogram body.
procedure Preanalyze_Condition
(Subp : Entity_Id;
@@ -253,6 +254,7 @@ package body Contracts is
Add_Classification;
elsif Prag_Nam in Name_Contract_Cases
+ | Name_Exceptional_Cases
| Name_Subprogram_Variant
| Name_Test_Case
then
@@ -629,8 +631,9 @@ package body Contracts is
end if;
-- Deal with preconditions, [refined] postconditions, Contract_Cases,
- -- Subprogram_Variant, invariants and predicates associated with body
- -- and its spec. Do not expand the contract of subprogram body stubs.
+ -- Exceptional_Cases, Subprogram_Variant, invariants and predicates
+ -- associated with body and its spec. Do not expand the contract of
+ -- subprogram body stubs.
if Nkind (Body_Decl) = N_Subprogram_Body then
Expand_Subprogram_Contract (Body_Id);
@@ -766,6 +769,9 @@ package body Contracts is
Analyze_Contract_Cases_In_Decl_Part (Prag, Freeze_Id);
end if;
+ elsif Prag_Nam = Name_Exceptional_Cases then
+ Analyze_Exceptional_Cases_In_Decl_Part (Prag);
+
elsif Prag_Nam = Name_Subprogram_Variant then
Analyze_Subprogram_Variant_In_Decl_Part (Prag);
@@ -1493,6 +1499,7 @@ package body Contracts is
-- The stub acts as its own spec, the applicable pragmas are:
-- Contract_Cases
-- Depends
+ -- Exceptional_Cases
-- Global
-- Postcondition
-- Precondition
@@ -2830,6 +2837,9 @@ package body Contracts is
Decls => Decls,
Stmts => Stmts);
+ elsif Pragma_Name (Prag) = Name_Exceptional_Cases then
+ Expand_Pragma_Exceptional_Cases (Prag);
+
elsif Pragma_Name (Prag) = Name_Subprogram_Variant then
Expand_Pragma_Subprogram_Variant
(Prag => Prag,
diff --git a/gcc/ada/contracts.ads b/gcc/ada/contracts.ads
index 0a03d19..a53565f 100644
--- a/gcc/ada/contracts.ads
+++ b/gcc/ada/contracts.ads
@@ -81,6 +81,7 @@ package Contracts is
--
-- Contract_Cases (stand alone subprogram body)
-- Depends (stand alone subprogram body)
+ -- Exceptional_Cases (stand alone subprogram body)
-- Global (stand alone subprogram body)
-- Postcondition (stand alone subprogram body)
-- Precondition (stand alone subprogram body)
@@ -99,6 +100,7 @@ package Contracts is
--
-- Contract_Cases
-- Depends
+ -- Exceptional_Cases
-- Global
-- Postcondition
-- Precondition
diff --git a/gcc/ada/einfo-utils.adb b/gcc/ada/einfo-utils.adb
index 5916188..fa28a9e 100644
--- a/gcc/ada/einfo-utils.adb
+++ b/gcc/ada/einfo-utils.adb
@@ -1018,6 +1018,7 @@ package body Einfo.Utils is
Is_CTC : constant Boolean :=
Id = Pragma_Contract_Cases or else
+ Id = Pragma_Exceptional_Cases or else
Id = Pragma_Subprogram_Variant or else
Id = Pragma_Test_Case;
diff --git a/gcc/ada/einfo-utils.ads b/gcc/ada/einfo-utils.ads
index 1749946..e805502 100644
--- a/gcc/ada/einfo-utils.ads
+++ b/gcc/ada/einfo-utils.ads
@@ -447,6 +447,7 @@ package Einfo.Utils is
-- Depends
-- Effective_Reads
-- Effective_Writes
+ -- Exceptional_Cases
-- Global
-- Initial_Condition
-- Initializes
diff --git a/gcc/ada/exp_prag.adb b/gcc/ada/exp_prag.adb
index c6b3bed..e660196 100644
--- a/gcc/ada/exp_prag.adb
+++ b/gcc/ada/exp_prag.adb
@@ -1978,6 +1978,47 @@ package body Exp_Prag is
In_Assertion_Expr := In_Assertion_Expr - 1;
end Expand_Pragma_Contract_Cases;
+ -------------------------------------
+ -- Expand_Pragma_Exceptional_Cases --
+ -------------------------------------
+
+ -- Aspect Exceptional_Cases shoule be expanded in the following manner:
+
+ -- Original declaration
+
+ -- procedure P (...) with
+ -- Exceptional_Cases =>
+ -- (Exp_1 => True,
+ -- Exp_2 => Post_4);
+
+ -- Expanded body
+
+ -- procedure P (...) is
+ -- begin
+ -- -- normal body of of P
+ -- declare
+ -- ...
+ -- end;
+ --
+ -- exception
+ -- when Exp1 =>
+ -- pragma Assert (True);
+ -- raise;
+ -- when E : Exp2 =>
+ -- pragma Assert (Post_4);
+ -- raise;
+ -- when others =>
+ -- pragma Assert (False);
+ -- raise;
+ -- end P;
+
+ procedure Expand_Pragma_Exceptional_Cases (Prag : Node_Id) is
+ begin
+ -- Currently we don't expand this pragma
+
+ Rewrite (Prag, Make_Null_Statement (Sloc (Prag)));
+ end Expand_Pragma_Exceptional_Cases;
+
---------------------------------------
-- Expand_Pragma_Import_Or_Interface --
---------------------------------------
diff --git a/gcc/ada/exp_prag.ads b/gcc/ada/exp_prag.ads
index 27c537c..9f810da 100644
--- a/gcc/ada/exp_prag.ads
+++ b/gcc/ada/exp_prag.ads
@@ -42,6 +42,10 @@ package Exp_Prag is
-- Subp_Id's body. All generated code is added to list Stmts. If Stmts is
-- No_List on entry, a new list is created.
+ procedure Expand_Pragma_Exceptional_Cases (Prag : Node_Id);
+ -- Given pragma Exceptional_Cases Prag, create the circuitry needed to
+ -- catch exceptions and evaluate consequence expressions.
+
procedure Expand_Pragma_Initial_Condition
(Pack_Id : Entity_Id;
N : Node_Id);
diff --git a/gcc/ada/inline.adb b/gcc/ada/inline.adb
index b2ff7c9..b7dafde 100644
--- a/gcc/ada/inline.adb
+++ b/gcc/ada/inline.adb
@@ -315,6 +315,7 @@ package body Inline is
-- Contract_Cases
-- Global
-- Depends
+ -- Exceptional_Cases
-- Postcondition
-- Precondition
-- Refined_Global
@@ -5165,6 +5166,7 @@ package body Inline is
and then Chars (Item_Id) in Name_Contract_Cases
| Name_Global
| Name_Depends
+ | Name_Exceptional_Cases
| Name_Postcondition
| Name_Precondition
| Name_Refined_Global
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 4a3517d..ac50c84 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -1371,6 +1371,7 @@ begin
| Pragma_Elaboration_Checks
| Pragma_Eliminate
| Pragma_Enable_Atomic_Synchronization
+ | Pragma_Exceptional_Cases
| Pragma_Export
| Pragma_Export_Function
| Pragma_Export_Object
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 91a1fad..b8cd160 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -263,7 +263,8 @@ package body Sem_Ch12 is
-- package subprogram [body]
-- Abstract_State Contract_Cases
-- Initial_Condition Depends
- -- Initializes Extensions_Visible
+ -- Initializes Exceptional_Cases
+ -- Extensions_Visible
-- Global
-- package body Post
-- Refined_State Post_Class
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 983f877..d40c70f 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -1410,6 +1410,7 @@ package body Sem_Ch13 is
-- Attach_Handler
-- Contract_Cases
-- Depends
+ -- Exceptional_Cases
-- Ghost
-- Global
-- Initial_Condition
@@ -1666,10 +1667,10 @@ package body Sem_Ch13 is
-- analyzed right now.
-- Note that there is a special handling for Pre, Post, Test_Case,
- -- Contract_Cases and Subprogram_Variant aspects. In these cases, we do
- -- not have to worry about delay issues, since the pragmas themselves
- -- deal with delay of visibility for the expression analysis. Thus, we
- -- just insert the pragma after the node N.
+ -- Contract_Cases, Exceptional_Cases and Subprogram_Variant aspects.
+ -- In these cases, we do not have to worry about delay issues, since the
+ -- pragmas themselves deal with delay of visibility for the expression
+ -- analysis. Thus, we just insert the pragma after the node N.
-- Loop through aspects
@@ -4287,8 +4288,9 @@ package body Sem_Ch13 is
-- Case 4: Aspects requiring special handling
- -- Pre/Post/Test_Case/Contract_Cases/Subprogram_Variant whose
- -- corresponding pragmas take care of the delay.
+ -- Pre/Post/Test_Case/Contract_Cases/Exceptional_Cases and
+ -- Subprogram_Variant whose corresponding pragmas take care
+ -- of the delay.
-- Pre/Post
@@ -4520,6 +4522,19 @@ package body Sem_Ch13 is
Insert_Pragma (Aitem);
goto Continue;
+ -- Exceptional_Cases
+
+ when Aspect_Exceptional_Cases =>
+ Aitem := Make_Aitem_Pragma
+ (Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression => Relocate_Node (Expr))),
+ Pragma_Name => Name_Exceptional_Cases);
+
+ Decorate (Aspect, Aitem);
+ Insert_Pragma (Aitem);
+ goto Continue;
+
-- Subprogram_Variant
when Aspect_Subprogram_Variant =>
@@ -11280,6 +11295,7 @@ package body Sem_Ch13 is
| Aspect_Depends
| Aspect_Dimension
| Aspect_Dimension_System
+ | Aspect_Exceptional_Cases
| Aspect_Effective_Reads
| Aspect_Effective_Writes
| Aspect_Extensions_Visible
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index d80f78f..963c6de 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -2105,6 +2105,298 @@ package body Sem_Prag is
end Analyze_Depends_In_Decl_Part;
--------------------------------------------
+ -- Analyze_Exceptional_Cases_In_Decl_Part --
+ --------------------------------------------
+
+ -- WARNING: This routine manages Ghost regions. Return statements must be
+ -- replaced by gotos which jump to the end of the routine and restore the
+ -- Ghost mode.
+
+ procedure Analyze_Exceptional_Cases_In_Decl_Part
+ (N : Node_Id;
+ Freeze_Id : Entity_Id := Empty)
+ is
+ Subp_Decl : constant Node_Id := Find_Related_Declaration_Or_Body (N);
+ Spec_Id : constant Entity_Id := Unique_Defining_Entity (Subp_Decl);
+
+ procedure Analyze_Exceptional_Contract (Exceptional_Contract : Node_Id);
+ -- Verify the legality of a single exceptional contract
+
+ procedure Check_Duplication (Id : Node_Id; Contracts : List_Id);
+ -- Iterate through the identifiers in each contract to find duplicates
+
+ ----------------------------------
+ -- Analyze_Exceptional_Contract --
+ ----------------------------------
+
+ procedure Analyze_Exceptional_Contract (Exceptional_Contract : Node_Id)
+ is
+ Exception_Choice : Node_Id;
+ Consequence : Node_Id;
+ Errors : Nat;
+
+ begin
+ if Nkind (Exceptional_Contract) /= N_Component_Association then
+ Error_Msg_N
+ ("wrong syntax in exceptional contract", Exceptional_Contract);
+ return;
+ end if;
+
+ Exception_Choice := First (Choices (Exceptional_Contract));
+ Consequence := Expression (Exceptional_Contract);
+
+ while Present (Exception_Choice) loop
+ if Nkind (Exception_Choice) = N_Others_Choice then
+ if Present (Next (Exception_Choice))
+ or else Present (Next (Exceptional_Contract))
+ or else Present (Prev (Exception_Choice))
+ then
+ Error_Msg_N
+ ("OTHERS must appear alone and last", Exception_Choice);
+ end if;
+
+ else
+ Analyze (Exception_Choice);
+
+ if Is_Entity_Name (Exception_Choice)
+ and then Ekind (Entity (Exception_Choice)) = E_Exception
+ then
+ if Present (Renamed_Entity (Entity (Exception_Choice)))
+ and then Entity (Exception_Choice) = Standard_Numeric_Error
+ then
+ Check_Restriction
+ (No_Obsolescent_Features, Exception_Choice);
+
+ if Warn_On_Obsolescent_Feature then
+ Error_Msg_N
+ ("Numeric_Error is an obsolescent feature " &
+ "(RM J.6(1))?j?",
+ Exception_Choice);
+ Error_Msg_N
+ ("\use Constraint_Error instead?j?",
+ Exception_Choice);
+ end if;
+ end if;
+
+ Check_Duplication
+ (Exception_Choice, List_Containing (Exceptional_Contract));
+
+ -- Check for exception declared within generic formal
+ -- package (which is illegal, see RM 11.2(8)).
+
+ declare
+ Ent : Entity_Id := Entity (Exception_Choice);
+ Scop : Entity_Id;
+
+ begin
+ if Present (Renamed_Entity (Ent)) then
+ Ent := Renamed_Entity (Ent);
+ end if;
+
+ Scop := Scope (Ent);
+ while Scop /= Standard_Standard
+ and then Ekind (Scop) = E_Package
+ loop
+ if Nkind (Declaration_Node (Scop)) =
+ N_Package_Specification
+ and then
+ Nkind (Original_Node (Parent
+ (Declaration_Node (Scop)))) =
+ N_Formal_Package_Declaration
+ then
+ Error_Msg_NE
+ ("exception& is declared in generic formal "
+ & "package", Exception_Choice, Ent);
+ Error_Msg_N
+ ("\and therefore cannot appear in contract "
+ & "(RM 11.2(8))", Exception_Choice);
+ exit;
+
+ -- If the exception is declared in an inner instance,
+ -- nothing else to check.
+
+ elsif Is_Generic_Instance (Scop) then
+ exit;
+ end if;
+
+ Scop := Scope (Scop);
+ end loop;
+ end;
+ else
+ Error_Msg_N ("exception name expected", Exception_Choice);
+ end if;
+ end if;
+
+ Next (Exception_Choice);
+ end loop;
+
+ -- Now analyze the expressions of this contract
+
+ Errors := Serious_Errors_Detected;
+
+ -- Preanalyze_Assert_Expression, but without enforcing any of the two
+ -- acceptable types.
+
+ Preanalyze_Assert_Expression (Consequence, Any_Boolean);
+
+ -- Emit a clarification message when the consequence contains at
+ -- least one undefined reference, possibly due to contract freezing.
+
+ if Errors /= Serious_Errors_Detected
+ and then Present (Freeze_Id)
+ and then Has_Undefined_Reference (Consequence)
+ then
+ Contract_Freeze_Error (Spec_Id, Freeze_Id);
+ end if;
+ end Analyze_Exceptional_Contract;
+
+ -----------------------
+ -- Check_Duplication --
+ -----------------------
+
+ procedure Check_Duplication (Id : Node_Id; Contracts : List_Id) is
+ Contract : Node_Id;
+ Id1 : Node_Id;
+ Id_Entity : Entity_Id := Entity (Id);
+
+ begin
+ if Present (Renamed_Entity (Id_Entity)) then
+ Id_Entity := Renamed_Entity (Id_Entity);
+ end if;
+
+ Contract := First (Contracts);
+ while Present (Contract) loop
+ Id1 := First (Choices (Contract));
+ while Present (Id1) loop
+
+ -- Only check against the exception choices which precede
+ -- Id in the contract, since the ones that follow Id have not
+ -- been analyzed yet and will be checked in a subsequent call.
+
+ if Id = Id1 then
+ return;
+
+ -- Duplication both simple and via a renaming across different
+ -- exceptional contracts is illegal.
+
+ elsif Nkind (Id1) /= N_Others_Choice
+ and then
+ (Id_Entity = Entity (Id1)
+ or else Id_Entity = Renamed_Entity (Entity (Id1)))
+ and then Contract /= Parent (Id)
+ then
+ Error_Msg_Sloc := Sloc (Id1);
+ Error_Msg_NE ("exception choice duplicates &#", Id, Id1);
+ end if;
+
+ Next (Id1);
+ end loop;
+
+ Next (Contract);
+ end loop;
+ end Check_Duplication;
+
+ -- Local variables
+
+ Exceptional_Contracts : constant Node_Id :=
+ Expression (Get_Argument (N, Spec_Id));
+
+ Saved_GM : constant Ghost_Mode_Type := Ghost_Mode;
+ Saved_IGR : constant Node_Id := Ignored_Ghost_Region;
+ -- Save the Ghost-related attributes to restore on exit
+
+ Exceptional_Contract : Node_Id;
+ Restore_Scope : Boolean := False;
+
+ -- Start of processing for Analyze_Subprogram_Variant_In_Decl_Part
+
+ begin
+ -- Do not analyze the pragma multiple times
+
+ if Is_Analyzed_Pragma (N) then
+ return;
+ end if;
+
+ -- Set the Ghost mode in effect from the pragma. Due to the delayed
+ -- analysis of the pragma, the Ghost mode at point of declaration and
+ -- point of analysis may not necessarily be the same. Use the mode in
+ -- effect at the point of declaration.
+
+ Set_Ghost_Mode (N);
+
+ -- Single and multiple contracts must appear in aggregate form. If this
+ -- is not the case, then either the parser of the analysis of the pragma
+ -- failed to produce an aggregate, e.g. when the contract is "null" or a
+ -- "(null record)".
+
+ pragma Assert
+ (if Nkind (Exceptional_Contracts) = N_Aggregate
+ then Null_Record_Present (Exceptional_Contracts)
+ xor (Present (Component_Associations (Exceptional_Contracts))
+ or
+ Present (Expressions (Exceptional_Contracts)))
+ else Nkind (Exceptional_Contracts) = N_Null);
+
+ -- Only clauses of the following form are allowed:
+ --
+ -- exceptional_contract ::=
+ -- [choice_parameter_specification:]
+ -- exception_choice {'|' exception_choice} => consequence
+ --
+ -- where
+ --
+ -- consequence ::= Boolean_expression
+
+ if Nkind (Exceptional_Contracts) = N_Aggregate
+ and then Present (Component_Associations (Exceptional_Contracts))
+ and then No (Expressions (Exceptional_Contracts))
+ then
+
+ -- Check that the expression is a proper aggregate (no parentheses)
+
+ if Paren_Count (Exceptional_Contracts) /= 0 then
+ Error_Msg_F -- CODEFIX
+ ("redundant parentheses", Exceptional_Contracts);
+ end if;
+
+ -- Ensure that the formal parameters are visible when analyzing all
+ -- clauses. This falls out of the general rule of aspects pertaining
+ -- to subprogram declarations.
+
+ if not In_Open_Scopes (Spec_Id) then
+ Restore_Scope := True;
+ Push_Scope (Spec_Id);
+
+ if Is_Generic_Subprogram (Spec_Id) then
+ Install_Generic_Formals (Spec_Id);
+ else
+ Install_Formals (Spec_Id);
+ end if;
+ end if;
+
+ Exceptional_Contract :=
+ First (Component_Associations (Exceptional_Contracts));
+ while Present (Exceptional_Contract) loop
+ Analyze_Exceptional_Contract (Exceptional_Contract);
+ Next (Exceptional_Contract);
+ end loop;
+
+ if Restore_Scope then
+ End_Scope;
+ end if;
+
+ -- Otherwise the pragma is illegal
+
+ else
+ Error_Msg_N ("wrong syntax for exceptional cases", N);
+ end if;
+
+ Set_Is_Analyzed_Pragma (N);
+
+ Restore_Ghost_Region (Saved_GM, Saved_IGR);
+ end Analyze_Exceptional_Cases_In_Decl_Part;
+
+ --------------------------------------------
-- Analyze_External_Property_In_Decl_Part --
--------------------------------------------
@@ -16280,6 +16572,142 @@ package body Sem_Prag is
GNAT_Pragma;
Process_Disable_Enable_Atomic_Sync (Name_Unsuppress);
+ -----------------------
+ -- Exceptional_Cases --
+ -----------------------
+
+ -- pragma Exceptional_Cases ( EXCEPTIONAL_CONTRACT_LIST );
+
+ -- EXCEPTIONAL_CONTRACT_LIST ::=
+ -- ( EXCEPTIONAL_CONTRACT {, EXCEPTIONAL_CONTRACT })
+
+ -- EXCEPTIONAL_CONTRACT ::=
+ -- EXCEPTION_CHOICE {'|' EXCEPTION_CHOICE} => CONSEQUENCE
+ --
+ -- where
+ --
+ -- CONSEQUENCE ::= boolean_EXPRESSION
+
+ -- Characteristics:
+
+ -- * Analysis - The annotation undergoes initial checks to verify
+ -- the legal placement and context. Secondary checks preanalyze the
+ -- expressions in:
+
+ -- Analyze_Exceptional_Cases_In_Decl_Part
+
+ -- * Expansion - The annotation is expanded during the expansion of
+ -- the related subprogram [body] contract as performed in:
+
+ -- Expand_Subprogram_Contract
+
+ -- * Template - The annotation utilizes the generic template of the
+ -- related subprogram [body] when it is:
+
+ -- aspect on subprogram declaration
+ -- aspect on stand-alone subprogram body
+ -- pragma on stand-alone subprogram body
+
+ -- The annotation must prepare its own template when it is:
+
+ -- pragma on subprogram declaration
+
+ -- * Globals - Capture of global references must occur after full
+ -- analysis.
+
+ -- * Instance - The annotation is instantiated automatically when
+ -- the related generic subprogram [body] is instantiated except for
+ -- the "pragma on subprogram declaration" case. In that scenario
+ -- the annotation must instantiate itself.
+
+ when Pragma_Exceptional_Cases => Exceptional_Cases : declare
+ Spec_Id : Entity_Id;
+ Subp_Decl : Node_Id;
+ Subp_Spec : Node_Id;
+
+ begin
+ GNAT_Pragma;
+ Check_No_Identifiers;
+ Check_Arg_Count (1);
+
+ -- Ensure the proper placement of the pragma. Exceptional_Cases
+ -- must be associated with a subprogram declaration or a body that
+ -- acts as a spec.
+
+ Subp_Decl :=
+ Find_Related_Declaration_Or_Body (N, Do_Checks => True);
+
+ -- Generic subprogram
+
+ if Nkind (Subp_Decl) = N_Generic_Subprogram_Declaration then
+ null;
+
+ -- Body acts as spec
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Body
+ and then No (Corresponding_Spec (Subp_Decl))
+ then
+ null;
+
+ -- Body stub acts as spec
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Body_Stub
+ and then No (Corresponding_Spec_Of_Stub (Subp_Decl))
+ then
+ null;
+
+ -- Subprogram
+
+ elsif Nkind (Subp_Decl) = N_Subprogram_Declaration then
+ Subp_Spec := Specification (Subp_Decl);
+
+ -- Pragma Exceptional_Cases is forbidden on null procedures,
+ -- as this may lead to potential ambiguities in behavior when
+ -- interface null procedures are involved. Also, it just
+ -- wouldn't make sense, because null procedures do not raise
+ -- exceptions.
+
+ if Nkind (Subp_Spec) = N_Procedure_Specification
+ and then Null_Present (Subp_Spec)
+ then
+ Error_Msg_N (Fix_Error
+ ("pragma % cannot apply to null procedure"), N);
+ return;
+ end if;
+
+ else
+ Pragma_Misplaced;
+ end if;
+
+ Spec_Id := Unique_Defining_Entity (Subp_Decl);
+
+ -- A pragma that applies to a Ghost entity becomes Ghost for the
+ -- purposes of legality checks and removal of ignored Ghost code.
+
+ Mark_Ghost_Pragma (N, Spec_Id);
+ Ensure_Aggregate_Form (Get_Argument (N, Spec_Id));
+
+ -- Chain the pragma on the contract for further processing by
+ -- Analyze_Subprogram_Variant_In_Decl_Part.
+
+ Add_Contract_Item (N, Defining_Entity (Subp_Decl));
+
+ -- Fully analyze the pragma when it appears inside a subprogram
+ -- body because it cannot benefit from forward references.
+
+ if Nkind (Subp_Decl) in N_Subprogram_Body
+ | N_Subprogram_Body_Stub
+ then
+ -- The legality checks of pragma Subprogram_Variant are
+ -- affected by the SPARK mode in effect and the volatility
+ -- of the context. Analyze all pragmas in a specific order.
+
+ Analyze_If_Present (Pragma_SPARK_Mode);
+ Analyze_If_Present (Pragma_Volatile_Function);
+ Analyze_Subprogram_Variant_In_Decl_Part (N);
+ end if;
+ end Exceptional_Cases;
+
------------
-- Export --
------------
@@ -31580,6 +32008,7 @@ package body Sem_Prag is
Pragma_Elaboration_Checks => 0,
Pragma_Eliminate => 0,
Pragma_Enable_Atomic_Synchronization => 0,
+ Pragma_Exceptional_Cases => -1,
Pragma_Export => -1,
Pragma_Export_Function => -1,
Pragma_Export_Object => -1,
diff --git a/gcc/ada/sem_prag.ads b/gcc/ada/sem_prag.ads
index fa7e707..993ff7a 100644
--- a/gcc/ada/sem_prag.ads
+++ b/gcc/ada/sem_prag.ads
@@ -138,6 +138,7 @@ package Sem_Prag is
Pragma_Compile_Time_Error => True,
Pragma_Contract_Cases => True,
Pragma_Default_Initial_Condition => True,
+ Pragma_Exceptional_Cases => True,
Pragma_Initial_Condition => True,
Pragma_Invariant => True,
Pragma_Loop_Invariant => True,
@@ -247,6 +248,13 @@ package Sem_Prag is
-- Perform full analysis of delayed pragma Depends. This routine is also
-- capable of performing basic analysis of pragma Refined_Depends.
+ procedure Analyze_Exceptional_Cases_In_Decl_Part
+ (N : Node_Id;
+ Freeze_Id : Entity_Id := Empty);
+ -- Perform full analysis of delayed pragma Exceptional_Cases. Freeze_Id is
+ -- the entity of [generic] package body or [generic] subprogram body which
+ -- caused "freezing" of the related contract where the pragma resides.
+
procedure Analyze_External_Property_In_Decl_Part
(N : Node_Id;
Expr_Val : out Boolean);
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 9a0197c..b28f289 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -20576,6 +20576,7 @@ package body Sem_Util is
return Nam = Name_Contract_Cases
or else Nam = Name_Depends
+ or else Nam = Name_Exceptional_Cases
or else Nam = Name_Extensions_Visible
or else Nam = Name_Global
or else Nam = Name_Post
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 253d1da..4028d37 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -2343,6 +2343,7 @@ package Sem_Util is
-- following subprogram contract annotations:
-- Contract_Cases
-- Depends
+ -- Exceptional_Cases
-- Extensions_Visible
-- Global
-- Post
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index b0ac6f9..e6a27e6 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -7963,8 +7963,8 @@ package Sinfo is
-- operation) are also in this list.
-- Contract_Test_Cases contains a collection of pragmas that correspond
- -- to aspects/pragmas Contract_Cases, Test_Case and Subprogram_Variant.
- -- The ordering in the list is in LIFO fashion.
+ -- to aspects/pragmas Contract_Cases, Exceptional_Cases, Test_Case and
+ -- Subprogram_Variant. The ordering in the list is in LIFO fashion.
-- Classifications contains pragmas that either declare, categorize, or
-- establish dependencies between subprogram or package inputs and
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index cf2efbb..9868d97 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -552,6 +552,7 @@ package Snames is
Name_Elaborate : constant Name_Id := N + $; -- Ada 83
Name_Elaborate_All : constant Name_Id := N + $;
Name_Elaborate_Body : constant Name_Id := N + $;
+ Name_Exceptional_Cases : constant Name_Id := N + $; -- GNAT
Name_Export : constant Name_Id := N + $;
Name_Export_Function : constant Name_Id := N + $; -- GNAT
Name_Export_Object : constant Name_Id := N + $; -- GNAT
@@ -1848,6 +1849,7 @@ package Snames is
Pragma_Elaborate,
Pragma_Elaborate_All,
Pragma_Elaborate_Body,
+ Pragma_Exceptional_Cases,
Pragma_Export,
Pragma_Export_Function,
Pragma_Export_Object,