This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] Add support for Preconditions/Postconditions


Tested on i686-linux, committed on trunk

This patch implements precondition and postcondition pragmas,
which can appear either immediately after the subprogram spec,
or at the start of declarations in the subprogram body. They
are activated by default by -gnata, and finer control can be
obtained using a new pragma Check_Policy, using Precondition or
Postcondition as the check name. See Sem_Prag for
details of syntax of new pragmas.

The Check pragma is like pragma Assert but has an extra parameter at
the start which is an identifier for the category of assertions.
The corresponding Check_Policy pragma can turn assertions on or
off for a specified category.

This patch also implements attribute function'Result, which may
only be used within a postcondition condition.

In addition, to make room for needed stuff in entities, the
Obsolescent_Warning field has been removed and replaced by the
use of a table which is searched when necessary.

The following test program if compiled and run without -gnata
outputs:

First call succeeded
Second call succeeded
Third call succeeded

Compiled and run with -gnata, it outputs:

First call succeeded
Second call failed raising SYSTEM.ASSERTIONS.ASSERT_FAILURE
   Msg = Precondition failed at ppc_test1.adb:7
Third call failed raising SYSTEM.ASSERTIONS.ASSERT_FAILURE
   Msg = Postcondition failed at ppc_test1.adb:13

Here is the test program:

