diff options
author | Ed Schonberg <schonberg@adacore.com> | 2018-08-21 14:49:34 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2018-08-21 14:49:34 +0000 |
commit | 0db1c3863d5167dd47e5a0ab4a714ace875a9202 (patch) | |
tree | c4a0ebe971f279ef50bb7d01b5146d9d0b097b64 /gcc/ada/contracts.adb | |
parent | 5b1c45479aa2fd573063e370005f0c377e8b888e (diff) | |
download | gcc-0db1c3863d5167dd47e5a0ab4a714ace875a9202.zip gcc-0db1c3863d5167dd47e5a0ab4a714ace875a9202.tar.gz gcc-0db1c3863d5167dd47e5a0ab4a714ace875a9202.tar.bz2 |
[Ada] Spurious crash on expression function as completion with contracts
This patch fixes a compiler abort on an expression function that is a
completion of a subprogram with preconditions. The problem is caused by
the presence of types in the precondition that are not frozen when the
subprogram body constructed for the expression function receives the
code that enforces the precondition. These types must be frozen before
the contract is expanded, so the freeze nodes for these types appear in
the proper scope. This is analogous to what is done with type references
that appear in the original expression of the expression function.
2018-08-21 Ed Schonberg <schonberg@adacore.com>
gcc/ada/
* sem_ch6.adb: Remove Freeze_Expr_Types.
* freeze.ads, freeze.adb (Freeze_Expr_Types): Moved from
sem_ch6.adb, and extended to handle other expressions that may
contain unfrozen types that must be frozen in their proper
scopes.
* contracts.adb (Analyze_Entry_Or_Subprogram_Contract): If the
contract is for the generated body of an expression function
that is a completion, traverse the expressions for pre- and
postconditions to freeze all types before adding the contract
code within the subprogram body.
gcc/testsuite/
* gnat.dg/expr_func6.adb, gnat.dg/expr_func6.ads: New testcase.
From-SVN: r263734
Diffstat (limited to 'gcc/ada/contracts.adb')
-rw-r--r-- | gcc/ada/contracts.adb | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb index 5577604..e70765a 100644 --- a/gcc/ada/contracts.adb +++ b/gcc/ada/contracts.adb @@ -32,6 +32,7 @@ with Errout; use Errout; with Exp_Prag; use Exp_Prag; with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; +with Freeze; use Freeze; with Namet; use Namet; with Nlists; use Nlists; with Nmake; use Nmake; @@ -47,6 +48,7 @@ with Sem_Prag; use Sem_Prag; with Sem_Util; use Sem_Util; with Sinfo; use Sinfo; with Snames; use Snames; +with Stand; use Stand; with Stringt; use Stringt; with SCIL_LL; use SCIL_LL; with Tbuild; use Tbuild; @@ -589,14 +591,40 @@ package body Contracts is if Skip_Assert_Exprs then null; - -- Otherwise analyze the pre/postconditions + -- Otherwise analyze the pre/postconditions. Their expressions + -- might include references to types that are not frozen yet, + -- in the case where the body is a rewritten expression function + -- that is a completion, so freeze all types within before + -- constructing the contract code. else - Prag := Pre_Post_Conditions (Items); - while Present (Prag) loop - Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id); - Prag := Next_Pragma (Prag); - end loop; + declare + Bod : Node_Id; + Freeze_Types : Boolean := False; + begin + if Present (Freeze_Id) then + Bod := Unit_Declaration_Node (Freeze_Id); + if Nkind (Bod) = N_Subprogram_Body + and then Was_Expression_Function (Bod) + and then Ekind (Subp_Id) = E_Function + and then Chars (Subp_Id) = Chars (Freeze_Id) + and then Subp_Id /= Freeze_Id + then + Freeze_Types := True; + end if; + end if; + + Prag := Pre_Post_Conditions (Items); + while Present (Prag) loop + if Freeze_Types then + Freeze_Expr_Types (Subp_Id, Standard_Boolean, + Expression (Corresponding_Aspect (Prag)), Bod); + end if; + + Analyze_Pre_Post_Condition_In_Decl_Part (Prag, Freeze_Id); + Prag := Next_Pragma (Prag); + end loop; + end; end if; -- Analyze contract-cases and test-cases |