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] New access-before-elaboration mechanism


This patch reimplements access-before-elaboration (ABE) checks from scratch.
The ABE mechanism has the following objectives:

   * Diagnose at compile-time or install a run-time check to prevent ABE access
     to data and behaviour.

   * Supply a partial elaboration order for a unit to bind.

The ABE mechanism supports three models of elaboration:

   * Dynamic model - This is the most permissive of the three models. When the
     dynamic model is in effect, the mechanism performs very little diagnostics
     and relies on generated run-time checks to detect ABE issues. This model
     is enabled with switch -gnatE.

   * Static model - This is the middle ground of the three models. When the
     static model is in effect, the mechanism diagnoses and installs run-time
     checks to detect ABE issues in the main unit. In addition, the mechanism
     generates implicit Elaborate or Elaborate_All pragmas to ensure the prior
     elaboration of withed units. The model employs textual order, with clause
     context, and elaboration-related source pragmas. This is the default
     model.

   * SPARK model - This is the most conservative of the three models and
     impelements the semantics defined in SPARK RM 7.7. The SPARK model is in
     effect only when a context resides in a SPARK_Mode On region, otherwise
     the mechanism falls back to one of the previous models.

The ABE mechanism consists of a "recording" phase and a "processing" phase.

The Recording phase coincides with the analysis/resolution phase of the
compiler. It has the following objectives:

  * Record all top level scenarios for examination by the Processing phase.

  * Detect and diagnose calls in preelaborable or pure units, including generic
    bodies.

  * Detect and diagnose guaranteed ABEs caused by instantiations and  calls.

The Processing phase is a separate pass which starts after instantiating and/or
inlining bodies, but before the removal of Ghost code. It has the following
objectives:

  * Examine all top level scenarios saved during the Recording phase.

  * Depending on the elaboration model in effect, perform the following
    actions:

       - Dynamic model - Diagnose conditional ABEs and install run-time
         conditional ABE checks.

       - SPARK model - Enforce the SPARK elaboration rules

       - Static model - Diagnose conditional ABEs, install run-time conditional
         ABE checks, and guarantee the elaboration of external units.

   * Examine nested scenarios

The new implementation employs the following architecture:

     +------------------------ Recording phase ---------------------------+
     |                                                                    |
     |              Record_Elaboration_Scenario                           |
     |                           |                                        |
     |                           +--> Check_Preelaborated_Call            |
     |                           |                                        |
     |                           +--> Process_Guaranteed_ABE              |
     |                           |                                        |
     +-------------------------  |  --------------------------------------+
                                 |
                                 |
                                 v
                       Top_Level_Scenarios
             +-----------+-----------+ .. +-----------+
             | Scenario1 | Scenario2 | .. | ScenarioN |
             +-----------+-----------+ .. +-----------+
                                 |
                                 |
     +-------------------------  |  --------------------------------------+
     |                           |                                        |
     |              Check_Elaboration_Scenarios                           |
     |                           |                                        |
     |                           v                                        |
     |       +----------- Process_Scenario <-----------+                  |
     |       |                                         |                  |
     |       +--> Process_Access               Is_Suitable_Scenario       |
     |       |                                         ^                  |
     |       +--> Process_Activation_Call --+          |                  |
     |       |                              +---> Traverse_Body           |
     |       +--> Process_Call -------------+                             |
     |       |                                                            |
     |       +--> Process_Instantiation                                   |
     |       |                                                            |
     |       +--> Process_Variable_Assignment                             |
     |       |                                                            |
     |       +--> Process_Variable_Reference                              |
     |                                                                    |
     +------------------------- Processing phase -------------------------+

Tests and diffs attached as compressed files.

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