with Text_IO; use Text_IO;
with Ada.Exceptions; use Ada.Exceptions;
procedure PPC_Test1 is
   Global : Integer := 3;
   Adjust : Integer := 0;
   function qq return Integer;
   pragma Precondition (Global = 3 or else Global = 0);
   pragma Postcondition (QQ'Result > 3, "OK");
   pragma Postcondition (Global = Global'Old + 1);

   function qq return Integer is
      pragma Precondition (Global >= 3 or else Global = 0);
      pragma Postcondition (Global >= 4);
   begin
      Global := Global + 1;
      return Global + Adjust;
   end qq;

   Res : Integer;

begin
   begin
      Res := qq;
      Put_Line ("First call succeeded");
   exception
      when E : others =>
         Put_Line ("First call failed raising " & Exception_Name (E));
         Put_Line ("   Msg = " & Exception_Message (E));
   end;

   begin
      Res := qq;
      Put_Line ("Second call succeeded");
   exception
      when E : others =>
         Put_Line ("Second call failed raising " & Exception_Name (E));
         Put_Line ("   Msg = " & Exception_Message (E));
   end;

   begin
      Global := 0;
      Res := qq;
      Put_Line ("Third call succeeded");
  exception
      when E : others =>
         Put_Line ("Third call failed raising " & Exception_Name (E));
         Put_Line ("   Msg = " & Exception_Message (E));
   end;
end PPC_Test1;

2008-04-08  Robert Dewar  <dewar@adacore.com>
	    Bob Duff  <duff@adacore.com>
	    Gary Dismukes  <dismukes@adacore.com>
	    Ed Schonberg  <schonberg@adacore.com>

	* einfo.ads, einfo.adb: Minor reformatting.
	(Is_Discriminal): New subprogram.
	(Is_Prival): New subprogram.
	(Is_Protected_Component): New subprogram.
	(Is_Protected_Private): Removed.
	(Object_Ref, Set_Object_Ref): Removed.
	(Prival, Set_Prival): Change assertion.
	(Privals_Chain, Set_Privals_Chain): Removed.
	(Prival_Link, Set_Prival_Link): New subprogram.
	(Protected_Operation, Set_Protected_Operation): Removed.
	(Protection_Object, Set_Protection_Object): New subprogram.
	(Write_Field17_Name): Remove case for Object_Ref.
	(Write_Field20_Name): Add case for Prival_Link.
	(Write_Field22_Name): Remove case for Protected_Operation,
	Privals_Chain.
	Add case for Protection_Object.
	(Can_Use_Internal_Rep): Make this into a [base type only] attribute,
	so clients
	(Overlays_Constant): New flag
	(Is_Constant_Object): New predicate
	(Is_Standard_Character_Type): New predicate
	(Optimize_Alignment_Space): New flag
	(Optimize_Alignment_Time): New flag
	(Has_Postconditions): New flag
	(Obsolescent_Warrning): Field removed
	(Spec_PPC_List): New field
	(Relative_Deadline_Variable, Set_Relative_Deadline_Variable): Add
	subprograms to get and set the relative deadline associated to a task.

	* alloc.ads: Add entries for Obsolescent_Warnings table

	* exp_attr.adb (May_Be_External_Call): Account for the case where the
	Access attribute is part of a named parameter association.
	(Expand_Access_To_Protected_Op): Test for the attribute occurring
	within an init proc and use that directly as the scope rather than
	traversing up to the protected operation's enclosing scope. Only apply
	assertion on Is_Open_Scopes in the case the scope traversal is done.
	For the init proc case use the address of the first formal (_init) as
	the protected object reference.
	Implement Invalid_Value attribute
	(Expand_N_Attribute_Reference): Case Attribute_Unrestricted_Access.
	contents of the dispatch table there is no need to duplicate the
	itypes associated with record types (i.e. the implicit full view
	of private types).
	Implement Enum_Val attribute
	(Expand_N_Attribute_Reference, case Old): Properly handle appearence
	within _Postconditions procedure
	(Expand_N_Attribute_Reference, case Result): Implement new attribute

	* exp_ch5.adb (Expand_N_Simple_Return_Statement): Handle case in which
	a return statement calls a function that is not available in
	configurable runtime.
	(Analyze_If_Statement): don't optimize simple True/False cases in -O0
	(Expand_Non_Function_Return): Generate call to _Postconditions proc
	(Expand_Simple_Function_Return): Ditto

	* frontend.adb: Add call to Sem_Aux.Initialize

	* sem_aux.ads, sem_aux.adb: New file.

	* par-prag.adb: Add entries for pragmas Precondition/Postcondition
	Add new Pragma_Relative_Deadline.
	Add support for pragmas Check and Check_Policy

	* sem_attr.ads, sem_attr.adb (Check_Not_CPP_Type): New subprogram.
	(Check_Stream_Attribute): Add missing check (not allowed in CPP types)
	(Analyze_Attribute): In case of attributes 'Alignment and 'size add
	missing check because they are not allowed in CPP tagged types.
	Add Sure parameter to Note_Possible_Modification calls
	Add implementation of Invalid_Value attribute
	Implement new attribute Has_Tagged_Values
	Implement Enum_Val attribute
	(Analyze_Attribute, case Range): Set Name_Req True for prefix of
	generated attributes.
	(Analyze_Attribute, case Result): If prefix of the attribute is
	overloaded, it always resolves to the enclosing function.
	(Analyze_Attribute, case Result): Properly deal with analysis when
	Postconditions are not active.
	(Resolve_Attribute, case Result): Properly deal with appearence during
	preanalysis in spec.
	Add processing for attribute Result

	* sem_ch6.ads, sem_ch6.adb (Check_Overriding_Indicator): Code cleanup
	for operators.
	(Analyze_Subprogram_Body): Install private_with_clauses when the body
	acts as a spec.
	(Check_Inline_Pragma): recognize an inline pragma that appears within
	the subprogram body to which it applies.
	(Analyze_Function_Return): Check that type of the expression of a return
	statement in a function with a class-wide result is not declared at a
	deeper level than the function.
	(Process_PPCs): Deal with enabling/disabling, using PPC_Enabled flag
	(Verify_Overriding_Indicator): Handle properly subprogram bodies for
	user- defined operators.
	(Install_Formals): Moved to spec to allow use from Sem_Prag for
	analysis of precondition/postcondition pragmas.
	(Analyze_Subprogram_Body.Last_Real_Spec_Entity): New name for
	Last_Formal, along with lots of comments on what this is about
	(Analyze_Subprogram_Body): Fix case where we move entities from the
	spec to the body when there are no body entities (now possible with
	precondition and postcondition pragmas).
	(Process_PPCs): New procedure
	(Analyze_Subprogram_Body): Add call to Process_PPCs

	* sem_ch8.adb (Use_One_Type): refine warning on a redundant use_type
	clause.
	(Pop_Scope): Restore Check_Policy_List on scope exit
	(Push_Scope): Save Check_Policy_List on scope entry
	Change name In_Default_Expression      => In_Spec_Expression
	Change name Analyze_Per_Use_Expression => Preanalyze_Spec_Expression
	Change name Pre_Analyze_And_Resolve    => Preanalyze_And_Resolve
	(Analyze_Object_Renaming): Allow 'Reference as object
	(Analyze_Pragma, case Restriction_Warnings): Call GNAT_Pragma
	(Process_Restrictions_Or_Restriction_Warnings): Check for bad spelling
	of restriction identifier.
	Add Sure parameter to Note_Possible_Modication calls

	* sem_prag.ads, sem_prag.adb (Analyze_Pragma, case Stream_Convert):
	Don't check for primitive operations when calling Rep_Item_Too_Late.
	(Process_Import_Or_Interface): Do not place flag on formal
	subprograms.
	(Analyze_Pragma, case Export): If the entity is a deferred constant,
	propagate information to full view, which is the one elaborated by the
	back-end.
	(Make_Inline): the pragma is effective if it applies to an internally
	generated subprogram declaration for a body that carries the pragma.
	(Analyze_Pragma, case Optimize_Alignment): Set new flag
	Optimize_Alignment_Local.
	(Analyze_PPC_In_Decl_Part): New procedure
	(Get_Pragma_Arg): Moved to outer level
	(Check_Precondition_Postcondition): Change to allow new visibility
	rules for package spec
	(Analyze_Pragma, case Check_Policy): Change placement rules to be
	same as pragma Suppress/Unsuppress.
	Change name In_Default_Expression      => In_Spec_Expression
	Change name Analyze_Per_Use_Expression => Preanalyze_Spec_Expression
	Change name Pre_Analyze_And_Resolve    => Preanalyze_And_Resolve
	(Check_Precondition_Postcondition): Do proper visibility preanalysis
	for the case of these pragmas appearing in the spec.
	(Check_Enabled): New function
	(Initialize): New procedure
	(Tree_Read): New procedure
	(Tree_Write): New procedure
	(Check_Precondition_Postcondition): New procedure
	Implement pragmas Check and Check_Policy
	Merge Assert processing with Check

	* sem_warn.adb (Warn_On_Known_Condition): Handle pragma Check
	New warning flag -gnatw.e

	* sinfo.ads, sinfo.adb (Has_Relative_Deadline_Pragma): New function
	returning whether a task (or main procedure) has a pragma
	Relative_Deadline.
	(Set_Has_Relative_Deadline_Pragma): Procedure to indicate that a task
	(or main procedure) has a pragma Relative_Deadline.
	Add Next_Pragma field to N_Pragma node
	(PPC_Enabled): New flag
	(Next_Pragma): Now used for Pre/Postcondition processing

	* snames.h, snames.ads, snames.adb: New standard name
	Inherit_Source_Path
	Add entry for 'Invalid_Value attribute
	Add entry for new attribute Has_Tagged_Values
	Add entry for Enum_Val attribute
	Add new standard names Aggregate, Configuration and Library.
	Add _Postconditions
	Add _Result
	Add Pragma_Precondition
	Add Pragma_Postcondition
	Add Attribute_Result
	New standard name Archive_Builder_Append_Option
	(Preset_Names): Add _relative_deadline and relative_deadline definitions
	There was also a missing non_preemptive_within_priorities.
	(Get_Pragma_Id, Is_Pragma_Name): Add support for pragma
	Relative_Deadline.
	Add support for pragmas Check and Check_Policy

	* tree_gen.adb: Call Sem_Aux.Tree_Write

	* tree_in.adb: Call Sem_Aux.Tree_Read

	* exp_ch11.adb (Expand_N_Raise_Statement): New Build_Location calling
	sequence

	* exp_intr.adb (Expand_Source_Info): New Build_Location calling
	sequence

	* exp_prag.adb (Expand_Pragma_Relative_Deadline): New procedure.
	(Expand_N_Pragma): Call the appropriate procedure for expanding pragma
	Relative_Deadline.
	(Expand_Pragma_Check): New procedure

	* sinput.ads, sinput.adb (Build_Location_String): Now appends to name
	buffer.

	* sinfo.adb (PPC_Enabled): New flag

Attachment: difs.bz2
Description: BZip2 compressed data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]