AI12-0280 relaxes the "potentially unevaluated" restrictions on the use
of the Old attribute in postconditions. A complex attribute prefix is
allowed in cases that were previously forbidden if the conditions
governing whether the attribute value will be needed during evaluation
of the postcondition are "known on entry". In this newly-allowed case,
evaluation of the 'Old attribute prefix upon entry to the subprogram is
performed conditionally. It turns out that this is similar to something
that was already part of the implementation of the Contract_Cases
attribute, and that bugs having to do with 'Old attribute references in
Contract_Cases consequences are fixed by sharing code with this new
implementation via a new package Sem_Util.Old_Attr_Util.Indirect_Temps.
In particular, such an attribute reference would previously generate a
malformed tree if the subtype of the prefix was indefinite; for example,
we might previously have generated an illegal declaration like
"Temp123 : String;" .

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

        * sem_util.ads: Declare a new package, Old_Attr_Util, which in
        turn declares two more packages, Conditional_Evaluation and
        Indirect_Temps. Conditional_Evaluation provides a predicate for
        deciding whether a given 'Old attribute reference is eligible
        for conditional evaluation and, in the case where it is
        eligible, a function that constructs the Boolean-valued
        condition that is to be evaluated at run time in deciding
        whether to evaluate the attribute prefix.  Indirect_Temps
        provides support for declaring a temporary which is only
        initialized conditionally; more specifically, an access type and
        a variable of that type are declared (unconditionally) and then
        the variable is (conditionally) initialized with an allocator.
        The existence of the access type and the pointer variable is
        hidden from clients, except that a predicate,
        Is_Access_Type_For_Indirect_Temp, is provided for identifying
        such access types. This is needed because we want such an access
        type to be treated like a "normal" access type (specifically
        with respect to finalization of allocated objects). Other parts
        of the compiler treat access types differently if
        Comes_From_Source is False, or if the secondary stack storage
        pool is used; this predicate is used to disable this special
        treatment.
        * sem_attr.adb (Uneval_Old_Msg): Improve message text to reflect
        Ada202x changes.
        (Analyze_Attribute): A previously-illegal 'Old attribute
        reference is accepted in Ada2020 if it is eligible for
        conditional evaluation.
        * sem_res.adb (Valid_Conversion): Do not treat a rewritten 'Old
        attribute like other rewrite substitutions. This makes a
        difference, for example, in the case where we are generating the
        expansion of a membership test of the form "Saooaaat'Old in
        Named_Access_Type"; in this case Valid_Conversion needs to
        return True (otherwise the expansion will be False - see the
        call site in exp_ch4.adb).
        * exp_attr.adb (Expand_N_Attribute_Reference): When expanding a
        'Old attribute reference, test for the case where the reference
        is eligible for conditional evaluation. In that case, use the
        new "indirect temporary" mechanism provided by Sem_Util.
        * exp_prag.adb
        (Expand_Attributes_In_Consequence.Expand_Attributes): If
        Sem_Util.Indirect_Temp_Needed indicates that there could be
        correctness problems associated with the old expansion scheme
        for dealing with 'Old attributes in contract cases consequences,
        then we use the new "indirect temporary" mechanism provided by
        Sem_Util instead. We do not want to do this unconditionally.
        * sem_util.adb: Provide a body for the new Old_Attr_Util
        package. Further work is needed in several areas for
        correctness:
        - The function Is_Repeatedly_Evaluated does not deal with
        container aggregates yet.
        - The function Is_Known_On_Entry does not deal with interactions
        with the Global aspect.
        Each area where more work is needed is indicated with a "???"
        comment in the code; a more detailed description can be found
        there. Some optimization opportunties are similarly indicated
        with a "???" comment.
        * exp_ch3.adb (Freeze_Type): In deciding whether to generate
        expansion for the list controller of an access type, take the
        predicate Is_Access_Type_For_Indirect_Temp into account. If the
        predicate yields True, then generate the expansion.
        * exp_util.adb (Build_Allocate_Deallocate_Proc): We don't
        normally finalize allocated objects that are allocated on the
        secondary stack. Add an exception to this rule if the predicate
        Is_Access_Type_For_Indirect_Temp yields True.  As a result of
        this exception, we have to deal with the fact that gigi expects
        a different parameter profile if we are using the secondary
        stack pool; the Pool and Alignment parameters must be omitted in
        this case.

Attachment: patch.diff.gz
Description: application/gzip

Reply via email to