2017-10-09  Hristian Kirtchev  <kirtchev@adacore.com>

	* atree.adb: Add new soft link Rewriting_Proc.
	(Rewrite): Invoke the subprogram attached to the rewriting soft link.
	(Set_Rewriting_Proc): New routine.
	* attree.ads: Add new access-to-subprogram type Rewrite_Proc.
	(Set_Rewriting_Proc): New routine.
	* checks.adb (Install_Primitive_Elaboration_Check): Use 'E' character
	for *E*laboration flag to maintain consistency with other elaboration
	flag generating subprograms.
	* debug.adb: Document the new usage of flag -gnatdL.
	* einfo.adb: Node19 is now used as Receiving_Entry.  Node39 is now used
	as Protected_Subprogram.  Flag148 is now used as
	Is_Elaboration_Checks_OK_Id.  Flag302 is now used as
	Is_Initial_Condition_Procedure.
	(Is_Elaboration_Checks_OK_Id): New routine.
	(Is_Initial_Condition_Procedure): New routine.
	(Protected_Subprogram): New routine.
	(Receiving_Entry): New routine.
	(SPARK_Pragma): Update assertion.
	(SPARK_Pragma_Inherited): Update assertion.
	(Suppress_Elaboration_Warnings): Removed.
	(Set_Is_Elaboration_Checks_OK_Id): New routine.
	(Set_Is_Initial_Condition_Procedure): New routine.
	(Set_Protected_Subprogram): New routine.
	(Set_Receiving_Entry): New routine.
	(Set_SPARK_Pragma): Update assertion.
	(Set_SPARK_Pragma_Inherited): Update assertion.
	(Write_Entity_Flags): Update the output for Flag148 and Flag302.
	(Write_Field19_Name): Add output for Receiving_Entry.
	(Write_Field39_Name): Add output for Protected_Subprogram.
	(Write_Field40_Name): Update the output for SPARK_Pragma.
	* einfo.ads: New attributes Is_Elaboration_Checks_OK_Id,
	Is_Initial_Condition_Procedure, Protected_Subprogram, Receiving_Entry.
	Remove attribute Suppress_Elaboration_Warnings.  Update the stricture
	of various entities.
	(Is_Elaboration_Checks_OK_Id): New routine along with pragma Inline.
	(Is_Initial_Condition_Procedure): New routine along with pragma Inline.
	(Protected_Subprogram): New routine along with pragma Inline.
	(Receiving_Entry): New routine along with pragma Inline.
	(Suppress_Elaboration_Warnings): Removed.
	(Set_Is_Elaboration_Checks_OK_Id): New routine along with pragma
	Inline.
	(Set_Is_Initial_Condition_Procedure): New routine along with pragma
	Inline.
	(Set_Protected_Subprogram): New routine along with pragma Inline.
	(Set_Receiving_Entry): New routine along with pragma Inline.
	(Set_Suppress_Elaboration_Warnings): Removed.
	* exp_ch3.adb (Build_Init_Procedure): Use name _Finalizer to maintain
	consistency with other finalizer generating subprograms.
	(Default_Initialize_Object): Mark the block which wraps the call to
	finalize as being part of initialization.
	* exp_ch7.adb (Expand_N_Package_Declaration): Directly expand pragma
	Initial_Condition.
	(Expand_N_Package_Body): Directly expand pragma Initial_Condition.
	(Next_Suitable_Statement): Update the comment on usage. Skip over call
	markers generated by the ABE mechanism.
	* exp_ch9.adb (Activation_Call_Loc): New routine.
	(Add_Accept): Link the accept procedure to the original entry.
	(Build_Protected_Sub_Specification): Link the protected or unprotected
	version to the original subprogram.
	(Build_Task_Activation_Call): Code cleanup. Use a source location which
	is very close to the "begin" or "end" keywords when generating the
	activation call.
	* exp_prag.adb (Expand_Pragma_Initial_Condition): Reimplemented.
	* exp_spark.adb (Expand_SPARK): Use Expand_SPARK_N_Loop_Statement to
	process loops.
	(Expand_SPARK_N_Loop_Statement): New routine.
	(Expand_SPARK_N_Object_Declaration): Code cleanup. Partially insert the
	call to the Default_Initial_Condition procedure.
	(Expand_SPARK_Op_Ne): Renamed to Expand_SPARK_N_Op_Ne.
	* exp_util.adb (Build_DIC_Procedure_Body): Capture the SPARK_Mode in
	effect.
	(Build_DIC_Procedure_Declaration): Capture the SPARK_Mode in effect.
	(Insert_Actions): Add processing for N_Call_Marker.
	(Kill_Dead_Code): Explicitly kill an elaboration scenario.
	* exp_util.ads (Make_Invariant_Call): Update the comment on usage.
	* frontend.adb: Initialize Sem_Elab. Process all saved top level
	elaboration scenarios for ABE issues.
	* gcc-interface/trans.c (gnat_to_gnu): Add processing for N_Call_Marker
	nodes.
	* lib.adb (Earlier_In_Extended_Unit): New variant.
	* sem.adb (Analyze): Ignore N_Call_Marker nodes.
	(Preanalysis_Active): New routine.
	* sem.ads (Preanalysis_Active): New routine.
	* sem_attr.adb (Analyze_Access_Attribute): Save certain
	elaboration-related attributes. Save the scenario for ABE processing.
	* sem_ch3.adb (Analyze_Object_Declaration): Save the SPARK mode in
	effect. Save certain elaboration-related attributes.
	* sem_ch5.adb (Analyze_Assignment): Save certain elaboration-related
	attributes. Save the scenario for ABE processing.
	* sem_ch6.adb (Analyze_Abstract_Subprogram_Declaration): Save the SPARK
	mode in effect. Save certain elaboration-related attributes.
	(Analyze_Subprogram_Body_Helper): Skip N_Call_Marker nodes when
	locating the first real statement.
	(Analyze_Subprogram_Declaration): Save the SPARK mode in effect. Save
	certain elaboration-related attributes.
	* sem_ch7.adb (Analyze_Package_Declaration): Do not suppress
	elaboration warnings.
	* sem_ch8.adb (Attribute_Renaming): Mark a subprogram body which was
	generated for purposes of wrapping an attribute used as a generic
	actual.
	(Find_Direct_Name): Save certain elaboration-related attributes. Save
	the scenario for ABE processing.
	(Find_Expanded_Name): Save certain elaboration-related attributes. Save
	the scenario for ABE processing.
	* sem_ch9.adb (Analyze_Entry_Declaration): Save certain
	elaboration-related attributes.
	(Analyze_Requeue): Save certain elaboration-related attributes. Save
	the scenario for ABE processing.
	(Analyze_Single_Task_Declaration): Save certain elaboration-related
	attributes.
	(Analyze_Task_Type_Declaration): Save certain elaboration-related
	attributes.
	* sem_ch12.adb (Analyze_Generic_Package_Declaration): Save certain
	elaboration-related attributes.
	(Analyze_Generic_Subprogram_Declaration): Save the SPARK mode in
	effect. Save certain elaboration-related attributes.
	(Analyze_Package_Instantiation): Save certain elaboration-related
	attributes.  Save the scenario for ABE processing. Create completing
	bodies in case the instantiation results in a guaranteed ABE.
	(Analyze_Subprogram_Instantiation): Save certain elaboration-related
	attributes Save the scenario for ABE processing. Create a completing
	body in case the instantiation results in a guaranteed ABE.
	(Provide_Completing_Bodies): New routine.
	* sem_elab.ads: Brand new implementation.
	* sem_prag.adb (Analyze_Pragma, cases Elaborate, Elaborate_All,
	Elaborate_Body): Do not suppress elaboration warnings.
	* sem_res.adb (Make_Call_Into_Operator): Set the parent field of the
	operator.
	(Resolve_Call): Save certain elaboration-related attributes. Save the
	scenario for ABE processing.
	(Resolve_Entity_Name): Do not perform any ABE processing here.
	(Resolve_Entry_Call): Inherit certain attributes from the original call.
	* sem_util.adb (Begin_Keyword_Location): New routine.
	(Defining_Entity): Update the parameter profile. Add processing for
	concurrent subunits that are rewritten as null statements.
	(End_Keyword_Location): New routine.
	(Find_Enclosing_Scope): New routine.
	(In_Instance_Visible_Part): Code cleanup.
	(In_Subtree): Update the parameter profile. Add new version.
	(Is_Preelaborable_Aggregate): New routine.
	(Is_Preelaborable_Construct): New routine.
	(Mark_Elaboration_Attributes): New routine.
	(Scope_Within): Update the parameter profile.
	(Scope_Within_Or_Same): Update the parameter profile.
	* sem_util.ads (Begin_Keyword_Location): New routine.
	(Defining_Entity): Update the parameter profile and the comment on
	usage.
	(End_Keyword_Location): New routine.
	(Find_Enclosing_Scope): New routine.
	(In_Instance_Visible_Part): Update the parameter profile.
	(In_Subtree): Update the parameter profile. Add new version.
	(Is_Preelaborable_Aggregate): New routine.
	(Is_Preelaborable_Construct): New routine.
	(Mark_Elaboration_Attributes): New routine.
	(Scope_Within): Update the parameter profile and the comment on usage.
	(Scope_Within_Or_Same): Update the parameter profile and the comment on
	usage.
	* sem_warn.adb (Check_Infinite_Loop_Warning): Use Has_Condition_Actions
	to determine whether a loop has meaningful condition actions.
	(Has_Condition_Actions): New routine.
	* sinfo.adb (ABE_Is_Certain): Removed.
	(Is_Declaration_Level_Node): New routine.
	(Is_Dispatching_Call): New routine.
	(Is_Elaboration_Checks_OK_Node): New routine.
	(Is_Initialization_Block): New routine.
	(Is_Known_Guaranteed_ABE): New routine.
	(Is_Recorded_Scenario): New routine.
	(Is_Source_Call): New routine.
	(Is_SPARK_Mode_On_Node): New routine.
	(No_Elaboration_Check): Removed.
	(Target): New routine.
	(Was_Attribute_Reference): New routine.
	(Set_ABE_Is_Certain): Removed.
	(Set_Is_Declaration_Level_Node): New routine.
	(Set_Is_Dispatching_Call): New routine.
	(Set_Is_Elaboration_Checks_OK_Node): New routine.
	(Set_Is_Initialization_Block): New routine.
	(Set_Is_Known_Guaranteed_ABE): New routine.
	(Set_Is_Recorded_Scenario): New routine.
	(Set_Is_Source_Call): New routine.
	(Set_Is_SPARK_Mode_On_Node): New routine.
	(Set_No_Elaboration_Check): Removed.
	(Set_Target): New routine.
	(Set_Was_Attribute_Reference): New routine.
	* sinfo.ads: Remove attribute ABE_Is_Certain.  Attribute
	Do_Discriminant_Check now utilizes Flag3.  Attribute
	No_Side_Effect_Removal now utilizes Flag17.  Add new node
	N_Call_Marker.  Update the structure of various nodes.
	(ABE_Is_Certain): Removed along with pragma Inline.
	(Is_Declaration_Level_Node): New routine along with pragma Inline.
	(Is_Dispatching_Call): New routine along with pragma Inline.
	(Is_Elaboration_Checks_OK_Node): New routine along with pragma Inline.
	(Is_Initialization_Block): New routine along with pragma Inline.
	(Is_Known_Guaranteed_ABE): New routine along with pragma Inline.
	(Is_Recorded_Scenario): New routine along with pragma Inline.
	(Is_Source_Call): New routine along with pragma Inline.
	(Is_SPARK_Mode_On_Node): New routine along with pragma Inline.
	(No_Elaboration_Check): Removed along with pragma Inline.
	(Target): New routine along with pragma Inline.
	(Was_Attribute_Reference): New routine along with pragma Inline.
	(Set_ABE_Is_Certain): Removed along with pragma Inline.
	(Set_Is_Declaration_Level_Node): New routine along with pragma Inline.
	(Set_Is_Dispatching_Call): New routine along with pragma Inline.
	(Set_Is_Elaboration_Checks_OK_Node): New routine along with pragma
	Inline.
	(Set_Is_Initialization_Block): New routine along with pragma Inline.
	(Set_Is_Known_Guaranteed_ABE): New routine along with pragma Inline.
	(Set_Is_Recorded_Scenario): New routine along with pragma Inline.
	(Set_Is_Source_Call): New routine along with pragma Inline.
	(Set_Is_SPARK_Mode_On_Node): New routine along with pragma Inline.
	(Set_No_Elaboration_Check): Removed along with pragma Inline.
	(Set_Target): New routine along with pragma Inline.
	(Set_Was_Attribute_Reference): New routine along with pragma Inline.
	* sprint.adb (Sprint_Node_Actual): Add an entry for N_Call_Marker.

Attachment: diffs.gz
Description: application/gzip

Attachment: tests.gz
Description: application/gzip


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