blob: c3dc5d677342b881c54f79a00919936db3aabda6 [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- C O N T R A C T S --
-- --
-- S p e c --
-- --
-- Copyright (C) 2015-2023, 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. --
-- --
------------------------------------------------------------------------------
-- This package contains routines that perform analysis and expansion of
-- various contracts.
with Types; use Types;
package Contracts is
procedure Add_Contract_Item (Prag : Node_Id; Id : Entity_Id);
-- Add pragma Prag to the contract of a constant, entry, entry family,
-- [generic] package, package body, protected unit, [generic] subprogram,
-- subprogram body, variable, task unit, or type denoted by Id.
-- The following are valid pragmas:
--
-- Abstract_State
-- Always_Terminates
-- Async_Readers
-- Async_Writers
-- Attach_Handler
-- Constant_After_Elaboration
-- Contract_Cases
-- Depends
-- Effective_Reads
-- Effective_Writes
-- Exceptional_Cases
-- Extensions_Visible
-- Global
-- Initial_Condition
-- Initializes
-- Interrupt_Handler
-- No_Caching
-- Part_Of
-- Postcondition
-- Precondition
-- Refined_Depends
-- Refined_Global
-- Refined_Post
-- Refined_States
-- Subprogram_Variant
-- Test_Case
-- Volatile_Function
procedure Analyze_Contracts (L : List_Id);
-- Analyze the contracts of all eligible constructs found in list L
procedure Analyze_Pragmas_In_Declarations (Body_Id : Entity_Id);
-- Perform early analysis of pragmas at the top of a given subprogram's
-- declarations.
--
-- The purpose of this is to analyze contract-related pragmas for later
-- processing, but also to handle other such pragmas before these
-- declarations get moved to an internal wrapper as part of contract
-- expansion. For example, pragmas Inline, Ghost, Volatile all need to
-- apply directly to the subprogram and not be moved to a wrapper.
procedure Analyze_Entry_Or_Subprogram_Body_Contract (Body_Id : Entity_Id);
-- Analyze all delayed pragmas chained on the contract of entry or
-- subprogram body Body_Id as if they appeared at the end of a declarative
-- region. Pragmas in question are:
--
-- Always_Terminates (stand alone subprogram body)
-- 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)
-- Refined_Depends
-- Refined_Global
-- Refined_Post
-- Subprogram_Variant (stand alone subprogram body)
-- Test_Case (stand alone subprogram body)
procedure Analyze_Entry_Or_Subprogram_Contract
(Subp_Id : Entity_Id;
Freeze_Id : Entity_Id := Empty);
-- Analyze all delayed pragmas chained on the contract of entry or
-- subprogram Subp_Id as if they appeared at the end of a declarative
-- region. The pragmas in question are:
--
-- Always_Terminates
-- Contract_Cases
-- Depends
-- Exceptional_Cases
-- Global
-- Postcondition
-- Precondition
-- Subprogram_Variant
-- Test_Case
--
-- Freeze_Id is the entity of a [generic] package body or a [generic]
-- subprogram body which "freezes" the contract of Subp_Id.
procedure Analyze_Object_Contract
(Obj_Id : Entity_Id;
Freeze_Id : Entity_Id := Empty);
-- Analyze all delayed pragmas chained on the contract of object Obj_Id as
-- if they appeared at the end of the declarative region. The pragmas to be
-- considered are:
--
-- Async_Readers
-- Async_Writers
-- Depends (single concurrent object)
-- Effective_Reads
-- Effective_Writes
-- Global (single concurrent object)
-- Part_Of
--
-- Freeze_Id is the entity of a [generic] package body or a [generic]
-- subprogram body which "freezes" the contract of Obj_Id.
procedure Analyze_Type_Contract (Type_Id : Entity_Id);
-- Analyze all delayed pragmas chained on the contract of object Obj_Id as
-- if they appeared at the end of the declarative region. The pragmas to be
-- considered are:
--
-- Async_Readers
-- Async_Writers
-- Effective_Reads
-- Effective_Writes
-- Postcondition
-- Precondition
--
-- In the case of a protected or task type, there will also be
-- a call to Analyze_Protected_Contract or Analyze_Task_Contract.
procedure Analyze_Package_Body_Contract
(Body_Id : Entity_Id;
Freeze_Id : Entity_Id := Empty);
-- Analyze all delayed pragmas chained on the contract of package body
-- Body_Id as if they appeared at the end of a declarative region. The
-- pragmas that are considered are:
--
-- Refined_State
--
-- Freeze_Id is the entity of a [generic] package body or a [generic]
-- subprogram body which "freezes" the contract of Body_Id.
procedure Analyze_Package_Contract (Pack_Id : Entity_Id);
-- Analyze all delayed pragmas chained on the contract of package Pack_Id
-- as if they appeared at the end of a declarative region. The pragmas
-- that are considered are:
--
-- Initial_Condition
-- Initializes
procedure Analyze_Protected_Contract (Prot_Id : Entity_Id);
-- Analyze all delayed pragmas chained on the contract of protected unit
-- Prot_Id if they appeared at the end of a declarative region. Currently
-- there are no such pragmas.
procedure Analyze_Subprogram_Body_Stub_Contract (Stub_Id : Entity_Id);
-- Analyze all delayed pragmas chained on the contract of subprogram body
-- stub Stub_Id as if they appeared at the end of a declarative region. The
-- pragmas in question are:
--
-- Always_Terminates
-- Contract_Cases
-- Depends
-- Exceptional_Cases
-- Global
-- Postcondition
-- Precondition
-- Refined_Depends
-- Refined_Global
-- Refined_Post
-- Subprogram_Variant
-- Test_Case
procedure Analyze_Task_Contract (Task_Id : Entity_Id);
-- Analyze all delayed pragmas chained on the contract of task unit Task_Id
-- as if they appeared at the end of a declarative region. The pragmas in
-- question are:
--
-- Depends
-- Global
procedure Build_Entry_Contract_Wrapper (E : Entity_Id; Decl : Node_Id);
-- Build the body of a wrapper procedure for an entry or entry family that
-- has contract cases, preconditions, or postconditions, and add it to the
-- freeze actions of the related synchronized type.
--
-- The body first verifies the preconditions and case guards of the
-- contract cases, then invokes the entry [family], and finally verifies
-- the postconditions and the consequences of the contract cases. E denotes
-- the entry family. Decl denotes the declaration of the enclosing
-- synchronized type.
procedure Create_Generic_Contract (Unit : Node_Id);
-- Create a contract node for a generic package, generic subprogram, or a
-- generic body denoted by Unit by collecting all source contract-related
-- pragmas in the contract of the unit.
procedure Freeze_Previous_Contracts (Body_Decl : Node_Id);
-- Freeze the contracts of all source constructs found in the declarative
-- list which contains entry, package, protected, subprogram, or task body
-- denoted by Body_Decl. In addition, freeze the contract of the nearest
-- enclosing package body.
procedure Inherit_Subprogram_Contract
(Subp : Entity_Id;
From_Subp : Entity_Id);
-- Inherit relevant contract items from source subprogram From_Subp. Subp
-- denotes the destination subprogram. The inherited items are:
-- Extensions_Visible
-- ??? it would be nice if this routine handles Pre'Class and Post'Class
procedure Instantiate_Subprogram_Contract (Templ : Node_Id; L : List_Id);
-- Instantiate all source pragmas found in the contract of the generic
-- subprogram declaration template denoted by Templ. The instantiated
-- pragmas are added to list L.
procedure Make_Class_Precondition_Subps
(Subp_Id : Entity_Id;
Late_Overriding : Boolean := False);
-- Build helpers that at run time evaluate statically and dynamically the
-- class-wide preconditions of Subp_Id; build also the indirect-call
-- wrapper (ICW) required to check class-wide preconditions when the
-- subprogram is invoked through an access-to-subprogram, or when it
-- overrides an inherited class-wide precondition (see AI12-0195-1).
-- Late_Overriding enables special handling required for late-overriding
-- subprograms.
--
-- For example, if we have a subprogram with the following profile:
--
-- procedure Prim (Obj : TagTyp; <additional formals>)
-- with Pre'Class => F1 (Obj) and F2(Obj)
--
-- We build the following helper that evaluates statically the class-wide
-- precondition:
--
-- function PrimSP (Obj : TagTyp) return Boolean is
-- begin
-- return F1 (Obj) and F2(Obj);
-- end PrimSP;
--
-- ... and the following helper that evaluates dynamically the class-wide
-- precondition:
--
-- function PrimDP (Obj : TagTyp'Class; ...) return Boolean is
-- begin
-- return F1 (Obj) and F2(Obj);
-- end PrimSP;
--
-- ... and the following indirect-call wrapper (ICW) that is used by the
-- code generated by the compiler for indirect calls:
--
-- procedure PrimICW (Obj : TagTyp; <additional formals> is
-- begin
-- if not PrimSP (Obj) then
-- $raise_assert_failure ("failed precondition in call at ...");
-- end if;
--
-- Prim (Obj, ...);
-- end Prim;
procedure Merge_Class_Conditions (Spec_Id : Entity_Id);
-- Merge and preanalyze all class-wide conditions of Spec_Id (class-wide
-- preconditions merged with operator or-else; class-wide postconditions
-- merged with operator and-then). Ignored pre/postconditions are also
-- merged since, although they are not required to generate code, their
-- preanalysis is required to perform semantic checks. Resulting merged
-- expressions are later installed by the expander in helper subprograms
-- which are invoked from the caller side; they are also used to build
-- the dispatch-table wrapper (DTW), if required.
procedure Preanalyze_Class_Conditions (Spec_Id : Entity_Id);
-- Preanalyze class-wide pre-/postconditions of the given subprogram
-- specification.
procedure Process_Class_Conditions_At_Freeze_Point (Typ : Entity_Id);
-- Merge, preanalyze, and check class-wide pre/postconditions of Typ
-- primitives.
procedure Save_Global_References_In_Contract
(Templ : Node_Id;
Gen_Id : Entity_Id);
-- Save all global references found within the aspect specifications and
-- the contract-related source pragmas assocated with generic template
-- Templ. Gen_Id denotes the entity of the analyzed generic copy.
end Contracts;