aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-09-25 01:02:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-09-25 01:02:42 +0000
commit5055f108385c076346b3b279788dc0129549b11f (patch)
tree91456c9f0ec368308f734e6d649b046d57a19114 /gcc/ada
parent414925ab0cb8d0aea39cb3383b18f72f3ce887a0 (diff)
parent44eb8fa73bb53afa17e4d72b1c073d0e08a76866 (diff)
downloadgcc-5055f108385c076346b3b279788dc0129549b11f.zip
gcc-5055f108385c076346b3b279788dc0129549b11f.tar.gz
gcc-5055f108385c076346b3b279788dc0129549b11f.tar.bz2
Merge from trunk revision 264547.
From-SVN: r264554
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/ChangeLog324
-rw-r--r--gcc/ada/Make-generated.in10
-rw-r--r--gcc/ada/Makefile.rtl17
-rw-r--r--gcc/ada/checks.adb39
-rw-r--r--gcc/ada/checks.ads18
-rw-r--r--gcc/ada/contracts.adb45
-rw-r--r--gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst33
-rw-r--r--gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst31
-rw-r--r--gcc/ada/einfo.adb52
-rw-r--r--gcc/ada/einfo.ads50
-rw-r--r--gcc/ada/exp_aggr.adb34
-rw-r--r--gcc/ada/exp_attr.adb40
-rw-r--r--gcc/ada/exp_cg.adb9
-rw-r--r--gcc/ada/exp_ch6.adb5
-rw-r--r--gcc/ada/exp_ch7.adb7
-rw-r--r--gcc/ada/exp_ch9.adb62
-rw-r--r--gcc/ada/exp_unst.adb13
-rw-r--r--gcc/ada/exp_unst.ads2
-rw-r--r--gcc/ada/exp_util.adb18
-rw-r--r--gcc/ada/fe.h2
-rw-r--r--gcc/ada/freeze.adb209
-rw-r--r--gcc/ada/freeze.ads11
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in1
-rw-r--r--gcc/ada/gcc-interface/Makefile.in13
-rw-r--r--gcc/ada/gcc-interface/decl.c2
-rw-r--r--gcc/ada/gcc-interface/gigi.h4
-rw-r--r--gcc/ada/gcc-interface/trans.c30
-rw-r--r--gcc/ada/gcc-interface/utils.c2
-rw-r--r--gcc/ada/gnat_ugn.texi70
-rw-r--r--gcc/ada/gnatlink.adb6
-rw-r--r--gcc/ada/impunit.adb9
-rw-r--r--gcc/ada/itypes.adb2
-rw-r--r--gcc/ada/itypes.ads2
-rw-r--r--gcc/ada/layout.adb10
-rw-r--r--gcc/ada/lib-writ.adb22
-rw-r--r--gcc/ada/lib-xref-spark_specific.adb13
-rw-r--r--gcc/ada/lib-xref.ads5
-rw-r--r--gcc/ada/libgnarl/a-intnam__dragonfly.ads2
-rw-r--r--gcc/ada/libgnarl/s-osinte__dragonfly.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__dragonfly.ads2
-rw-r--r--gcc/ada/libgnarl/s-osinte__gnu.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__gnu.ads2
-rw-r--r--gcc/ada/libgnarl/s-osinte__hpux-dce.adb2
-rw-r--r--gcc/ada/libgnarl/s-osinte__hpux-dce.ads2
-rw-r--r--gcc/ada/libgnarl/s-taprop__hpux-dce.adb2
-rw-r--r--gcc/ada/libgnarl/s-taspri__hpux-dce.ads2
-rw-r--r--gcc/ada/libgnat/g-dynhta.adb834
-rw-r--r--gcc/ada/libgnat/g-dynhta.ads310
-rw-r--r--gcc/ada/libgnat/g-lists.adb635
-rw-r--r--gcc/ada/libgnat/g-lists.ads245
-rw-r--r--gcc/ada/libgnat/s-dfmkio.ads38
-rw-r--r--gcc/ada/libgnat/s-dfmopr.ads35
-rw-r--r--gcc/ada/libgnat/s-dgmgop.ads174
-rw-r--r--gcc/ada/libgnat/s-diflmk.ads34
-rw-r--r--gcc/ada/libgnat/s-digemk.ads396
-rw-r--r--gcc/ada/libgnat/s-dilomk.ads34
-rw-r--r--gcc/ada/libgnat/s-dimmks.ads363
-rw-r--r--gcc/ada/libgnat/s-dlmkio.ads38
-rw-r--r--gcc/ada/libgnat/s-dlmopr.ads35
-rw-r--r--gcc/ada/libgnat/s-dmotpr.ads141
-rw-r--r--gcc/ada/sa_messages.adb539
-rw-r--r--gcc/ada/sa_messages.ads267
-rw-r--r--gcc/ada/sem_attr.adb9
-rw-r--r--gcc/ada/sem_ch10.adb3
-rw-r--r--gcc/ada/sem_ch13.adb78
-rw-r--r--gcc/ada/sem_ch3.adb8
-rw-r--r--gcc/ada/sem_ch6.adb250
-rw-r--r--gcc/ada/sem_res.adb35
-rw-r--r--gcc/ada/sem_spark.adb3902
-rw-r--r--gcc/ada/sem_util.adb10
-rw-r--r--gcc/ada/sem_util.ads2
-rwxr-xr-xgcc/ada/set_targ.adb3
-rw-r--r--gcc/ada/sinfo.ads2
-rw-r--r--gcc/ada/sprint.adb9
-rw-r--r--gcc/ada/terminals.c9
-rw-r--r--gcc/ada/vxlink-bind.adb390
-rw-r--r--gcc/ada/vxlink-bind.ads87
-rw-r--r--gcc/ada/vxlink-link.adb194
-rw-r--r--gcc/ada/vxlink-link.ads63
-rw-r--r--gcc/ada/vxlink-main.adb81
-rw-r--r--gcc/ada/vxlink.adb288
-rw-r--r--gcc/ada/vxlink.ads68
82 files changed, 7053 insertions, 3796 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index c6f1911..e51a2a3 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,325 @@
+2018-09-24 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/87396
+ * fe.h (Get_Attribute_Definition_Clause): Use 'unsigned char' instead
+ of 'char' as the type of the second parameter.
+
+2018-09-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.rtl (arm% linux-gnueabi%): Always set EH_MECHANISM to -arm.
+
+2018-09-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/81103
+ * terminals.c: Do not include termio.h.
+
+2018-08-27 Martin Liska <mliska@suse.cz>
+
+ * gcc-interface/decl.c (update_profile): Use new function
+ fndecl_built_in_p and remove check for FUNCTION_DECL if
+ possible.
+ * gcc-interface/gigi.h (call_is_atomic_load): Likewise.
+ * gcc-interface/utils.c (gnat_pushdecl): Likewise.
+
+2018-08-23 Giuliano Belinassi <giuliano.belinassi@usp.br>
+
+ * exp_unst.ads: Fix typo 'exapnded' to 'expanded'.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * checks.adb, contracts.adb, exp_aggr.adb, exp_attr.adb,
+ exp_ch6.adb, exp_ch7.adb, exp_ch9.adb, exp_unst.adb,
+ exp_util.adb, freeze.adb, gnatlink.adb, layout.adb,
+ lib-writ.adb, lib-xref-spark_specific.adb, sem_ch13.adb,
+ sem_ch3.adb, sem_ch6.adb, sem_res.adb, sem_util.adb, sinfo.ads,
+ sprint.adb: Minor reformatting.
+
+2018-08-21 Jerome Lambourg <lambourg@adacore.com>
+
+ * vxlink-bind.adb, vxlink-bind.ads, vxlink-link.adb,
+ vxlink-link.ads, vxlink-main.adb, vxlink.adb, vxlink.ads: Add a
+ new tool vxlink to handle VxWorks constructors in DKMs.
+ * gcc-interface/Makefile.in: add rules to build vxlink
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Analyze_Subprogram_Body_Helper, Mask_Type):
+ Refine the handling of freezing types for expression functions
+ that are not completions, when analyzing the generated body for
+ the function: the body is inserted at the end of the enclosing
+ declarative part, and its analysis may freeze types declared in
+ the same scope that have not been frozen yet.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * 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.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * sem_ch10.adb: Remove the with and use clause for unit Ghost.
+ (Analyze_With_Clause): Do not mark a with clause which mentions
+ an ignored Ghost code for elimination.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * lib-writ.adb (Write_Unit_Information): Handle pragmas removed
+ by the expander.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Check_Synchronized_Overriding): The conformance
+ between an overriding protected operation and the overridden
+ abstract progenitor operation requires subtype conformance;
+ requiring equality of return types in the case of a function is
+ too restrictive and leads to spurious errors when the return
+ type is a generic actual.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch9.adb (Expand_N_Timed_Entry_Call,
+ Expand_Conditional_Entry_Call): Use Reset_Scopes_Of to set
+ properly the scope of all entities created in blocks generated
+ by the expansion of these constructs.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb (Build_Predicate_Functioss): Apply
+ Reset_Quantified_Variables_Scope after predicate function has
+ been analyzed, so that the scope can be reset on the generated
+ loop statements that have replaced the quantified expressions.
+
+2018-08-21 Bob Duff <duff@adacore.com>
+
+ * einfo.ads, einfo.adb (Private_View, Shadow_Entities): Remove
+ obsolete code.
+
+2018-08-21 Maroua Maalej <maalej@adacore.com>
+
+ * sem_spark.adb (Check_Call_Statement): Check global and formal
+ parameter permissions at call sites.
+ (Check_Callable_Body): Assume permissions on globals and
+ parameters depending on their modes then analyse the body
+ operations.
+ (Check_Declaration): Consider both deep (including elementary
+ access) object declarations and normal variables. First check
+ whether the deep object is of Ownership Aspec True or not, then,
+ depending on its initialization, assign the appropriate state.
+ Check related to non access type variables deal with
+ initialization value permissions.
+ (Check_Expression): Check nodes used in the expression being
+ analyzed.
+ (Check_Globals): Call by Check_Call_Statement to perform the
+ check on globals.
+ (Check_List): Call Check_Node on each element of the list.
+ (Check_Loop_Statement): Check the Iteration_Scheme and loop
+ statements.
+ (Check_Node): Main traversal procedure to check safe pointer usage.
+ (Check_Package_Body): Check subprogram's body.
+ (Check_Param_In): Take a formal and an actual parameter and
+ Check the permission of every in-mode parameter.
+ (Check_Param_Out): Take a formal and an actual parameter and
+ check the state of out-mode and in out-mode parameters.
+ (Check_Statement): Check statements other than procedure call.
+ (Get_Perm, Get_Perm_Or_Tree, Get_Perm_Tree): Find out the state
+ related to the given name.
+ (Is_Deep): Return True if an object is of access type or has
+ subfields of access type.
+ (Perm_Error, Perm_Error_Subprogram_End): Add an error message
+ whenever the found state on the given name is different from the
+ one expected (in the statement being analyzed).
+ (Process_Path): Given an operation and a current state, call
+ Perm_Error if there is any mismatch.
+ (Return_Declarations, Return_Globals, Return_The_Global): Check
+ the state of a given name at the end of the subprogram. These
+ procedures may change depending on how we shall finally deal
+ with globals and the rhs state in a move operation.
+ (Set_Perm_Extensions, Set_Perm_Prefixes_Borrow,
+ Set_Perm_Prefixes, Setup_Globals, Setup_Parameter_Or_Global,
+ Setup_Parameters): Set up the new states to the given node and
+ up and down the tree after an operation.
+ (Has_Ownership_Aspect_True): This function may disappear later
+ when the Ownership Aspect will be implemented in the FE.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Call): Resolve correctly a parameterless
+ call that returns an access type whose designated type is the
+ component type of an array, when the function has no defaulted
+ parameters.
+
+2018-08-21 Yannick Moy <moy@adacore.com>
+
+ * doc/gnat_ugn/building_executable_programs_with_gnat.rst:
+ Document entries of the target parametrization file.
+ * gnat_ugn.texi: Regenerate.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb: Set scope of elaboration flag for 'Access.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sprint.adb: Add guard on printing aspects.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * exp_cg.adb (Generate_CG_Output): Handle calls removed by the
+ expander.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * layout.adb: Do not set size of access subprogram if unnesting.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb: Remove warnings for access to subprograms when
+ unnesting is active.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Expand_Array_Aggregate): If the component type
+ is limited, the array must be constructed in place, so set flag
+ In_Place_Assign_OK_For_Declaration accordingly. This prevents
+ improper copying of an array of tasks during initialization.
+
+2018-08-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Call_to_gnu): Always suppress an
+ unchecked conversion around the actual for an In parameter
+ passed by copy.
+
+2018-08-21 Eric Botcazou <ebotcazou@adacore.com>
+
+ * exp_util.adb (Is_Possibly_Unaligned_Object): For the case of a
+ selected component inherited in a record extension and subject
+ to a representation clause, retrieve the position and size from
+ the original record component.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.ads, sem_util.adb (New_External_Entity): Type of
+ Suffix_Index must be Int, not Nat, so that a negative value can
+ be used to generate a unique name for an external object, as
+ specified in Tbuild.New_External_Name.
+ (Scope_Within): Handle private type whose completion is a
+ synchronized type (For unnesting).
+ * itypes.ads, itypes.adb (Create_Itype): Ditto
+ * sem_ch3.adb (Constrain_Corresponding_Record): Generate a
+ unique name for the created subtype, because there may be
+ several discriminated tasks present in the same scope, and each
+ needs its distinct corresponding record subtype.
+
+2018-08-21 Yannick Moy <moy@adacore.com>
+
+ * doc/gnat_ugn/gnat_and_program_execution.rst: Update
+ documentation of dimensionality analysis.
+ * gnat_ugn.texi: Regenerate.
+ * Makefile.rtl, impunit.adb: Consider the new units.
+ * libgnat/s-dfmkio.ads, libgnat/s-dfmopr.ads,
+ libgnat/s-diflmk.ads: New units based on Float.
+ * libgnat/s-dilomk.ads, libgnat/s-dlmkio.ads,
+ libgnat/s-dlmopr.ads: New units based on Long_Float.
+ * libgnat/s-dmotpr.ads: Rename to libgnat/s-dgmgop.ads and turn
+ into an instance of
+ System.Dim.Generic_Mks.Generic_Other_Prefixes.
+ * libgnat/s-dimmks.ads: Rename to libgnat/s-digemk.ads and turn
+ into an instance of System.Dim.Generic_Mks.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * impunit.adb: Add g-lists to the set of non-implementation
+ units.
+ * libgnat/g-lists.adb, libgnat/g-lists.ads: New unit.
+ * Makefile.rtl: Add g-lists to the set of non-tasking units.
+ * gcc-interface/Make-lang.in: Add g-lists to the set of files
+ used by gnat1.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_ch9.adb (Reset_Scopes): Do not recurse into type
+ declarations when resetting the scope of entities declared the
+ procedures generated for entry bodies and accept alternatives.
+ Use the entity of the procedure declaration, not its body, as
+ the new scope.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * einfo.adb (Elaboration_Entity): Include entries and entry
+ families in the set of legal entities.
+ (Elaboration_Entity_Required): Include entries and entry
+ families in the set of legal entities.
+ (Set_Elaboration_Entity): Include entries and entry families in
+ the set of legal entities.
+ (Set_Elaboration_Entity_Required): Include entries and entry
+ families in the set of legal entities.
+ (Write_Field13_Name): Update the output of attribute
+ Elaboration_Entity.
+ * einfo.ads: Attributes Elaboration_Entity and
+ Elaboration_Entity_Required now apply to entries and entry
+ families.
+
+2018-08-21 Arnaud Charlet <charlet@adacore.com>
+
+ * set_targ.adb: Mark some CodePeer message as Intentional.
+
+2018-08-21 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_res.adb (Resolve_Call): Force the freezing of an
+ expression function that is called to provide a default value
+ for a defaulted discriminant in an object initialization.
+
+2018-08-21 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * libgnat/g-dynhta.adb, libgnat/g-dynhta.ads: New package
+ Dynamic_HTable.
+
+2018-08-21 Javier Miranda <miranda@adacore.com>
+
+ * checks.ads (Determine_Range): Adding documentation.
+ * checks.adb (Determine_Range): Don't deal with enumerated types
+ with non-standard representation.
+ (Convert_And_Check_Range): For conversion of enumeration types
+ with non standard representation to an integer type perform a
+ direct conversion to the target integer type.
+
+2018-08-21 Piotr Trojanek <trojanek@adacore.com>
+
+ * lib-xref.ads, lib-xref-spark_specific.adb
+ (Enclosing_Subprogram_Or_Library_Package): Now roughtly works
+ for pragmas that come from aspect specifications.
+
+2018-08-21 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ * sa_messages.ads, sa_messages.adb: New source files.
+
+2018-08-03 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ Reverts
+ 2018-07-06 Jim Wilson <jimw@sifive.com>
+
+ * Make-generated.in (treeprs.ads): Use $(GNATMAKE) instead of gnatmake.
+ (einfo.h, sinfo.h, stamp-snames, stamp-nmake): Likewise.
+ * gcc-interface/Makefile.in (xoscons): Likewise.
+
+2018-07-31 Alexandre Oliva <oliva@adacore.com>
+ Olivier Hainque <hainque@adacore.com>
+
+ * gcc-interface/trans.c: Include debug.h.
+ (file_map): New static variable.
+ (gigi): Set it. Create decl_to_instance_map when needed.
+ (Subprogram_Body_to_gnu): Pass gnu_subprog_decl to...
+ (Sloc_to_locus): ... this. Add decl parm, map it to instance.
+ * gcc-interface/gigi.h (Sloc_to_locus): Adjust declaration.
+
2018-07-31 Arnaud Charlet <charlet@adacore.com>
* clean.adb, gnatchop.adb, gnatfind.adb, gnatls.adb,
@@ -60,7 +382,7 @@
2018-07-31 Eric Botcazou <ebotcazou@adacore.com>
- * libgnarl/s-osinte__solaris.ads (upad64_t): New private type.
+ * libgnarl/s-osinte__solaris.ads (upad64_t): New private type.
(mutex_t): Use it for 'lock' and 'data' components.
(cond_t): Likewise for 'data' and use single 'flags' component.
diff --git a/gcc/ada/Make-generated.in b/gcc/ada/Make-generated.in
index bdcb62c..757eaa8 100644
--- a/gcc/ada/Make-generated.in
+++ b/gcc/ada/Make-generated.in
@@ -28,21 +28,21 @@ $(ADA_GEN_SUBDIR)/treeprs.ads : $(ADA_GEN_SUBDIR)/treeprs.adt $(ADA_GEN_SUBDIR)/
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/treeprs
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/treeprs/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/treeprs
- (cd $(ADA_GEN_SUBDIR)/bldtools/treeprs; $(GNATMAKE) -q xtreeprs ; ./xtreeprs treeprs.ads )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/treeprs; gnatmake -q xtreeprs ; ./xtreeprs treeprs.ads )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/treeprs/treeprs.ads $(ADA_GEN_SUBDIR)/treeprs.ads
$(ADA_GEN_SUBDIR)/einfo.h : $(ADA_GEN_SUBDIR)/einfo.ads $(ADA_GEN_SUBDIR)/einfo.adb $(ADA_GEN_SUBDIR)/xeinfo.adb $(ADA_GEN_SUBDIR)/ceinfo.adb
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/einfo
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/einfo/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/einfo
- (cd $(ADA_GEN_SUBDIR)/bldtools/einfo; $(GNATMAKE) -q xeinfo ; ./xeinfo einfo.h )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/einfo; gnatmake -q xeinfo ; ./xeinfo einfo.h )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/einfo/einfo.h $(ADA_GEN_SUBDIR)/einfo.h
$(ADA_GEN_SUBDIR)/sinfo.h : $(ADA_GEN_SUBDIR)/sinfo.ads $(ADA_GEN_SUBDIR)/sinfo.adb $(ADA_GEN_SUBDIR)/xsinfo.adb $(ADA_GEN_SUBDIR)/csinfo.adb
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/sinfo
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/sinfo/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/sinfo
- (cd $(ADA_GEN_SUBDIR)/bldtools/sinfo; $(GNATMAKE) -q xsinfo ; ./xsinfo sinfo.h )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/sinfo; gnatmake -q xsinfo ; ./xsinfo sinfo.h )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/sinfo/sinfo.h $(ADA_GEN_SUBDIR)/sinfo.h
$(ADA_GEN_SUBDIR)/snames.h $(ADA_GEN_SUBDIR)/snames.ads $(ADA_GEN_SUBDIR)/snames.adb : $(ADA_GEN_SUBDIR)/stamp-snames ; @true
@@ -50,7 +50,7 @@ $(ADA_GEN_SUBDIR)/stamp-snames : $(ADA_GEN_SUBDIR)/snames.ads-tmpl $(ADA_GEN_SUB
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/snamest
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/snamest/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/snamest
- (cd $(ADA_GEN_SUBDIR)/bldtools/snamest; $(GNATMAKE) -q xsnamest ; ./xsnamest )
+ (cd $(ADA_GEN_SUBDIR)/bldtools/snamest; gnatmake -q xsnamest ; ./xsnamest )
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/snamest/snames.ns $(ADA_GEN_SUBDIR)/snames.ads
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/snamest/snames.nb $(ADA_GEN_SUBDIR)/snames.adb
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/snamest/snames.nh $(ADA_GEN_SUBDIR)/snames.h
@@ -61,7 +61,7 @@ $(ADA_GEN_SUBDIR)/stamp-nmake: $(ADA_GEN_SUBDIR)/sinfo.ads $(ADA_GEN_SUBDIR)/nma
-$(MKDIR) $(ADA_GEN_SUBDIR)/bldtools/nmake
$(RM) $(addprefix $(ADA_GEN_SUBDIR)/bldtools/nmake/,$(notdir $^))
$(CP) $^ $(ADA_GEN_SUBDIR)/bldtools/nmake
- (cd $(ADA_GEN_SUBDIR)/bldtools/nmake; $(GNATMAKE) -q xnmake ; ./xnmake -b nmake.adb ; ./xnmake -s nmake.ads)
+ (cd $(ADA_GEN_SUBDIR)/bldtools/nmake; gnatmake -q xnmake ; ./xnmake -b nmake.adb ; ./xnmake -s nmake.ads)
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/nmake/nmake.ads $(ADA_GEN_SUBDIR)/nmake.ads
$(MOVE_IF_CHANGE) $(ADA_GEN_SUBDIR)/bldtools/nmake/nmake.adb $(ADA_GEN_SUBDIR)/nmake.adb
touch $(ADA_GEN_SUBDIR)/stamp-nmake
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 7eaa9ba..936a16d 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -427,6 +427,7 @@ GNATRTL_NONTASKING_OBJS= \
g-htable$(objext) \
g-io$(objext) \
g-io_aux$(objext) \
+ g-lists$(objext) \
g-locfil$(objext) \
g-mbdira$(objext) \
g-mbflra$(objext) \
@@ -522,12 +523,20 @@ GNATRTL_NONTASKING_OBJS= \
s-conca9$(objext) \
s-crc32$(objext) \
s-crtl$(objext) \
+ s-dfmkio$(objext) \
+ s-dfmopr$(objext) \
+ s-dgmgop$(objext) \
+ s-dlmopr$(objext) \
s-diflio$(objext) \
+ s-diflmk$(objext) \
+ s-digemk$(objext) \
s-diinio$(objext) \
+ s-dilomk$(objext) \
s-dim$(objext) \
s-dimkio$(objext) \
s-dimmks$(objext) \
s-direio$(objext) \
+ s-dlmkio$(objext) \
s-dmotpr$(objext) \
s-dsaser$(objext) \
s-elaall$(objext) \
@@ -2131,15 +2140,10 @@ ifeq ($(strip $(filter-out arm% linux-gnueabi%,$(target_cpu) $(target_os))),)
$(ATOMICS_BUILTINS_TARGET_PAIRS) \
system.ads<libgnat/system-linux-arm.ads
- ifeq ($(strip $(filter-out arm%b,$(target_cpu))),)
- EH_MECHANISM=
- else
- EH_MECHANISM=-arm
- endif
-
TOOLS_TARGET_PAIRS = indepsw.adb<indepsw-gnu.adb
EXTRA_GNATRTL_TASKING_OBJS=s-linux.o
+ EH_MECHANISM=-arm
THREADSLIB = -lpthread
GNATLIB_SHARED = gnatlib-shared-dual
GMEM_LIB = gmemlib
@@ -2761,4 +2765,3 @@ a-tags.o : a-tags.adb a-tags.ads
s-memory.o : s-memory.adb s-memory.ads
$(ADAC) -c $(ALL_ADAFLAGS) $(NO_SIBLING_ADAFLAGS) $(ADA_INCLUDES) \
$< $(OUTPUT_OPTION)
-
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index 871f1f7..1704a2f 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -4490,6 +4490,11 @@ package body Checks is
or else not Is_Discrete_Type (Typ)
+ -- Don't deal with enumerated types with non-standard representation
+
+ or else (Is_Enumeration_Type (Typ)
+ and then Present (Enum_Pos_To_Rep (Base_Type (Typ))))
+
-- Ignore type for which an error has been posted, since range in
-- this case may well be a bogosity deriving from the error. Also
-- ignore if error posted on the reference node.
@@ -6758,9 +6763,36 @@ package body Checks is
-----------------------------
procedure Convert_And_Check_Range is
- Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N);
+ Tnn : constant Entity_Id := Make_Temporary (Loc, 'T', N);
+ Conv_Node : Node_Id;
begin
+ -- For enumeration types with non-standard representation this is a
+ -- direct conversion from the enumeration type to the target integer
+ -- type, which is treated by the back end as a normal integer type
+ -- conversion, treating the enumeration type as an integer, which is
+ -- exactly what we want. We set Conversion_OK to make sure that the
+ -- analyzer does not complain about what otherwise might be an
+ -- illegal conversion.
+
+ if Is_Enumeration_Type (Source_Base_Type)
+ and then Present (Enum_Pos_To_Rep (Source_Base_Type))
+ and then Is_Integer_Type (Target_Base_Type)
+ then
+ Conv_Node :=
+ OK_Convert_To
+ (Typ => Target_Base_Type,
+ Expr => Duplicate_Subexpr (N));
+
+ -- Common case
+
+ else
+ Conv_Node :=
+ Make_Type_Conversion (Loc,
+ Subtype_Mark => New_Occurrence_Of (Target_Base_Type, Loc),
+ Expression => Duplicate_Subexpr (N));
+ end if;
+
-- We make a temporary to hold the value of the converted value
-- (converted to the base type), and then do the test against this
-- temporary. The conversion itself is replaced by an occurrence of
@@ -6776,10 +6808,7 @@ package body Checks is
Defining_Identifier => Tnn,
Object_Definition => New_Occurrence_Of (Target_Base_Type, Loc),
Constant_Present => True,
- Expression =>
- Make_Type_Conversion (Loc,
- Subtype_Mark => New_Occurrence_Of (Target_Base_Type, Loc),
- Expression => Duplicate_Subexpr (N))),
+ Expression => Conv_Node),
Make_Raise_Constraint_Error (Loc,
Condition =>
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index 85affc4..f2eed3d 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -310,14 +310,16 @@ package Checks is
-- then OK is True on return, and Lo and Hi are set to a conservative
-- estimate of the possible range of values of N. Thus if OK is True on
-- return, the value of the subexpression N is known to lie in the range
- -- Lo .. Hi (inclusive). If the expression is not of a discrete type, or
- -- some kind of error condition is detected, then OK is False on exit, and
- -- Lo/Hi are set to No_Uint. Thus the significance of OK being False on
- -- return is that no useful information is available on the range of the
- -- expression. Assume_Valid determines whether the processing is allowed to
- -- assume that values are in range of their subtypes. If it is set to True,
- -- then this assumption is valid, if False, then processing is done using
- -- base types to allow invalid values.
+ -- Lo .. Hi (inclusive). For enumeration and character literals the values
+ -- returned are the Pos value in the relevant enumeration type. If the
+ -- expression is not of a discrete type, or some kind of error condition
+ -- is detected, then OK is False on exit, and Lo/Hi are set to No_Uint.
+ -- Thus the significance of OK being False on return is that no useful
+ -- information is available on the range of the expression. Assume_Valid
+ -- determines whether the processing is allowed to assume that values are
+ -- in range of their subtypes. If it is set to True, then this assumption
+ -- is valid, if False, then processing is done using base types to allow
+ -- invalid values.
procedure Determine_Range_R
(N : Node_Id;
diff --git a/gcc/ada/contracts.adb b/gcc/ada/contracts.adb
index 5577604..26a8d28 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,45 @@ 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
+ (Def_Id => Subp_Id,
+ Typ => Standard_Boolean,
+ Expr => Expression (Corresponding_Aspect (Prag)),
+ N => 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
diff --git a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
index e79f630..1455087 100644
--- a/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
+++ b/gcc/ada/doc/gnat_ugn/building_executable_programs_with_gnat.rst
@@ -1692,13 +1692,44 @@ Alphabetical List of All Switches
Maximum_Alignment : Pos; -- Maximum permitted alignment
Max_Unaligned_Field : Pos; -- Maximum size for unaligned bit field
Pointer_Size : Pos; -- System.Address'Size
- Short_Enums : Nat; -- Short foreign convention enums?
+ Short_Enums : Nat; -- Foreign enums use short size?
Short_Size : Pos; -- Standard.Short_Integer'Size
Strict_Alignment : Nat; -- Strict alignment?
System_Allocator_Alignment : Nat; -- Alignment for malloc calls
Wchar_T_Size : Pos; -- Interfaces.C.wchar_t'Size
Words_BE : Nat; -- Words stored big-endian?
+ ``Bits_Per_Unit`` is the number of bits in a storage unit, the equivalent of
+ GCC macro ``BITS_PER_UNIT`` documented as follows: `Define this macro to be
+ the number of bits in an addressable storage unit (byte); normally 8.`
+
+ ``Bits_Per_Word`` is the number of bits in a machine word, the equivalent of
+ GCC macro ``BITS_PER_WORD`` documented as follows: `Number of bits in a word;
+ normally 32.`
+
+ ``Double_Scalar_Alignment`` is the alignment for a scalar whose size is two
+ machine words. It should be the same as the alignment for C ``long_long`` on
+ most targets.
+
+ ``Maximum_Alignment`` is the maximum alignment that the compiler might choose
+ by default for a type or object, which is also the maximum alignment that can
+ be specified in GNAT. It is computed for GCC backends as ``BIGGEST_ALIGNMENT
+ / BITS_PER_UNIT`` where GCC macro ``BIGGEST_ALIGNMENT`` is documented as
+ follows: `Biggest alignment that any data type can require on this machine,
+ in bits.`
+
+ ``Max_Unaligned_Field`` is the maximum size for unaligned bit field, which is
+ 64 for the majority of GCC targets (but can be different on some targets like
+ AAMP).
+
+ ``Strict_Alignment`` is the equivalent of GCC macro ``STRICT_ALIGNMENT``
+ documented as follows: `Define this macro to be the value 1 if instructions
+ will fail to work if given data not on the nominal alignment. If instructions
+ will merely go slower in that case, define this macro as 0.`
+
+ ``System_Allocator_Alignment`` is the guaranteed alignment of data returned
+ by calls to ``malloc``.
+
The format of the input file is as follows. First come the values of
the variables defined above, with one line per value:
diff --git a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
index 3e0c6ff..9cbdb15 100644
--- a/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
+++ b/gcc/ada/doc/gnat_ugn/gnat_and_program_execution.rst
@@ -3280,19 +3280,18 @@ to use the proper subtypes in object declarations.
.. index:: MKS_Type type
The simplest way to impose dimensionality checking on a computation is to make
-use of the package ``System.Dim.Mks``,
-which is part of the GNAT library. This
-package defines a floating-point type ``MKS_Type``,
-for which a sequence of
-dimension names are specified, together with their conventional abbreviations.
-The following should be read together with the full specification of the
-package, in file :file:`s-dimmks.ads`.
+use of one of the instantiations of the package ``System.Dim.Generic_Mks``, which
+are part of the GNAT library. This generic package defines a floating-point
+type ``MKS_Type``, for which a sequence of dimension names are specified,
+together with their conventional abbreviations. The following should be read
+together with the full specification of the package, in file
+:file:`s-digemk.ads`.
- .. index:: s-dimmks.ads file
+ .. index:: s-digemk.ads file
.. code-block:: ada
- type Mks_Type is new Long_Long_Float
+ type Mks_Type is new Float_Type
with
Dimension_System => (
(Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
@@ -3336,10 +3335,16 @@ as well as useful multiples of these units:
day : constant Time := 60.0 * 24.0 * min;
...
-Using this package, you can then define a derived unit by
-providing the aspect that
-specifies its dimensions within the MKS system, as well as the string to
-be used for output of a value of that unit:
+There are three instantiations of ``System.Dim.Generic_Mks`` defined in the
+GNAT library:
+
+* ``System.Dim.Float_Mks`` based on ``Float`` defined in :file:`s-diflmk.ads`.
+* ``System.Dim.Long_Mks`` based on ``Long_Float`` defined in :file:`s-dilomk.ads`.
+* ``System.Dim.Mks`` based on ``Long_Long_Float`` defined in :file:`s-dimmks.ads`.
+
+Using one of these packages, you can then define a derived unit by providing
+the aspect that specifies its dimensions within the MKS system, as well as the
+string to be used for output of a value of that unit:
.. code-block:: ada
diff --git a/gcc/ada/einfo.adb b/gcc/ada/einfo.adb
index e89ea5a..52a9435 100644
--- a/gcc/ada/einfo.adb
+++ b/gcc/ada/einfo.adb
@@ -118,7 +118,6 @@ package body Einfo is
-- Alignment Uint14
-- Normalized_Position Uint14
-- Postconditions_Proc Node14
- -- Shadow_Entities List14
-- Discriminant_Number Uint15
-- DT_Position Uint15
@@ -199,7 +198,6 @@ package body Einfo is
-- Corresponding_Remote_Type Node22
-- Enumeration_Rep_Expr Node22
-- Original_Record_Component Node22
- -- Private_View Node22
-- Protected_Formal Node22
-- Scope_Depth_Value Uint22
-- Shared_Var_Procs_Instance Node22
@@ -1182,7 +1180,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
return Node13 (Id);
@@ -1193,7 +1191,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
return Flag174 (Id);
@@ -3126,12 +3124,6 @@ package body Einfo is
return Elist18 (Id);
end Private_Dependents;
- function Private_View (Id : E) return N is
- begin
- pragma Assert (Is_Private_Type (Id));
- return Node22 (Id);
- end Private_View;
-
function Protected_Body_Subprogram (Id : E) return E is
begin
pragma Assert (Is_Subprogram (Id) or else Is_Entry (Id));
@@ -3314,12 +3306,6 @@ package body Einfo is
return Flag167 (Id);
end Sec_Stack_Needed_For_Return;
- function Shadow_Entities (Id : E) return S is
- begin
- pragma Assert (Ekind_In (Id, E_Package, E_Generic_Package));
- return List14 (Id);
- end Shadow_Entities;
-
function Shared_Var_Procs_Instance (Id : E) return E is
begin
pragma Assert (Ekind (Id) = E_Variable);
@@ -4412,7 +4398,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
Set_Node13 (Id, V);
@@ -4423,7 +4409,7 @@ package body Einfo is
pragma Assert
(Is_Subprogram (Id)
or else
- Ekind (Id) = E_Package
+ Ekind_In (Id, E_Entry, E_Entry_Family, E_Package)
or else
Is_Generic_Unit (Id));
Set_Flag174 (Id, V);
@@ -6376,12 +6362,6 @@ package body Einfo is
Set_Elist18 (Id, V);
end Set_Private_Dependents;
- procedure Set_Private_View (Id : E; V : N) is
- begin
- pragma Assert (Is_Private_Type (Id));
- Set_Node22 (Id, V);
- end Set_Private_View;
-
procedure Set_Prev_Entity (Id : E; V : E) is
begin
Set_Node36 (Id, V);
@@ -6573,12 +6553,6 @@ package body Einfo is
Set_Flag167 (Id, V);
end Set_Sec_Stack_Needed_For_Return;
- procedure Set_Shadow_Entities (Id : E; V : S) is
- begin
- pragma Assert (Ekind_In (Id, E_Package, E_Generic_Package));
- Set_List14 (Id, V);
- end Set_Shadow_Entities;
-
procedure Set_Shared_Var_Procs_Instance (Id : E; V : E) is
begin
pragma Assert (Ekind (Id) = E_Variable);
@@ -10355,7 +10329,9 @@ package body Einfo is
=>
Write_Str ("Component_Clause");
- when E_Function
+ when E_Entry
+ | E_Entry_Family
+ | E_Function
| E_Procedure
| E_Package
| Generic_Unit_Kind
@@ -10403,11 +10379,6 @@ package body Einfo is
=>
Write_Str ("Postconditions_Proc");
- when E_Generic_Package
- | E_Package
- =>
- Write_Str ("Shadow_Entities");
-
when others =>
Write_Str ("Field14??");
end case;
@@ -10843,15 +10814,6 @@ package body Einfo is
when E_Enumeration_Literal =>
Write_Str ("Enumeration_Rep_Expr");
- when E_Limited_Private_Subtype
- | E_Limited_Private_Type
- | E_Private_Subtype
- | E_Private_Type
- | E_Record_Subtype_With_Private
- | E_Record_Type_With_Private
- =>
- Write_Str ("Private_View");
-
when Formal_Kind =>
Write_Str ("Protected_Formal");
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 8e5bf65..018684d 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -1090,10 +1090,10 @@ package Einfo is
-- to the spec as possible.
-- Elaboration_Entity (Node13)
--- Defined in generic and non-generic package and subprogram entities.
--- This is a counter associated with the unit that is initially set to
--- zero, is incremented when an elaboration request for the unit is
--- made, and is decremented when a finalization request for the unit
+-- Defined in entry, entry family, [generic] package, and subprogram
+-- entities. This is a counter associated with the unit that is initially
+-- set to zero, is incremented when an elaboration request for the unit
+-- is made, and is decremented when a finalization request for the unit
-- is made. This is used for three purposes. First, it is used to
-- implement access before elaboration checks (the counter must be
-- non-zero to call a subprogram at elaboration time). Second, it is
@@ -1110,9 +1110,9 @@ package Einfo is
-- is elaboration code), but is simply not used for any purpose.
-- Elaboration_Entity_Required (Flag174)
--- Defined in generic and non-generic package and subprogram entities.
--- Set only if Elaboration_Entity is non-Empty to indicate that the
--- counter is required to be non-zero even if there is no other
+-- Defined in entry, entry family, [generic] package, and subprogram
+-- entities. Set only if Elaboration_Entity is non-Empty to indicate that
+-- the counter is required to be non-zero even if there is no other
-- elaboration code. This occurs when the Elaboration_Entity counter
-- is used for access before elaboration checks. If the counter is
-- only used to prevent multiple execution of the elaboration code,
@@ -4005,17 +4005,6 @@ package Einfo is
-- declaration of the type is seen. Subprograms that have such an
-- access parameter are also placed in the list of private_dependents.
--- Private_View (Node22)
--- For each private type, three entities are allocated, the private view,
--- the full view, and the shadow entity. The shadow entity contains a
--- copy of the private view and is used for restoring the proper private
--- view after a region in which the full view is visible (and is copied
--- into the entity normally used for the private view during this period
--- of visibility). The Private_View field is self-referential when the
--- private view lives in its normal entity, but in the copy that is made
--- in the shadow entity, it points to the proper location in which to
--- restore the private view saved in the shadow.
-
-- Protected_Body_Subprogram (Node11)
-- Defined in protected operations. References the entity for the
-- subprogram which implements the body of the operation.
@@ -4264,18 +4253,6 @@ package Einfo is
-- returned value of a function and thus should not be released on scope
-- exit.
--- Shadow_Entities (List14)
--- Defined in package and generic package entities. Points to a list
--- of entities that correspond to private types. For each private type
--- a shadow entity is created that holds a copy of the private view.
--- In regions of the program where the full views of these private
--- entities are visible, the full view is copied into the entity that
--- is normally used to hold the private view, but the shadow entity
--- copy is unchanged. The shadow entities are then used to restore the
--- original private views at the end of the region. This list is a
--- standard format list (i.e. First (Shadow_Entities) is the first
--- entry and subsequent entries are obtained using Next.
-
-- Shared_Var_Procs_Instance (Node22)
-- Defined in variables. Set non-Empty only if Is_Shared_Passive is
-- set, in which case this is the entity for the associated instance of
@@ -6058,6 +6035,7 @@ package Einfo is
-- E_Entry_Family
-- Protected_Body_Subprogram (Node11)
-- Barrier_Function (Node12)
+ -- Elaboration_Entity (Node13)
-- Postconditions_Proc (Node14)
-- Entry_Parameters_Type (Node15)
-- First_Entity (Node17)
@@ -6322,7 +6300,6 @@ package Einfo is
-- Underlying_Full_View (Node19)
-- Last_Entity (Node20)
-- Discriminant_Constraint (Elist21)
- -- Private_View (Node22)
-- Stored_Constraint (Elist23)
-- Has_Completion (Flag26)
-- (plus type attributes)
@@ -6401,7 +6378,6 @@ package Einfo is
-- Generic_Homonym (Node11) (generic case only)
-- Associated_Formal_Package (Node12)
-- Elaboration_Entity (Node13)
- -- Shadow_Entities (List14)
-- Related_Instance (Node15) (non-generic case only)
-- First_Private_Entity (Node16)
-- First_Entity (Node17)
@@ -6479,7 +6455,6 @@ package Einfo is
-- Underlying_Full_View (Node19)
-- Last_Entity (Node20)
-- Discriminant_Constraint (Elist21)
- -- Private_View (Node22)
-- Stored_Constraint (Elist23)
-- Has_Completion (Flag26)
-- Is_Controlled_Active (Flag42) (base type only)
@@ -6660,7 +6635,6 @@ package Einfo is
-- Underlying_Full_View (Node19)
-- Last_Entity (Node20)
-- Discriminant_Constraint (Elist21)
- -- Private_View (Node22)
-- Stored_Constraint (Elist23)
-- Interfaces (Elist25)
-- Predicated_Parent (Node38) (subtype only)
@@ -7475,7 +7449,6 @@ package Einfo is
function Prival (Id : E) return E;
function Prival_Link (Id : E) return E;
function Private_Dependents (Id : E) return L;
- function Private_View (Id : E) return N;
function Protected_Body_Subprogram (Id : E) return E;
function Protected_Formal (Id : E) return E;
function Protected_Subprogram (Id : E) return N;
@@ -7508,7 +7481,6 @@ package Einfo is
function Scale_Value (Id : E) return U;
function Scope_Depth_Value (Id : E) return U;
function Sec_Stack_Needed_For_Return (Id : E) return B;
- function Shadow_Entities (Id : E) return S;
function Shared_Var_Procs_Instance (Id : E) return E;
function Size_Check_Code (Id : E) return N;
function Size_Depends_On_Discriminant (Id : E) return B;
@@ -8181,7 +8153,6 @@ package Einfo is
procedure Set_Prival (Id : E; V : E);
procedure Set_Prival_Link (Id : E; V : E);
procedure Set_Private_Dependents (Id : E; V : L);
- procedure Set_Private_View (Id : E; V : N);
procedure Set_Protected_Body_Subprogram (Id : E; V : E);
procedure Set_Protected_Formal (Id : E; V : E);
procedure Set_Protected_Subprogram (Id : E; V : N);
@@ -8214,7 +8185,6 @@ package Einfo is
procedure Set_Scale_Value (Id : E; V : U);
procedure Set_Scope_Depth_Value (Id : E; V : U);
procedure Set_Sec_Stack_Needed_For_Return (Id : E; V : B := True);
- procedure Set_Shadow_Entities (Id : E; V : S);
procedure Set_Shared_Var_Procs_Instance (Id : E; V : E);
procedure Set_Size_Check_Code (Id : E; V : N);
procedure Set_Size_Depends_On_Discriminant (Id : E; V : B := True);
@@ -9058,7 +9028,6 @@ package Einfo is
pragma Inline (Prival);
pragma Inline (Prival_Link);
pragma Inline (Private_Dependents);
- pragma Inline (Private_View);
pragma Inline (Protected_Body_Subprogram);
pragma Inline (Protected_Formal);
pragma Inline (Protected_Subprogram);
@@ -9092,7 +9061,6 @@ package Einfo is
pragma Inline (Scale_Value);
pragma Inline (Scope_Depth_Value);
pragma Inline (Sec_Stack_Needed_For_Return);
- pragma Inline (Shadow_Entities);
pragma Inline (Shared_Var_Procs_Instance);
pragma Inline (Size_Check_Code);
pragma Inline (Size_Depends_On_Discriminant);
@@ -9551,7 +9519,6 @@ package Einfo is
pragma Inline (Set_Prival);
pragma Inline (Set_Prival_Link);
pragma Inline (Set_Private_Dependents);
- pragma Inline (Set_Private_View);
pragma Inline (Set_Protected_Body_Subprogram);
pragma Inline (Set_Protected_Formal);
pragma Inline (Set_Protected_Subprogram);
@@ -9584,7 +9551,6 @@ package Einfo is
pragma Inline (Set_Scale_Value);
pragma Inline (Set_Scope_Depth_Value);
pragma Inline (Set_Sec_Stack_Needed_For_Return);
- pragma Inline (Set_Shadow_Entities);
pragma Inline (Set_Shared_Var_Procs_Instance);
pragma Inline (Set_Size_Check_Code);
pragma Inline (Set_Size_Depends_On_Discriminant);
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index 9d9ab6a..f65230f 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -6195,10 +6195,11 @@ package body Exp_Aggr is
-- Look if in place aggregate expansion is possible
-- For object declarations we build the aggregate in place, unless
- -- the array is bit-packed or the component is controlled.
+ -- the array is bit-packed.
-- For assignments we do the assignment in place if all the component
- -- associations have compile-time known values. For other cases we
+ -- associations have compile-time known values, or are default-
+ -- initialized limited components, e.g. tasks. For other cases we
-- create a temporary. The analysis for safety of on-line assignment
-- is delicate, i.e. we don't know how to do it fully yet ???
@@ -6211,7 +6212,12 @@ package body Exp_Aggr is
Establish_Transient_Scope (N, Manage_Sec_Stack => False);
end if;
- if Has_Default_Init_Comps (N) then
+ -- An array of limited components is built in place
+
+ if Is_Limited_Type (Typ) then
+ Maybe_In_Place_OK := True;
+
+ elsif Has_Default_Init_Comps (N) then
Maybe_In_Place_OK := False;
elsif Is_Bit_Packed_Array (Typ)
@@ -6247,15 +6253,17 @@ package body Exp_Aggr is
-- expected to appear in qualified form. In-place expansion eliminates
-- the qualification and eventually violates this SPARK 05 restiction.
- -- Should document the rest of the guards ???
+ -- Arrays of limited components must be built in place. The code
+ -- previously excluded controlled components but this is an old
+ -- oversight: the rules in 7.6 (17) are clear.
- if not Has_Default_Init_Comps (N)
+ if (not Has_Default_Init_Comps (N)
+ or else Is_Limited_Type (Etype (N)))
and then Comes_From_Source (Parent_Node)
and then Parent_Kind = N_Object_Declaration
and then Present (Expression (Parent_Node))
and then not
Must_Slide (Etype (Defining_Identifier (Parent_Node)), Typ)
- and then not Has_Controlled_Component (Typ)
and then not Is_Bit_Packed_Array (Typ)
and then not Restriction_Check_Required (SPARK_05)
then
@@ -6292,6 +6300,15 @@ package body Exp_Aggr is
Set_Expansion_Delayed (N);
return;
+ -- Limited arrays in return statements are expanded when
+ -- enclosing construct is expanded.
+
+ elsif Maybe_In_Place_OK
+ and then Nkind (Parent (N)) = N_Simple_Return_Statement
+ then
+ Set_Expansion_Delayed (N);
+ return;
+
-- In the remaining cases the aggregate is the RHS of an assignment
elsif Maybe_In_Place_OK
@@ -6365,8 +6382,9 @@ package body Exp_Aggr is
Target := New_Occurrence_Of (Tmp, Loc);
else
- if Has_Default_Init_Comps (N) then
-
+ if Has_Default_Init_Comps (N)
+ and then not Maybe_In_Place_OK
+ then
-- Ada 2005 (AI-287): This case has not been analyzed???
raise Program_Error;
diff --git a/gcc/ada/exp_attr.adb b/gcc/ada/exp_attr.adb
index 469a90e..d789748 100644
--- a/gcc/ada/exp_attr.adb
+++ b/gcc/ada/exp_attr.adb
@@ -3672,29 +3672,35 @@ package body Exp_Attr is
if Is_Fixed_Point_Type (Etype (N)) then
declare
Loc : constant Source_Ptr := Sloc (N);
- Equiv_T : constant Entity_Id := Make_Temporary (Loc, 'T', N);
- Expr : constant Node_Id := Expression (N);
- Fst : constant Entity_Id := Root_Type (Etype (N));
+ Equiv_T : constant Entity_Id := Make_Temporary (Loc, 'T', N);
+ Expr : constant Node_Id := Expression (N);
+ Fst : constant Entity_Id := Root_Type (Etype (N));
Decl : Node_Id;
begin
- Decl := Make_Full_Type_Declaration (Sloc (N),
- Equiv_T,
- Type_Definition =>
- Make_Signed_Integer_Type_Definition (Loc,
- Low_Bound => Make_Integer_Literal (Loc,
- Intval => Corresponding_Integer_Value
- (Type_Low_Bound (Fst))),
- High_Bound => Make_Integer_Literal (Loc,
- Intval => Corresponding_Integer_Value
- (Type_High_Bound (Fst)))));
+ Decl :=
+ Make_Full_Type_Declaration (Sloc (N),
+ Defining_Identifier => Equiv_T,
+ Type_Definition =>
+ Make_Signed_Integer_Type_Definition (Loc,
+ Low_Bound =>
+ Make_Integer_Literal (Loc,
+ Intval =>
+ Corresponding_Integer_Value
+ (Type_Low_Bound (Fst))),
+ High_Bound =>
+ Make_Integer_Literal (Loc,
+ Intval =>
+ Corresponding_Integer_Value
+ (Type_High_Bound (Fst)))));
Insert_Action (N, Decl);
- -- Verify that the conversion is possible.
- Generate_Range_Check
- (Expr, Equiv_T, CE_Overflow_Check_Failed);
+ -- Verify that the conversion is possible
+
+ Generate_Range_Check (Expr, Equiv_T, CE_Overflow_Check_Failed);
+
+ -- and verify that the result is in range
- -- and verify that the result is in range.
Generate_Range_Check (N, Etype (N), CE_Range_Check_Failed);
end;
end if;
diff --git a/gcc/ada/exp_cg.adb b/gcc/ada/exp_cg.adb
index 00f029b..f40dc7e 100644
--- a/gcc/ada/exp_cg.adb
+++ b/gcc/ada/exp_cg.adb
@@ -121,7 +121,14 @@ package body Exp_CG is
for J in Call_Graph_Nodes.First .. Call_Graph_Nodes.Last loop
N := Call_Graph_Nodes.Table (J);
- if Nkind (N) in N_Subprogram_Call then
+ -- No action needed for subprogram calls removed by the expander
+ -- (for example, calls to ignored ghost entities).
+
+ if Nkind (N) = N_Null_Statement then
+ pragma Assert (Nkind (Original_Node (N)) in N_Subprogram_Call);
+ null;
+
+ elsif Nkind (N) in N_Subprogram_Call then
Write_Call_Info (N);
else pragma Assert (Nkind (N) = N_Defining_Identifier);
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 224f4c7..e08b748 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -6402,12 +6402,13 @@ package body Exp_Ch6 is
and then Is_Protected_Type (Etype (Prefix (Name (Parent (N)))))
and then Is_Entity_Name (Name (N))
and then Scope (Entity (Name (N))) =
- Etype (Prefix (Name (Parent (N))))
+ Etype (Prefix (Name (Parent (N))))
then
Rewrite (Name (N),
Make_Selected_Component (Sloc (N),
- Prefix => New_Copy_Tree (Prefix (Name (Parent (N)))),
+ Prefix => New_Copy_Tree (Prefix (Name (Parent (N)))),
Selector_Name => Relocate_Node (Name (N))));
+
Analyze_And_Resolve (N);
return;
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 1b8b8f2..ee04b22 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -4030,8 +4030,8 @@ package body Exp_Ch7 is
-----------------------
function First_Local_Scope (L : List_Id) return Entity_Id is
- Stat : Node_Id;
Scop : Entity_Id;
+ Stat : Node_Id;
begin
Stat := First (L);
@@ -4099,6 +4099,7 @@ package body Exp_Ch7 is
when others =>
null;
end case;
+
Next (Stat);
end loop;
@@ -4119,8 +4120,8 @@ package body Exp_Ch7 is
and then Present (Handled_Statement_Sequence (N))
and then Is_Compilation_Unit (Current_Scope)
then
- Ent := First_Local_Scope
- (Statements (Handled_Statement_Sequence (N)));
+ Ent :=
+ First_Local_Scope (Statements (Handled_Statement_Sequence (N)));
if Present (Ent) then
Elab_Proc :=
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index e7561df..4470c4e 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -476,10 +476,13 @@ package body Exp_Ch9 is
-- ...
-- <actualN> := P.<formalN>;
- procedure Reset_Scopes_To (Proc_Body : Node_Id; E : Entity_Id);
- -- Reset the scope of declarations and blocks at the top level of Proc_Body
- -- to be E. Used after expanding entry bodies into their corresponding
- -- procedures.
+ procedure Reset_Scopes_To (Bod : Node_Id; E : Entity_Id);
+ -- Reset the scope of declarations and blocks at the top level of Bod
+ -- to be E. Bod is either a block or a subprogram body. Used after
+ -- expanding various kinds of entry bodies into their corresponding
+ -- constructs. This is needed during unnesting to determine whether a
+ -- body geenrated for an entry or an accept alternative includes uplevel
+ -- references.
function Trivial_Accept_OK return Boolean;
-- If there is no DO-END block for an accept, or if the DO-END block has
@@ -3807,7 +3810,7 @@ package body Exp_Ch9 is
New_Occurrence_Of
(RTE (RE_Get_GNAT_Exception), Loc)))))))));
- Reset_Scopes_To (Proc_Body, Bod_Id);
+ Reset_Scopes_To (Proc_Body, Protected_Body_Subprogram (Ent));
return Proc_Body;
end if;
end Build_Protected_Entry;
@@ -8238,6 +8241,8 @@ package body Exp_Ch9 is
end if;
Analyze (N);
+
+ Reset_Scopes_To (N, Entity (Identifier (N)));
end Expand_N_Conditional_Entry_Call;
---------------------------------------
@@ -12651,7 +12656,7 @@ package body Exp_Ch9 is
Expression => D_Disc));
-- Do the assignment at this stage only because the evaluation of the
- -- expression must not occur before (see ACVC C97302A).
+ -- expression must not occur earlier (see ACVC C97302A).
Append_To (Stmts,
Make_Assignment_Statement (Loc,
@@ -12848,7 +12853,7 @@ package body Exp_Ch9 is
end loop;
-- Do the assignment at this stage only because the evaluation
- -- of the expression must not occur before (see ACVC C97302A).
+ -- of the expression must not occur earlier (see ACVC C97302A).
Insert_Before (Stmt,
Make_Assignment_Statement (Loc,
@@ -12933,6 +12938,21 @@ package body Exp_Ch9 is
Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
Analyze (N);
+
+ -- Some items in Decls used to be in the N_Block in E_Call that
+ -- is constructed in Expand_Entry_Call, and are now in the new
+ -- Block into which N has been rewritten. Adjust their scopes
+ -- to reflect that.
+
+ if Nkind (E_Call) = N_Block_Statement then
+ Obj := First_Entity (Entity (Identifier (E_Call)));
+ while Present (Obj) loop
+ Set_Scope (Obj, Entity (Identifier (N)));
+ Next_Entity (Obj);
+ end loop;
+ end if;
+
+ Reset_Scopes_To (N, Entity (Identifier (N)));
end Expand_N_Timed_Entry_Call;
----------------------------------------
@@ -14830,11 +14850,12 @@ package body Exp_Ch9 is
-- Reset_Scopes_To --
---------------------
- procedure Reset_Scopes_To (Proc_Body : Node_Id; E : Entity_Id) is
+ procedure Reset_Scopes_To (Bod : Node_Id; E : Entity_Id) is
function Reset_Scope (N : Node_Id) return Traverse_Result;
-- Temporaries may have been declared during expansion of the procedure
- -- alternative. Indicate that their scope is the new body, to prevent
- -- generation of spurious uplevel references for these entities.
+ -- created for an entry body or an accept alternative. Indicate that
+ -- their scope is the new body, to unsure proper generation of uplevel
+ -- references where needed during unnesting.
procedure Reset_Scopes is new Traverse_Proc (Reset_Scope);
@@ -14849,19 +14870,26 @@ package body Exp_Ch9 is
-- If this is a block statement with an Identifier, it forms a scope,
-- so we want to reset its scope but not look inside.
- if Nkind (N) = N_Block_Statement
+ if N /= Bod
+ and then Nkind (N) = N_Block_Statement
and then Present (Identifier (N))
then
Set_Scope (Entity (Identifier (N)), E);
return Skip;
- elsif Nkind (N) = N_Package_Declaration then
+ -- Ditto for a package declaration or a full type declaration, etc.
+
+ elsif Nkind (N) = N_Package_Declaration
+ or else Nkind (N) in N_Declaration
+ or else Nkind (N) in N_Renaming_Declaration
+ then
Set_Scope (Defining_Entity (N), E);
return Skip;
- elsif N = Proc_Body then
+ elsif N = Bod then
- -- Scan declarations
+ -- Scan declarations in new body. Declarations in the statement
+ -- part will be handled during later traversal.
Decl := First (Declarations (N));
while Present (Decl) loop
@@ -14869,10 +14897,8 @@ package body Exp_Ch9 is
Next (Decl);
end loop;
- elsif N /= Proc_Body and then Nkind (N) in N_Proper_Body then
+ elsif N /= Bod and then Nkind (N) in N_Proper_Body then
return Skip;
- elsif Nkind (N) = N_Defining_Identifier then
- Set_Scope (N, E);
end if;
return OK;
@@ -14881,7 +14907,7 @@ package body Exp_Ch9 is
-- Start of processing for Reset_Scopes_To
begin
- Reset_Scopes (Proc_Body);
+ Reset_Scopes (Bod);
end Reset_Scopes_To;
----------------------
diff --git a/gcc/ada/exp_unst.adb b/gcc/ada/exp_unst.adb
index c5b03c4..d688157 100644
--- a/gcc/ada/exp_unst.adb
+++ b/gcc/ada/exp_unst.adb
@@ -260,12 +260,10 @@ package body Exp_Unst is
E := Ultimate_Alias (E);
-- The body of a protected operation has a different name and
- -- has been scanned at this point, and thus has an entry in
- -- the subprogram table.
+ -- has been scanned at this point, and thus has an entry in the
+ -- subprogram table.
- if E = Sub
- and then Convention (E) = Convention_Protected
- then
+ if E = Sub and then Convention (E) = Convention_Protected then
E := Protected_Body_Subprogram (E);
end if;
@@ -551,9 +549,8 @@ package body Exp_Unst is
-- Explicit dereference and selected component case
- elsif Nkind_In (N,
- N_Explicit_Dereference,
- N_Selected_Component)
+ elsif Nkind_In (N, N_Explicit_Dereference,
+ N_Selected_Component)
then
Note_Uplevel_Bound (Prefix (N), Ref);
diff --git a/gcc/ada/exp_unst.ads b/gcc/ada/exp_unst.ads
index 3b67a0d..a5cdf06 100644
--- a/gcc/ada/exp_unst.ads
+++ b/gcc/ada/exp_unst.ads
@@ -477,7 +477,7 @@ package Exp_Unst is
-- subprograms exist. Similarly overloading would cause a naming issue.
-- In fact, the expanded code includes qualified names which eliminate this
- -- problem. We omitted the qualification from the exapnded examples above
+ -- problem. We omitted the qualification from the expanded examples above
-- for simplicity. But to see this in action, consider this example:
-- function Mnames return Boolean is
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index 3bed508..314e3ee 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -8402,9 +8402,23 @@ package body Exp_Util is
declare
Align_In_Bits : constant Nat := M * System_Storage_Unit;
+ Comp : Entity_Id;
+
begin
- if Component_Bit_Offset (C) mod Align_In_Bits /= 0
- or else Esize (C) mod Align_In_Bits /= 0
+ Comp := C;
+
+ -- For a component inherited in a record extension, the
+ -- clause is inherited but position and size are not set.
+
+ if Is_Base_Type (Etype (P))
+ and then Is_Tagged_Type (Etype (P))
+ and then Present (Original_Record_Component (Comp))
+ then
+ Comp := Original_Record_Component (Comp);
+ end if;
+
+ if Component_Bit_Offset (Comp) mod Align_In_Bits /= 0
+ or else Esize (Comp) mod Align_In_Bits /= 0
then
return True;
end if;
diff --git a/gcc/ada/fe.h b/gcc/ada/fe.h
index 1928609..2d07aa5 100644
--- a/gcc/ada/fe.h
+++ b/gcc/ada/fe.h
@@ -85,7 +85,7 @@ extern void Set_RM_Size (Entity_Id, Uint);
extern Boolean Is_Entity_Name (Node_Id);
#define Get_Attribute_Definition_Clause einfo__get_attribute_definition_clause
-extern Node_Id Get_Attribute_Definition_Clause (Entity_Id, char);
+extern Node_Id Get_Attribute_Definition_Clause (Entity_Id, unsigned char);
/* errout: */
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 9979cbf..5036a79 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -49,6 +49,7 @@ with Rtsfind; use Rtsfind;
with Sem; use Sem;
with Sem_Aux; use Sem_Aux;
with Sem_Cat; use Sem_Cat;
+with Sem_Ch3; use Sem_Ch3;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch7; use Sem_Ch7;
with Sem_Ch8; use Sem_Ch8;
@@ -3611,10 +3612,14 @@ package body Freeze is
Error_Msg_Qual_Level := 1;
- -- Check suspicious use of fat C pointer
+ -- Check suspicious use of fat C pointer, but do not emit
+ -- a warning on an access to subprogram when unnesting is
+ -- active.
if Is_Access_Type (F_Type)
and then Esize (F_Type) > Ttypes.System_Address_Size
+ and then (not Unnest_Subprogram_Mode
+ or else not Is_Access_Subprogram_Type (F_Type))
then
Error_Msg_N
("?x?type of & does not correspond to C pointer!", Formal);
@@ -7639,6 +7644,208 @@ package body Freeze is
In_Spec_Expression := In_Spec_Exp;
end Freeze_Expression;
+ -----------------------
+ -- Freeze_Expr_Types --
+ -----------------------
+
+ procedure Freeze_Expr_Types
+ (Def_Id : Entity_Id;
+ Typ : Entity_Id;
+ Expr : Node_Id;
+ N : Node_Id)
+ is
+ function Cloned_Expression return Node_Id;
+ -- Build a duplicate of the expression of the return statement that has
+ -- no defining entities shared with the original expression.
+
+ function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result;
+ -- Freeze all types referenced in the subtree rooted at Node
+
+ -----------------------
+ -- Cloned_Expression --
+ -----------------------
+
+ function Cloned_Expression return Node_Id is
+ function Clone_Id (Node : Node_Id) return Traverse_Result;
+ -- Tree traversal routine that clones the defining identifier of
+ -- iterator and loop parameter specification nodes.
+
+ --------------
+ -- Clone_Id --
+ --------------
+
+ function Clone_Id (Node : Node_Id) return Traverse_Result is
+ begin
+ if Nkind_In (Node, N_Iterator_Specification,
+ N_Loop_Parameter_Specification)
+ then
+ Set_Defining_Identifier
+ (Node, New_Copy (Defining_Identifier (Node)));
+ end if;
+
+ return OK;
+ end Clone_Id;
+
+ procedure Clone_Def_Ids is new Traverse_Proc (Clone_Id);
+
+ -- Local variable
+
+ Dup_Expr : constant Node_Id := New_Copy_Tree (Expr);
+
+ -- Start of processing for Cloned_Expression
+
+ begin
+ -- We must duplicate the expression with semantic information to
+ -- inherit the decoration of global entities in generic instances.
+ -- Set the parent of the new node to be the parent of the original
+ -- to get the proper context, which is needed for complete error
+ -- reporting and for semantic analysis.
+
+ Set_Parent (Dup_Expr, Parent (Expr));
+
+ -- Replace the defining identifier of iterators and loop param
+ -- specifications by a clone to ensure that the cloned expression
+ -- and the original expression don't have shared identifiers;
+ -- otherwise, as part of the preanalysis of the expression, these
+ -- shared identifiers may be left decorated with itypes which
+ -- will not be available in the tree passed to the backend.
+
+ Clone_Def_Ids (Dup_Expr);
+
+ return Dup_Expr;
+ end Cloned_Expression;
+
+ ----------------------
+ -- Freeze_Type_Refs --
+ ----------------------
+
+ function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result is
+ procedure Check_And_Freeze_Type (Typ : Entity_Id);
+ -- Check that Typ is fully declared and freeze it if so
+
+ ---------------------------
+ -- Check_And_Freeze_Type --
+ ---------------------------
+
+ procedure Check_And_Freeze_Type (Typ : Entity_Id) is
+ begin
+ -- Skip Itypes created by the preanalysis, and itypes whose
+ -- scope is another type (i.e. component subtypes that depend
+ -- on a discriminant),
+
+ if Is_Itype (Typ)
+ and then (Scope_Within_Or_Same (Scope (Typ), Def_Id)
+ or else Is_Type (Scope (Typ)))
+ then
+ return;
+ end if;
+
+ -- This provides a better error message than generating primitives
+ -- whose compilation fails much later. Refine the error message if
+ -- possible.
+
+ Check_Fully_Declared (Typ, Node);
+
+ if Error_Posted (Node) then
+ if Has_Private_Component (Typ)
+ and then not Is_Private_Type (Typ)
+ then
+ Error_Msg_NE ("\type& has private component", Node, Typ);
+ end if;
+
+ else
+ Freeze_Before (N, Typ);
+ end if;
+ end Check_And_Freeze_Type;
+
+ -- Start of processing for Freeze_Type_Refs
+
+ begin
+ -- Check that a type referenced by an entity can be frozen
+
+ if Is_Entity_Name (Node) and then Present (Entity (Node)) then
+ Check_And_Freeze_Type (Etype (Entity (Node)));
+
+ -- Check that the enclosing record type can be frozen
+
+ if Ekind_In (Entity (Node), E_Component, E_Discriminant) then
+ Check_And_Freeze_Type (Scope (Entity (Node)));
+ end if;
+
+ -- Freezing an access type does not freeze the designated type, but
+ -- freezing conversions between access to interfaces requires that
+ -- the interface types themselves be frozen, so that dispatch table
+ -- entities are properly created.
+
+ -- Unclear whether a more general rule is needed ???
+
+ elsif Nkind (Node) = N_Type_Conversion
+ and then Is_Access_Type (Etype (Node))
+ and then Is_Interface (Designated_Type (Etype (Node)))
+ then
+ Check_And_Freeze_Type (Designated_Type (Etype (Node)));
+ end if;
+
+ -- An implicit dereference freezes the designated type. In the case
+ -- of a dispatching call whose controlling argument is an access
+ -- type, the dereference is not made explicit, so we must check for
+ -- such a call and freeze the designated type.
+
+ if Nkind (Node) in N_Has_Etype
+ and then Present (Etype (Node))
+ and then Is_Access_Type (Etype (Node))
+ and then Nkind (Parent (Node)) = N_Function_Call
+ and then Node = Controlling_Argument (Parent (Node))
+ then
+ Check_And_Freeze_Type (Designated_Type (Etype (Node)));
+ end if;
+
+ -- No point in posting several errors on the same expression
+
+ if Serious_Errors_Detected > 0 then
+ return Abandon;
+ else
+ return OK;
+ end if;
+ end Freeze_Type_Refs;
+
+ procedure Freeze_References is new Traverse_Proc (Freeze_Type_Refs);
+
+ -- Local variables
+
+ Saved_First_Entity : constant Entity_Id := First_Entity (Def_Id);
+ Saved_Last_Entity : constant Entity_Id := Last_Entity (Def_Id);
+ Dup_Expr : constant Node_Id := Cloned_Expression;
+
+ -- Start of processing for Freeze_Expr_Types
+
+ begin
+ -- Preanalyze a duplicate of the expression to have available the
+ -- minimum decoration needed to locate referenced unfrozen types
+ -- without adding any decoration to the function expression.
+
+ Push_Scope (Def_Id);
+ Install_Formals (Def_Id);
+
+ Preanalyze_Spec_Expression (Dup_Expr, Typ);
+ End_Scope;
+
+ -- Restore certain attributes of Def_Id since the preanalysis may
+ -- have introduced itypes to this scope, thus modifying attributes
+ -- First_Entity and Last_Entity.
+
+ Set_First_Entity (Def_Id, Saved_First_Entity);
+ Set_Last_Entity (Def_Id, Saved_Last_Entity);
+
+ if Present (Last_Entity (Def_Id)) then
+ Set_Next_Entity (Last_Entity (Def_Id), Empty);
+ end if;
+
+ -- Freeze all types referenced in the expression
+
+ Freeze_References (Dup_Expr);
+ end Freeze_Expr_Types;
+
-----------------------------
-- Freeze_Fixed_Point_Type --
-----------------------------
diff --git a/gcc/ada/freeze.ads b/gcc/ada/freeze.ads
index 20badd0..96b3c90 100644
--- a/gcc/ada/freeze.ads
+++ b/gcc/ada/freeze.ads
@@ -230,6 +230,17 @@ package Freeze is
-- so need to be similarly treated. Freeze_Expression takes care of
-- determining the proper insertion point for generated freeze actions.
+ procedure Freeze_Expr_Types
+ (Def_Id : Entity_Id;
+ Typ : Entity_Id;
+ Expr : Node_Id;
+ N : Node_Id);
+ -- N is the body constructed for an expression function that is a
+ -- completion, and Def_Id is the function being completed.
+ -- This procedure freezes before N all the types referenced in Expr,
+ -- which is either the expression of the expression function, or
+ -- the expression in a pre/post aspect that applies to Def_Id;
+
procedure Freeze_Fixed_Point_Type (Typ : Entity_Id);
-- Freeze fixed point type. For fixed-point types, we have to defer
-- setting the size and bounds till the freeze point, since they are
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index d51d397..d8dac73 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -319,6 +319,7 @@ GNAT_ADA_OBJS = \
ada/libgnat/g-dynhta.o \
ada/libgnat/g-hesora.o \
ada/libgnat/g-htable.o \
+ ada/libgnat/g-lists.o \
ada/libgnat/g-spchge.o \
ada/libgnat/g-speche.o \
ada/libgnat/g-u3spch.o \
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 601f23a..4d870c2 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -441,6 +441,11 @@ ifeq ($(ENABLE_VXADDR2LINE),true)
TOOLSCASE=cross top_buildir=../../.. \
../../vxaddr2line$(exeext)
endif
+ifeq ($(ENABLE_VXLINK),true)
+ $(MAKE) -C tools -f ../Makefile $(TOOLS_FLAGS_TO_PASS) \
+ TOOLSCASE=cross top_build=../../.. \
+ ../../vxlink$(exeext)
+endif
common-tools: ../stamp-tools
$(GNATMAKE) -j0 -c -b $(ADA_INCLUDES) \
@@ -478,6 +483,12 @@ common-tools: ../stamp-tools
$(GNATLINK) -v vxaddr2line -o $@ \
--GCC="$(CC) $(ADA_INCLUDES)" --LINK="$(GCC_LINK)" ../targext.o $(CLIB)
+../../vxlink$(exeext): ../stamp-tools
+ $(GNATMAKE) -c $(ADA_INCLUDES) vxlink-main --GCC="$(CC) $(ALL_ADAFLAGS)"
+ $(GNATBIND) $(ADA_INCLUDES) $(GNATBIND_FLAGS) vxlink-main
+ $(GNATLINK) -v vxlink-main -o $@ \
+ --GCC="$(CC) $(ADA_INCLUDES)" --LINK="$(GCC_LINK)"
+
gnatmake-re: ../stamp-tools
$(GNATMAKE) -j0 $(ADA_INCLUDES) -u sdefault --GCC="$(CC) $(MOST_ADA_FLAGS)"
$(GNATMAKE) -j0 -c $(ADA_INCLUDES) gnatmake --GCC="$(CC) $(ALL_ADAFLAGS)"
@@ -613,7 +624,7 @@ OSCONS_EXTRACT=$(OSCONS_CC) $(GNATLIBCFLAGS_FOR_C) -S s-oscons-tmplt.i
-$(MKDIR) ./bldtools/oscons
$(RM) $(addprefix ./bldtools/oscons/,$(notdir $^))
$(CP) $^ ./bldtools/oscons
- (cd ./bldtools/oscons ; $(GNATMAKE) -q xoscons)
+ (cd ./bldtools/oscons ; gnatmake -q xoscons)
$(RTSDIR)/s-oscons.ads: ../stamp-gnatlib1-$(RTSDIR) s-oscons-tmplt.c gsocket.h ./bldtools/oscons/xoscons
$(RM) $(RTSDIR)/s-oscons-tmplt.i $(RTSDIR)/s-oscons-tmplt.s
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index b1dc379..6f605bd 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -5421,7 +5421,7 @@ update_profile (Entity_Id gnat_subprog)
if (DECL_P (gnu_type))
{
/* Builtins cannot have their address taken so we can reset them. */
- gcc_assert (DECL_BUILT_IN (gnu_type));
+ gcc_assert (fndecl_built_in_p (gnu_type));
save_gnu_tree (gnat_subprog, NULL_TREE, false);
save_gnu_tree (gnat_subprog, gnu_type, false);
return;
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index a75cb90..eb64a8b 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -285,7 +285,7 @@ extern void process_type (Entity_Id gnat_entity);
location and false if it doesn't. If CLEAR_COLUMN is true, set the column
information to 0. */
extern bool Sloc_to_locus (Source_Ptr Sloc, location_t *locus,
- bool clear_column = false);
+ bool clear_column = false, const_tree decl = 0);
/* Post an error message. MSG is the error message, properly annotated.
NODE is the node at which to post the error and the node to use for the
@@ -1081,7 +1081,7 @@ call_is_atomic_load (tree exp)
{
tree fndecl = get_callee_fndecl (exp);
- if (!(fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL))
+ if (!(fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)))
return false;
enum built_in_function code = DECL_FUNCTION_CODE (fndecl);
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 31e098a..940bf5f 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -41,6 +41,7 @@
#include "stmt.h"
#include "varasm.h"
#include "output.h"
+#include "debug.h"
#include "libfuncs.h" /* For set_stack_check_libfunc. */
#include "tree-iterator.h"
#include "gimplify.h"
@@ -255,6 +256,12 @@ static tree create_init_temporary (const char *, tree, tree *, Node_Id);
static const char *extract_encoding (const char *) ATTRIBUTE_UNUSED;
static const char *decode_name (const char *) ATTRIBUTE_UNUSED;
+/* This makes gigi's file_info_ptr visible in this translation unit,
+ so that Sloc_to_locus can look it up when deciding whether to map
+ decls to instances. */
+
+static struct File_Info_Type *file_map;
+
/* This is the main program of the back-end. It sets up all the table
structures and then generates code. */
@@ -300,6 +307,12 @@ gigi (Node_Id gnat_root,
type_annotate_only = (gigi_operating_mode == 1);
+ if (Generate_SCO_Instance_Table != 0)
+ {
+ file_map = file_info_ptr;
+ maybe_create_decl_to_instance_map (number_file);
+ }
+
for (i = 0; i < number_file; i++)
{
/* Use the identifier table to make a permanent copy of the filename as
@@ -701,6 +714,7 @@ gigi (Node_Id gnat_root,
}
/* Destroy ourselves. */
+ file_map = NULL;
destroy_gnat_decl ();
destroy_gnat_utils ();
@@ -3771,7 +3785,7 @@ Subprogram_Body_to_gnu (Node_Id gnat_node)
}
/* Set the line number in the decl to correspond to that of the body. */
- if (!Sloc_to_locus (Sloc (gnat_node), &locus))
+ if (!Sloc_to_locus (Sloc (gnat_node), &locus, false, gnu_subprog_decl))
locus = input_location;
DECL_SOURCE_LOCATION (gnu_subprog_decl) = locus;
@@ -4436,6 +4450,7 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target,
const bool suppress_type_conversion
= ((Nkind (gnat_actual) == N_Unchecked_Type_Conversion
&& (!in_param
+ || !is_by_ref_formal_parm
|| (Is_Composite_Type (Underlying_Type (gnat_formal_type))
&& !Is_Constrained (Underlying_Type (gnat_formal_type)))))
|| (Nkind (gnat_actual) == N_Type_Conversion
@@ -9970,12 +9985,14 @@ maybe_implicit_deref (tree exp)
return exp;
}
-/* Convert SLOC into LOCUS. Return true if SLOC corresponds to a source code
- location and false if it doesn't. If CLEAR_COLUMN is true, set the column
- information to 0. */
+/* Convert SLOC into LOCUS. Return true if SLOC corresponds to a
+ source code location and false if it doesn't. If CLEAR_COLUMN is
+ true, set the column information to 0. If DECL is given and SLOC
+ refers to a File with an instance, map DECL to that instance. */
bool
-Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
+Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column,
+ const_tree decl)
{
if (Sloc == No_Location)
return false;
@@ -9999,6 +10016,9 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus, bool clear_column)
*locus
= linemap_position_for_line_and_column (line_table, map, line, column);
+ if (file_map && file_map[file - 1].Instance)
+ decl_to_instance_map->put (decl, file_map[file - 1].Instance);
+
return true;
}
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index cc1fe77..313d984 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -773,7 +773,7 @@ gnat_pushdecl (tree decl, Node_Id gnat_node)
debugger at the proper time. */
if (DECL_EXTERNAL (decl)
&& TREE_CODE (decl) == FUNCTION_DECL
- && DECL_BUILT_IN (decl))
+ && fndecl_built_in_p (decl))
vec_safe_push (builtin_decls, decl);
else if (global_bindings_p ())
vec_safe_push (global_decls, decl);
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index b5972bb..aeaa146 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -21,7 +21,7 @@
@copying
@quotation
-GNAT User's Guide for Native Platforms , Jul 13, 2018
+GNAT User's Guide for Native Platforms , Aug 20, 2018
AdaCore
@@ -9429,7 +9429,7 @@ Long_Size : Pos; -- Standard.Long_Integer'Size
Maximum_Alignment : Pos; -- Maximum permitted alignment
Max_Unaligned_Field : Pos; -- Maximum size for unaligned bit field
Pointer_Size : Pos; -- System.Address'Size
-Short_Enums : Nat; -- Short foreign convention enums?
+Short_Enums : Nat; -- Foreign enums use short size?
Short_Size : Pos; -- Standard.Short_Integer'Size
Strict_Alignment : Nat; -- Strict alignment?
System_Allocator_Alignment : Nat; -- Alignment for malloc calls
@@ -9437,6 +9437,32 @@ Wchar_T_Size : Pos; -- Interfaces.C.wchar_t'Size
Words_BE : Nat; -- Words stored big-endian?
@end example
+@code{Bits_Per_Unit} is the number of bits in a storage unit, the equivalent of
+GCC macro @code{BITS_PER_UNIT} documented as follows: @cite{Define this macro to be the number of bits in an addressable storage unit (byte); normally 8.}
+
+@code{Bits_Per_Word} is the number of bits in a machine word, the equivalent of
+GCC macro @code{BITS_PER_WORD} documented as follows: @cite{Number of bits in a word; normally 32.}
+
+@code{Double_Scalar_Alignment} is the alignment for a scalar whose size is two
+machine words. It should be the same as the alignment for C @code{long_long} on
+most targets.
+
+@code{Maximum_Alignment} is the maximum alignment that the compiler might choose
+by default for a type or object, which is also the maximum alignment that can
+be specified in GNAT. It is computed for GCC backends as @code{BIGGEST_ALIGNMENT
+/ BITS_PER_UNIT} where GCC macro @code{BIGGEST_ALIGNMENT} is documented as
+follows: @cite{Biggest alignment that any data type can require on this machine@comma{} in bits.}
+
+@code{Max_Unaligned_Field} is the maximum size for unaligned bit field, which is
+64 for the majority of GCC targets (but can be different on some targets like
+AAMP).
+
+@code{Strict_Alignment} is the equivalent of GCC macro @code{STRICT_ALIGNMENT}
+documented as follows: @cite{Define this macro to be the value 1 if instructions will fail to work if given data not on the nominal alignment. If instructions will merely go slower in that case@comma{} define this macro as 0.}
+
+@code{System_Allocator_Alignment} is the guaranteed alignment of data returned
+by calls to @code{malloc}.
+
The format of the input file is as follows. First come the values of
the variables defined above, with one line per value:
@@ -22606,20 +22632,19 @@ to use the proper subtypes in object declarations.
@geindex MKS_Type type
The simplest way to impose dimensionality checking on a computation is to make
-use of the package @code{System.Dim.Mks},
-which is part of the GNAT library. This
-package defines a floating-point type @code{MKS_Type},
-for which a sequence of
-dimension names are specified, together with their conventional abbreviations.
-The following should be read together with the full specification of the
-package, in file @code{s-dimmks.ads}.
+use of one of the instantiations of the package @code{System.Dim.Generic_Mks}, which
+are part of the GNAT library. This generic package defines a floating-point
+type @code{MKS_Type}, for which a sequence of dimension names are specified,
+together with their conventional abbreviations. The following should be read
+together with the full specification of the package, in file
+@code{s-digemk.ads}.
@quotation
-@geindex s-dimmks.ads file
+@geindex s-digemk.ads file
@example
-type Mks_Type is new Long_Long_Float
+type Mks_Type is new Float_Type
with
Dimension_System => (
(Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
@@ -22674,10 +22699,25 @@ as well as useful multiples of these units:
@end example
@end quotation
-Using this package, you can then define a derived unit by
-providing the aspect that
-specifies its dimensions within the MKS system, as well as the string to
-be used for output of a value of that unit:
+There are three instantiations of @code{System.Dim.Generic_Mks} defined in the
+GNAT library:
+
+
+@itemize *
+
+@item
+@code{System.Dim.Float_Mks} based on @code{Float} defined in @code{s-diflmk.ads}.
+
+@item
+@code{System.Dim.Long_Mks} based on @code{Long_Float} defined in @code{s-dilomk.ads}.
+
+@item
+@code{System.Dim.Mks} based on @code{Long_Long_Float} defined in @code{s-dimmks.ads}.
+@end itemize
+
+Using one of these packages, you can then define a derived unit by providing
+the aspect that specifies its dimensions within the MKS system, as well as the
+string to be used for output of a value of that unit:
@quotation
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index 16981b8..5c8bb7d 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -1103,9 +1103,9 @@ procedure Gnatlink is
-- as it is in the same directory as the shared version.
if Nlast >= Library_Version'Length
- and then Next_Line
- (Nlast - Library_Version'Length + 1 .. Nlast)
- = Library_Version
+ and then
+ Next_Line (Nlast - Library_Version'Length + 1 .. Nlast) =
+ Library_Version
then
-- Set Last to point to last character before the
-- library version.
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index cfa1d5e..3e5fbe0 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -281,6 +281,7 @@ package body Impunit is
("g-htable", F), -- GNAT.Htable
("g-io ", F), -- GNAT.IO
("g-io_aux", F), -- GNAT.IO_Aux
+ ("g-lists ", F), -- GNAT.Lists
("g-locfil", F), -- GNAT.Lock_Files
("g-mbdira", F), -- GNAT.MBBS_Discrete_Random
("g-mbflra", F), -- GNAT.MBBS_Float_Random
@@ -372,10 +373,18 @@ package body Impunit is
("s-addima", F), -- System.Address_Image
("s-atocou", F), -- System.Atomic_Counters
("s-assert", F), -- System.Assertions
+ ("s-dfmkio", F), -- System.Dim.Float_Mks_IO
+ ("s-dfmopr", F), -- System.Dim.Float_Mks.Other_Prefixes
+ ("s-dgmgop", F), -- System.Dim.Generic_Mks.Generic_Other_Prefixes
+ ("s-dlmopr", F), -- System.Dim.Long_Mks.Other_Prefixes
("s-diflio", F), -- System.Dim.Float_IO
+ ("s-diflmk", F), -- System.Dim.Float_Mks
+ ("s-digemk", F), -- System.Dim.Generic_Mks
("s-diinio", F), -- System.Dim.Integer_IO
+ ("s-dilomk", F), -- System.Dim.Long_Mks
("s-dimkio", F), -- System.Dim.Mks_IO
("s-dimmks", F), -- System.Dim.Mks
+ ("s-dlmkio", F), -- System.Dim.Long_Mks_IO
("s-dmotpr", F), -- System.Dim.Mks.Other_Prefixes
("s-memory", F), -- System.Memory
("s-parint", F), -- System.Partition_Interface
diff --git a/gcc/ada/itypes.adb b/gcc/ada/itypes.adb
index fa88ef7..6640c57 100644
--- a/gcc/ada/itypes.adb
+++ b/gcc/ada/itypes.adb
@@ -42,7 +42,7 @@ package body Itypes is
Related_Nod : Node_Id;
Related_Id : Entity_Id := Empty;
Suffix : Character := ' ';
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Scope_Id : Entity_Id := Current_Scope) return Entity_Id
is
Typ : Entity_Id;
diff --git a/gcc/ada/itypes.ads b/gcc/ada/itypes.ads
index e59cbe8..1513c8a 100644
--- a/gcc/ada/itypes.ads
+++ b/gcc/ada/itypes.ads
@@ -110,7 +110,7 @@ package Itypes is
Related_Nod : Node_Id;
Related_Id : Entity_Id := Empty;
Suffix : Character := ' ';
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Scope_Id : Entity_Id := Current_Scope) return Entity_Id;
-- Used to create a new Itype
--
diff --git a/gcc/ada/layout.adb b/gcc/ada/layout.adb
index 6b77757..a7b24ab 100644
--- a/gcc/ada/layout.adb
+++ b/gcc/ada/layout.adb
@@ -325,6 +325,16 @@ package body Layout is
then
Init_Size (E, 2 * System_Address_Size);
+ -- If unnesting subprograms, subprogram access types contain the
+ -- address of both the subprogram and an activation record. But if we
+ -- set that, we'll get a warning on different unchecked conversion
+ -- sizes in the RTS. So leave unset ub that case.
+
+ elsif Unnest_Subprogram_Mode
+ and then Is_Access_Subprogram_Type (E)
+ then
+ null;
+
-- Normal case of thin pointer
else
diff --git a/gcc/ada/lib-writ.adb b/gcc/ada/lib-writ.adb
index 9a54fa9..a4f9526 100644
--- a/gcc/ada/lib-writ.adb
+++ b/gcc/ada/lib-writ.adb
@@ -744,7 +744,14 @@ package body Lib.Writ is
Note_Unit := U;
end if;
- if Note_Unit = Unit_Num then
+ -- No action needed for pragmas removed by the expander (for
+ -- example, pragmas of ignored ghost entities).
+
+ if Nkind (N) = N_Null_Statement then
+ pragma Assert (Nkind (Original_Node (N)) = N_Pragma);
+ null;
+
+ elsif Note_Unit = Unit_Num then
Write_Info_Initiate ('N');
Write_Info_Char (' ');
@@ -956,10 +963,11 @@ package body Lib.Writ is
-- allow partial analysis on incomplete sources.
if GNATprove_Mode then
-
Body_Fname :=
- Get_File_Name (Get_Body_Name (Uname),
- Subunit => False, May_Fail => True);
+ Get_File_Name
+ (Uname => Get_Body_Name (Uname),
+ Subunit => False,
+ May_Fail => True);
Body_Index := Get_Unit_Index (Get_Body_Name (Uname));
@@ -974,8 +982,10 @@ package body Lib.Writ is
else
Body_Fname :=
- Get_File_Name (Get_Body_Name (Uname),
- Subunit => False, May_Fail => False);
+ Get_File_Name
+ (Uname => Get_Body_Name (Uname),
+ Subunit => False,
+ May_Fail => False);
Body_Index := Get_Unit_Index (Get_Body_Name (Uname));
end if;
diff --git a/gcc/ada/lib-xref-spark_specific.adb b/gcc/ada/lib-xref-spark_specific.adb
index 0ce834a..ce4538b 100644
--- a/gcc/ada/lib-xref-spark_specific.adb
+++ b/gcc/ada/lib-xref-spark_specific.adb
@@ -228,7 +228,18 @@ package body SPARK_Specific is
end loop;
if Nkind (Context) = N_Pragma then
- Context := Parent (Context);
+
+ -- When used for cross-references then aspects might not be
+ -- yet linked to pragmas; when used for AST navigation in
+ -- GNATprove this routine is expected to follow those links.
+
+ if From_Aspect_Specification (Context) then
+ Context := Corresponding_Aspect (Context);
+ pragma Assert (Nkind (Context) = N_Aspect_Specification);
+ Context := Entity (Context);
+ else
+ Context := Parent (Context);
+ end if;
end if;
when N_Entry_Body
diff --git a/gcc/ada/lib-xref.ads b/gcc/ada/lib-xref.ads
index 5c7a086..903e64e 100644
--- a/gcc/ada/lib-xref.ads
+++ b/gcc/ada/lib-xref.ads
@@ -632,6 +632,11 @@ package Lib.Xref is
-- Return the closest enclosing subprogram or library-level package.
-- This ensures that GNATprove can distinguish local variables from
-- global variables.
+ --
+ -- ??? This routine should only be used for processing related to
+ -- cross-references, where it might return wrong result but must avoid
+ -- crashes on ill-formed source code. It is wrong to use it where exact
+ -- result is needed.
procedure Generate_Dereference
(N : Node_Id;
diff --git a/gcc/ada/libgnarl/a-intnam__dragonfly.ads b/gcc/ada/libgnarl/a-intnam__dragonfly.ads
index 1de9735..8fb16f3 100644
--- a/gcc/ada/libgnarl/a-intnam__dragonfly.ads
+++ b/gcc/ada/libgnarl/a-intnam__dragonfly.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1991-2015, Free Software Foundation, Inc. --
+-- Copyright (C) 1991-2018, Free Software Foundation, Inc. --
-- --
-- GNARL 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__dragonfly.adb b/gcc/ada/libgnarl/s-osinte__dragonfly.adb
index dc9e19c..3cf18d1 100644
--- a/gcc/ada/libgnarl/s-osinte__dragonfly.adb
+++ b/gcc/ada/libgnarl/s-osinte__dragonfly.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1991-2015, Free Software Foundation, Inc. --
+-- Copyright (C) 1991-2018, Free Software Foundation, Inc. --
-- --
-- GNARL 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__dragonfly.ads b/gcc/ada/libgnarl/s-osinte__dragonfly.ads
index a67702c..5a4255f 100644
--- a/gcc/ada/libgnarl/s-osinte__dragonfly.ads
+++ b/gcc/ada/libgnarl/s-osinte__dragonfly.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2015, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__gnu.adb b/gcc/ada/libgnarl/s-osinte__gnu.adb
index fb099ac..3147748 100644
--- a/gcc/ada/libgnarl/s-osinte__gnu.adb
+++ b/gcc/ada/libgnarl/s-osinte__gnu.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2015-2016, Free Software Foundation, Inc. --
+-- Copyright (C) 2015-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__gnu.ads b/gcc/ada/libgnarl/s-osinte__gnu.ads
index 183c5b8..0482a4e 100644
--- a/gcc/ada/libgnarl/s-osinte__gnu.ads
+++ b/gcc/ada/libgnarl/s-osinte__gnu.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2016, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__hpux-dce.adb b/gcc/ada/libgnarl/s-osinte__hpux-dce.adb
index a9d46a0..84d5101 100644
--- a/gcc/ada/libgnarl/s-osinte__hpux-dce.adb
+++ b/gcc/ada/libgnarl/s-osinte__hpux-dce.adb
@@ -7,7 +7,7 @@
-- B o d y --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2010, AdaCore --
+-- Copyright (C) 1995-2018, AdaCore --
-- --
-- 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- --
diff --git a/gcc/ada/libgnarl/s-osinte__hpux-dce.ads b/gcc/ada/libgnarl/s-osinte__hpux-dce.ads
index 28fb5ba..36c4b9c 100644
--- a/gcc/ada/libgnarl/s-osinte__hpux-dce.ads
+++ b/gcc/ada/libgnarl/s-osinte__hpux-dce.ads
@@ -7,7 +7,7 @@
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2018, 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- --
diff --git a/gcc/ada/libgnarl/s-taprop__hpux-dce.adb b/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
index 1c5dcc1..6a1bb86 100644
--- a/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
+++ b/gcc/ada/libgnarl/s-taprop__hpux-dce.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2018, Free Software Foundation, Inc. --
-- --
-- GNARL 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- --
diff --git a/gcc/ada/libgnarl/s-taspri__hpux-dce.ads b/gcc/ada/libgnarl/s-taspri__hpux-dce.ads
index 137f34b..9c75f29 100644
--- a/gcc/ada/libgnarl/s-taspri__hpux-dce.ads
+++ b/gcc/ada/libgnarl/s-taspri__hpux-dce.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1991-2014, Free Software Foundation, Inc. --
+-- Copyright (C) 1991-2018, Free Software Foundation, Inc. --
-- --
-- GNARL 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- --
diff --git a/gcc/ada/libgnat/g-dynhta.adb b/gcc/ada/libgnat/g-dynhta.adb
index a6e2734..b093e79 100644
--- a/gcc/ada/libgnat/g-dynhta.adb
+++ b/gcc/ada/libgnat/g-dynhta.adb
@@ -38,11 +38,10 @@ package body GNAT.Dynamic_HTables is
-------------------
package body Static_HTable is
-
function Get_Non_Null (T : Instance) return Elmt_Ptr;
-- Returns Null_Ptr if Iterator_Started is False or if the Table is
- -- empty. Returns Iterator_Ptr if non null, or the next non null
- -- element in table if any.
+ -- empty. Returns Iterator_Ptr if non null, or the next non null element
+ -- in table if any.
---------
-- Get --
@@ -363,7 +362,834 @@ package body GNAT.Dynamic_HTables is
begin
E.Next := Next;
end Set_Next;
-
end Simple_HTable;
+ --------------------
+ -- Dynamic_HTable --
+ --------------------
+
+ package body Dynamic_HTable is
+ Minimum_Size : constant Bucket_Range_Type := 32;
+ -- Minimum size of the buckets
+
+ Safe_Compression_Size : constant Bucket_Range_Type :=
+ Minimum_Size * Compression_Factor;
+ -- Maximum safe size for hash table compression. Beyond this size, a
+ -- compression will violate the minimum size constraint on the buckets.
+
+ Safe_Expansion_Size : constant Bucket_Range_Type :=
+ Bucket_Range_Type'Last / Expansion_Factor;
+ -- Maximum safe size for hash table expansion. Beyond this size, an
+ -- expansion will overflow the buckets.
+
+ procedure Destroy_Buckets (Bkts : Bucket_Table_Ptr);
+ pragma Inline (Destroy_Buckets);
+ -- Destroy all nodes within buckets Bkts
+
+ procedure Detach (Nod : Node_Ptr);
+ pragma Inline (Detach);
+ -- Detach node Nod from the bucket it resides in
+
+ procedure Ensure_Circular (Head : Node_Ptr);
+ pragma Inline (Ensure_Circular);
+ -- Ensure that dummy head Head is circular with respect to itself
+
+ procedure Ensure_Created (T : Instance);
+ pragma Inline (Ensure_Created);
+ -- Verify that hash table T is created. Raise Not_Created if this is not
+ -- the case.
+
+ procedure Ensure_Unlocked (T : Instance);
+ pragma Inline (Ensure_Unlocked);
+ -- Verify that hash table T is unlocked. Raise Table_Locked if this is
+ -- not the case.
+
+ function Find_Bucket
+ (Bkts : Bucket_Table_Ptr;
+ Key : Key_Type) return Node_Ptr;
+ pragma Inline (Find_Bucket);
+ -- Find the bucket among buckets Bkts which corresponds to key Key, and
+ -- return its dummy head.
+
+ function Find_Node (Head : Node_Ptr; Key : Key_Type) return Node_Ptr;
+ pragma Inline (Find_Node);
+ -- Traverse a bucket indicated by dummy head Head to determine whether
+ -- there exists a node with key Key. If such a node exists, return it,
+ -- otherwise return null.
+
+ procedure First_Valid_Node
+ (T : Instance;
+ Low_Bkt : Bucket_Range_Type;
+ High_Bkt : Bucket_Range_Type;
+ Idx : out Bucket_Range_Type;
+ Nod : out Node_Ptr);
+ pragma Inline (First_Valid_Node);
+ -- Find the first valid node in the buckets of hash table T constrained
+ -- by the range Low_Bkt .. High_Bkt. If such a node exists, return its
+ -- bucket index in Idx and reference in Nod. If no such node exists,
+ -- Idx is set to 0 and Nod to null.
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Bucket_Table, Bucket_Table_Ptr);
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Hash_Table, Instance);
+
+ procedure Free is
+ new Ada.Unchecked_Deallocation (Node, Node_Ptr);
+
+ function Is_Valid (Iter : Iterator) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether iterator Iter refers to a valid key-value pair
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether node Nod is non-null and does not refer to dummy
+ -- head Head, thus making it valid.
+
+ function Load_Factor (T : Instance) return Threshold_Type;
+ pragma Inline (Load_Factor);
+ -- Calculate the load factor of hash table T
+
+ procedure Lock (T : Instance);
+ pragma Inline (Lock);
+ -- Lock all mutation functionality of hash table T
+
+ procedure Mutate_And_Rehash (T : Instance; Size : Bucket_Range_Type);
+ pragma Inline (Mutate_And_Rehash);
+ -- Replace the buckets of hash table T with a new set of buckets of size
+ -- Size. Rehash all key-value pairs from the old to the new buckets.
+
+ procedure Prepend (Nod : Node_Ptr; Head : Node_Ptr);
+ pragma Inline (Prepend);
+ -- Insert node Nod immediately after dummy head Head
+
+ procedure Unlock (T : Instance);
+ pragma Inline (Unlock);
+ -- Unlock all mutation functionality of hash table T
+
+ ------------
+ -- Create --
+ ------------
+
+ function Create (Initial_Size : Bucket_Range_Type) return Instance is
+ Size : constant Bucket_Range_Type :=
+ Bucket_Range_Type'Max (Initial_Size, Minimum_Size);
+ -- Ensure that the buckets meet a minimum size
+
+ T : constant Instance := new Hash_Table;
+
+ begin
+ T.Buckets := new Bucket_Table (0 .. Size - 1);
+ T.Initial_Size := Size;
+
+ return T;
+ end Create;
+
+ ------------
+ -- Delete --
+ ------------
+
+ procedure Delete (T : Instance; Key : Key_Type) is
+ procedure Compress;
+ pragma Inline (Compress);
+ -- Determine whether hash table T requires compression, and if so,
+ -- half its size.
+
+ --------------
+ -- Compress --
+ --------------
+
+ procedure Compress is
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ Old_Size : constant Bucket_Range_Type := T.Buckets'Length;
+
+ begin
+ -- The ratio of pairs to buckets is under the desited threshold.
+ -- Compress the hash table only when there is still room to do so.
+
+ if Load_Factor (T) < Compression_Threshold
+ and then Old_Size >= Safe_Compression_Size
+ then
+ Mutate_And_Rehash (T, Old_Size / Compression_Factor);
+ end if;
+ end Compress;
+
+ -- Local variables
+
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ -- Start of processing for Delete
+
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Try to find a node in the bucket which matches the key
+
+ Nod := Find_Node (Head, Key);
+
+ -- If such a node exists, remove it from the bucket and deallocate it
+
+ if Is_Valid (Nod, Head) then
+ Detach (Nod);
+ Free (Nod);
+
+ T.Pairs := T.Pairs - 1;
+
+ -- Compress the hash table if the load factor drops below
+ -- Compression_Threshold.
+
+ Compress;
+ end if;
+ end Delete;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (T : in out Instance) is
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Destroy all nodes in all buckets
+
+ Destroy_Buckets (T.Buckets);
+ Free (T.Buckets);
+ Free (T);
+ end Destroy;
+
+ ---------------------
+ -- Destroy_Buckets --
+ ---------------------
+
+ procedure Destroy_Buckets (Bkts : Bucket_Table_Ptr) is
+ procedure Destroy_Bucket (Head : Node_Ptr);
+ pragma Inline (Destroy_Bucket);
+ -- Destroy all nodes in a bucket with dummy head Head
+
+ --------------------
+ -- Destroy_Bucket --
+ --------------------
+
+ procedure Destroy_Bucket (Head : Node_Ptr) is
+ Nod : Node_Ptr;
+
+ begin
+ -- Destroy all valid nodes which follow the dummy head
+
+ while Is_Valid (Head.Next, Head) loop
+ Nod := Head.Next;
+
+ Detach (Nod);
+ Free (Nod);
+ end loop;
+ end Destroy_Bucket;
+
+ -- Start of processing for Destroy_Buckets
+
+ begin
+ pragma Assert (Bkts /= null);
+
+ for Scan_Idx in Bkts'Range loop
+ Destroy_Bucket (Bkts (Scan_Idx)'Access);
+ end loop;
+ end Destroy_Buckets;
+
+ ------------
+ -- Detach --
+ ------------
+
+ procedure Detach (Nod : Node_Ptr) is
+ pragma Assert (Nod /= null);
+
+ Next : constant Node_Ptr := Nod.Next;
+ Prev : constant Node_Ptr := Nod.Prev;
+
+ begin
+ pragma Assert (Next /= null);
+ pragma Assert (Prev /= null);
+
+ Prev.Next := Next;
+ Next.Prev := Prev;
+
+ Nod.Next := null;
+ Nod.Prev := null;
+ end Detach;
+
+ ---------------------
+ -- Ensure_Circular --
+ ---------------------
+
+ procedure Ensure_Circular (Head : Node_Ptr) is
+ pragma Assert (Head /= null);
+
+ begin
+ if Head.Next = null and then Head.Prev = null then
+ Head.Next := Head;
+ Head.Prev := Head;
+ end if;
+ end Ensure_Circular;
+
+ --------------------
+ -- Ensure_Created --
+ --------------------
+
+ procedure Ensure_Created (T : Instance) is
+ begin
+ if T = null then
+ raise Not_Created;
+ end if;
+ end Ensure_Created;
+
+ ---------------------
+ -- Ensure_Unlocked --
+ ---------------------
+
+ procedure Ensure_Unlocked (T : Instance) is
+ begin
+ pragma Assert (T /= null);
+
+ -- The hash table has at least one outstanding iterator
+
+ if T.Locked > 0 then
+ raise Table_Locked;
+ end if;
+ end Ensure_Unlocked;
+
+ -----------------
+ -- Find_Bucket --
+ -----------------
+
+ function Find_Bucket
+ (Bkts : Bucket_Table_Ptr;
+ Key : Key_Type) return Node_Ptr
+ is
+ pragma Assert (Bkts /= null);
+
+ Idx : constant Bucket_Range_Type := Hash (Key) mod Bkts'Length;
+
+ begin
+ return Bkts (Idx)'Access;
+ end Find_Bucket;
+
+ ---------------
+ -- Find_Node --
+ ---------------
+
+ function Find_Node (Head : Node_Ptr; Key : Key_Type) return Node_Ptr is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- Traverse the nodes of the bucket, looking for a key-value pair
+ -- with the same key.
+
+ Nod := Head.Next;
+ while Is_Valid (Nod, Head) loop
+ if Equivalent_Keys (Nod.Key, Key) then
+ return Nod;
+ end if;
+
+ Nod := Nod.Next;
+ end loop;
+
+ return null;
+ end Find_Node;
+
+ ----------------------
+ -- First_Valid_Node --
+ ----------------------
+
+ procedure First_Valid_Node
+ (T : Instance;
+ Low_Bkt : Bucket_Range_Type;
+ High_Bkt : Bucket_Range_Type;
+ Idx : out Bucket_Range_Type;
+ Nod : out Node_Ptr)
+ is
+ Head : Node_Ptr;
+
+ begin
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ -- Assume that no valid node exists
+
+ Idx := 0;
+ Nod := null;
+
+ -- Examine the buckets of the hash table within the requested range,
+ -- looking for the first valid node.
+
+ for Scan_Idx in Low_Bkt .. High_Bkt loop
+ Head := T.Buckets (Scan_Idx)'Access;
+
+ -- The bucket contains at least one valid node, return the first
+ -- such node.
+
+ if Is_Valid (Head.Next, Head) then
+ Idx := Scan_Idx;
+ Nod := Head.Next;
+ return;
+ end if;
+ end loop;
+ end First_Valid_Node;
+
+ ---------
+ -- Get --
+ ---------
+
+ function Get (T : Instance; Key : Key_Type) return Value_Type is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Try to find a node in the bucket which matches the key
+
+ Nod := Find_Node (Head, Key);
+
+ -- If such a node exists, return the value of the key-value pair
+
+ if Is_Valid (Nod, Head) then
+ return Nod.Value;
+ end if;
+
+ return No_Value;
+ end Get;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Iterator) return Boolean is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+ T : constant Instance := Iter.Table;
+
+ begin
+ pragma Assert (T /= null);
+
+ -- The iterator is no longer valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the hash table
+ -- because the iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (T);
+ end if;
+
+ return Is_OK;
+ end Has_Next;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Iter : Iterator) return Boolean is
+ begin
+ -- The invariant of Iterate and Next ensures that the iterator always
+ -- refers to a valid node if there exists one.
+
+ return Iter.Nod /= null;
+ end Is_Valid;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean is
+ begin
+ -- A node is valid if it is non-null, and does not refer to the dummy
+ -- head of some bucket.
+
+ return Nod /= null and then Nod /= Head;
+ end Is_Valid;
+
+ -------------
+ -- Iterate --
+ -------------
+
+ function Iterate (T : Instance) return Iterator is
+ Iter : Iterator;
+
+ begin
+ Ensure_Created (T);
+ pragma Assert (T.Buckets /= null);
+
+ -- Initialize the iterator to reference the first valid node in
+ -- the full range of hash table buckets. If no such node exists,
+ -- the iterator is left in a state which does not allow it to
+ -- advance.
+
+ First_Valid_Node
+ (T => T,
+ Low_Bkt => T.Buckets'First,
+ High_Bkt => T.Buckets'Last,
+ Idx => Iter.Idx,
+ Nod => Iter.Nod);
+
+ -- Associate the iterator with the hash table to allow for future
+ -- mutation functionality unlocking.
+
+ Iter.Table := T;
+
+ -- Lock all mutation functionality of the hash table while it is
+ -- being iterated on.
+
+ Lock (T);
+
+ return Iter;
+ end Iterate;
+
+ -----------------
+ -- Load_Factor --
+ -----------------
+
+ function Load_Factor (T : Instance) return Threshold_Type is
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ begin
+ -- The load factor is the ratio of key-value pairs to buckets
+
+ return Threshold_Type (T.Pairs) / Threshold_Type (T.Buckets'Length);
+ end Load_Factor;
+
+ ----------
+ -- Lock --
+ ----------
+
+ procedure Lock (T : Instance) is
+ begin
+ -- The hash table may be locked multiple times if multiple iterators
+ -- are operating over it.
+
+ T.Locked := T.Locked + 1;
+ end Lock;
+
+ -----------------------
+ -- Mutate_And_Rehash --
+ -----------------------
+
+ procedure Mutate_And_Rehash (T : Instance; Size : Bucket_Range_Type) is
+ procedure Rehash (From : Bucket_Table_Ptr; To : Bucket_Table_Ptr);
+ pragma Inline (Rehash);
+ -- Remove all nodes from buckets From and rehash them into buckets To
+
+ procedure Rehash_Bucket (Head : Node_Ptr; To : Bucket_Table_Ptr);
+ pragma Inline (Rehash_Bucket);
+ -- Detach all nodes starting from dummy head Head and rehash them
+ -- into To.
+
+ procedure Rehash_Node (Nod : Node_Ptr; To : Bucket_Table_Ptr);
+ pragma Inline (Rehash_Node);
+ -- Rehash node Nod into To
+
+ ------------
+ -- Rehash --
+ ------------
+
+ procedure Rehash (From : Bucket_Table_Ptr; To : Bucket_Table_Ptr) is
+ begin
+ pragma Assert (From /= null);
+ pragma Assert (To /= null);
+
+ for Scan_Idx in From'Range loop
+ Rehash_Bucket (From (Scan_Idx)'Access, To);
+ end loop;
+ end Rehash;
+
+ -------------------
+ -- Rehash_Bucket --
+ -------------------
+
+ procedure Rehash_Bucket (Head : Node_Ptr; To : Bucket_Table_Ptr) is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- Detach all nodes which follow the dummy head
+
+ while Is_Valid (Head.Next, Head) loop
+ Nod := Head.Next;
+
+ Detach (Nod);
+ Rehash_Node (Nod, To);
+ end loop;
+ end Rehash_Bucket;
+
+ -----------------
+ -- Rehash_Node --
+ -----------------
+
+ procedure Rehash_Node (Nod : Node_Ptr; To : Bucket_Table_Ptr) is
+ pragma Assert (Nod /= null);
+
+ Head : Node_Ptr;
+
+ begin
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (To, Nod.Key);
+
+ -- Ensure that the dummy head of an empty bucket is circular with
+ -- respect to itself.
+
+ Ensure_Circular (Head);
+
+ -- Prepend the node to the bucket
+
+ Prepend (Nod, Head);
+ end Rehash_Node;
+
+ -- Local declarations
+
+ Old_Bkts : Bucket_Table_Ptr;
+
+ -- Start of processing for Mutate_And_Rehash
+
+ begin
+ pragma Assert (T /= null);
+
+ Old_Bkts := T.Buckets;
+ T.Buckets := new Bucket_Table (0 .. Size - 1);
+
+ -- Transfer and rehash all key-value pairs from the old buckets to
+ -- the new buckets.
+
+ Rehash (From => Old_Bkts, To => T.Buckets);
+ Free (Old_Bkts);
+ end Mutate_And_Rehash;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next (Iter : in out Iterator; Key : out Key_Type) is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+ Saved : constant Node_Ptr := Iter.Nod;
+ T : constant Instance := Iter.Table;
+ Head : Node_Ptr;
+
+ begin
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ -- The iterator is no longer valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the hash table as
+ -- the iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (T);
+ raise Iterator_Exhausted;
+ end if;
+
+ -- Advance to the next node along the same bucket
+
+ Iter.Nod := Iter.Nod.Next;
+ Head := T.Buckets (Iter.Idx)'Access;
+
+ -- If the new node is no longer valid, then this indicates that the
+ -- current bucket has been exhausted. Advance to the next valid node
+ -- within the remaining range of buckets. If no such node exists, the
+ -- iterator is left in a state which does not allow it to advance.
+
+ if not Is_Valid (Iter.Nod, Head) then
+ First_Valid_Node
+ (T => T,
+ Low_Bkt => Iter.Idx + 1,
+ High_Bkt => T.Buckets'Last,
+ Idx => Iter.Idx,
+ Nod => Iter.Nod);
+ end if;
+
+ Key := Saved.Key;
+ end Next;
+
+ -------------
+ -- Prepend --
+ -------------
+
+ procedure Prepend (Nod : Node_Ptr; Head : Node_Ptr) is
+ pragma Assert (Nod /= null);
+ pragma Assert (Head /= null);
+
+ Next : constant Node_Ptr := Head.Next;
+
+ begin
+ Head.Next := Nod;
+ Next.Prev := Nod;
+
+ Nod.Next := Next;
+ Nod.Prev := Head;
+ end Prepend;
+
+ ---------
+ -- Put --
+ ---------
+
+ procedure Put
+ (T : Instance;
+ Key : Key_Type;
+ Value : Value_Type)
+ is
+ procedure Expand;
+ pragma Inline (Expand);
+ -- Determine whether hash table T requires expansion, and if so,
+ -- double its size.
+
+ procedure Prepend_Or_Replace (Head : Node_Ptr);
+ pragma Inline (Prepend_Or_Replace);
+ -- Update the value of a node within a bucket with dummy head Head
+ -- whose key is Key to Value. If there is no such node, prepend a new
+ -- key-value pair to the bucket.
+
+ ------------
+ -- Expand --
+ ------------
+
+ procedure Expand is
+ pragma Assert (T /= null);
+ pragma Assert (T.Buckets /= null);
+
+ Old_Size : constant Bucket_Range_Type := T.Buckets'Length;
+
+ begin
+ -- The ratio of pairs to buckets is over the desited threshold.
+ -- Expand the hash table only when there is still room to do so.
+
+ if Load_Factor (T) > Expansion_Threshold
+ and then Old_Size <= Safe_Expansion_Size
+ then
+ Mutate_And_Rehash (T, Old_Size * Expansion_Factor);
+ end if;
+ end Expand;
+
+ ------------------------
+ -- Prepend_Or_Replace --
+ ------------------------
+
+ procedure Prepend_Or_Replace (Head : Node_Ptr) is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- If the bucket containst at least one valid node, then there is
+ -- a chance that a node with the same key as Key exists. If this
+ -- is the case, the value of that node must be updated.
+
+ Nod := Head.Next;
+ while Is_Valid (Nod, Head) loop
+ if Equivalent_Keys (Nod.Key, Key) then
+ Nod.Value := Value;
+ return;
+ end if;
+
+ Nod := Nod.Next;
+ end loop;
+
+ -- At this point the bucket is either empty, or none of the nodes
+ -- match key Key. Prepend a new key-value pair.
+
+ Nod := new Node'(Key, Value, null, null);
+
+ Prepend (Nod, Head);
+ end Prepend_Or_Replace;
+
+ -- Local variables
+
+ Head : Node_Ptr;
+
+ -- Start of processing for Put
+
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Obtain the dummy head of the bucket which should house the
+ -- key-value pair.
+
+ Head := Find_Bucket (T.Buckets, Key);
+
+ -- Ensure that the dummy head of an empty bucket is circular with
+ -- respect to itself.
+
+ Ensure_Circular (Head);
+
+ -- In case the bucket already contains a node with the same key,
+ -- replace its value, otherwise prepend a new key-value pair.
+
+ Prepend_Or_Replace (Head);
+
+ T.Pairs := T.Pairs + 1;
+
+ -- Expand the hash table if the ratio of pairs to buckets goes over
+ -- Expansion_Threshold.
+
+ Expand;
+ end Put;
+
+ -----------
+ -- Reset --
+ -----------
+
+ procedure Reset (T : Instance) is
+ begin
+ Ensure_Created (T);
+ Ensure_Unlocked (T);
+
+ -- Destroy all nodes in all buckets
+
+ Destroy_Buckets (T.Buckets);
+ Free (T.Buckets);
+
+ -- Recreate the buckets using the original size from creation time
+
+ T.Buckets := new Bucket_Table (0 .. T.Initial_Size - 1);
+ T.Pairs := 0;
+ end Reset;
+
+ ----------
+ -- Size --
+ ----------
+
+ function Size (T : Instance) return Pair_Count_Type is
+ begin
+ Ensure_Created (T);
+
+ return T.Pairs;
+ end Size;
+
+ ------------
+ -- Unlock --
+ ------------
+
+ procedure Unlock (T : Instance) is
+ begin
+ -- The hash table may be locked multiple times if multiple iterators
+ -- are operating over it.
+
+ T.Locked := T.Locked - 1;
+ end Unlock;
+ end Dynamic_HTable;
+
end GNAT.Dynamic_HTables;
diff --git a/gcc/ada/libgnat/g-dynhta.ads b/gcc/ada/libgnat/g-dynhta.ads
index ea331c0..41574fd 100644
--- a/gcc/ada/libgnat/g-dynhta.ads
+++ b/gcc/ada/libgnat/g-dynhta.ads
@@ -31,13 +31,11 @@
-- Hash table searching routines
--- This package contains three separate packages. The Simple_HTable package
+-- This package contains two separate packages. The Simple_HTable package
-- provides a very simple abstraction that associates one element to one key
-- value and takes care of all allocations automatically using the heap. The
-- Static_HTable package provides a more complex interface that allows full
--- control over allocation. The Load_Factor_HTable package provides a more
--- complex abstraction where collisions are resolved by chaining, and the
--- table grows by a percentage after the load factor has been exceeded.
+-- control over allocation.
-- This package provides a facility similar to that of GNAT.HTable, except
-- that this package declares types that can be used to define dynamic
@@ -48,6 +46,8 @@
-- GNAT.HTable to keep as much coherency as possible between these two
-- related units.
+pragma Compiler_Unit_Warning;
+
package GNAT.Dynamic_HTables is
-------------------
@@ -85,40 +85,38 @@ package GNAT.Dynamic_HTables is
Null_Ptr : Elmt_Ptr;
-- The null value of the Elmt_Ptr type
+ with function Next (E : Elmt_Ptr) return Elmt_Ptr;
with procedure Set_Next (E : Elmt_Ptr; Next : Elmt_Ptr);
- with function Next (E : Elmt_Ptr) return Elmt_Ptr;
-- The type must provide an internal link for the sake of the
-- staticness of the HTable.
type Key is limited private;
with function Get_Key (E : Elmt_Ptr) return Key;
- with function Hash (F : Key) return Header_Num;
- with function Equal (F1, F2 : Key) return Boolean;
+ with function Hash (F : Key) return Header_Num;
+ with function Equal (F1 : Key; F2 : Key) return Boolean;
package Static_HTable is
-
type Instance is private;
Nil : constant Instance;
procedure Reset (T : in out Instance);
- -- Resets the hash table by releasing all memory associated with
- -- it. The hash table can safely be reused after this call. For the
- -- most common case where Elmt_Ptr is an access type, and Null_Ptr is
- -- null, this is only needed if the same table is reused in a new
- -- context. If Elmt_Ptr is other than an access type, or Null_Ptr is
- -- other than null, then Reset must be called before the first use of
- -- the hash table.
+ -- Resets the hash table by releasing all memory associated with it. The
+ -- hash table can safely be reused after this call. For the most common
+ -- case where Elmt_Ptr is an access type, and Null_Ptr is null, this is
+ -- only needed if the same table is reused in a new context. If Elmt_Ptr
+ -- is other than an access type, or Null_Ptr is other than null, then
+ -- Reset must be called before the first use of the hash table.
procedure Set (T : in out Instance; E : Elmt_Ptr);
-- Insert the element pointer in the HTable
function Get (T : Instance; K : Key) return Elmt_Ptr;
- -- Returns the latest inserted element pointer with the given Key
- -- or null if none.
+ -- Returns the latest inserted element pointer with the given Key or
+ -- null if none.
procedure Remove (T : Instance; K : Key);
- -- Removes the latest inserted element pointer associated with the
- -- given key if any, does nothing if none.
+ -- Removes the latest inserted element pointer associated with the given
+ -- key if any, does nothing if none.
function Get_First (T : Instance) return Elmt_Ptr;
-- Returns Null_Ptr if the Htable is empty, otherwise returns one
@@ -126,11 +124,11 @@ package GNAT.Dynamic_HTables is
-- function will return the same element.
function Get_Next (T : Instance) return Elmt_Ptr;
- -- Returns an unspecified element that has not been returned by the
- -- same function since the last call to Get_First or Null_Ptr if
- -- there is no such element or Get_First has never been called. If
- -- there is no call to 'Set' in between Get_Next calls, all the
- -- elements of the Htable will be traversed.
+ -- Returns an unspecified element that has not been returned by the same
+ -- function since the last call to Get_First or Null_Ptr if there is no
+ -- such element or Get_First has never been called. If there is no call
+ -- to 'Set' in between Get_Next calls, all the elements of the Htable
+ -- will be traversed.
private
type Table_Type is array (Header_Num) of Elmt_Ptr;
@@ -169,11 +167,10 @@ package GNAT.Dynamic_HTables is
-- a given key
type Key is private;
- with function Hash (F : Key) return Header_Num;
- with function Equal (F1, F2 : Key) return Boolean;
+ with function Hash (F : Key) return Header_Num;
+ with function Equal (F1 : Key; F2 : Key) return Boolean;
package Simple_HTable is
-
type Instance is private;
Nil : constant Instance;
@@ -233,7 +230,6 @@ package GNAT.Dynamic_HTables is
-- same restrictions apply as Get_Next.
private
-
type Element_Wrapper;
type Elmt_Ptr is access all Element_Wrapper;
type Element_Wrapper is record
@@ -260,7 +256,263 @@ package GNAT.Dynamic_HTables is
type Instance is new Tab.Instance;
Nil : constant Instance := Instance (Tab.Nil);
-
end Simple_HTable;
+ --------------------
+ -- Dynamic_HTable --
+ --------------------
+
+ -- The following package offers a hash table abstraction with the following
+ -- characteristics:
+ --
+ -- * Dynamic resizing based on load factor.
+ -- * Creation of multiple instances, of different sizes.
+ -- * Iterable keys.
+ --
+ -- This type of hash table is best used in scenarios where the size of the
+ -- key set is not known. The dynamic resizing aspect allows for performance
+ -- to remain within reasonable bounds as the size of the key set grows.
+ --
+ -- The following use pattern must be employed when operating this table:
+ --
+ -- Table : Instance := Create (<some size>);
+ --
+ -- <various operations>
+ --
+ -- Destroy (Table);
+ --
+ -- The destruction of the table reclaims all storage occupied by it.
+
+ -- The following type denotes the underlying range of the hash table
+ -- buckets.
+
+ type Bucket_Range_Type is mod 2 ** 32;
+
+ -- The following type denotes the multiplicative factor used in expansion
+ -- and compression of the hash table.
+
+ subtype Factor_Type is Bucket_Range_Type range 2 .. 100;
+
+ -- The following type denotes the number of key-value pairs stored in the
+ -- hash table.
+
+ type Pair_Count_Type is range 0 .. 2 ** 31 - 1;
+
+ -- The following type denotes the threshold range used in expansion and
+ -- compression of the hash table.
+
+ subtype Threshold_Type is Long_Float range 0.0 .. Long_Float'Last;
+
+ generic
+ type Key_Type is private;
+ type Value_Type is private;
+ -- The types of the key-value pairs stored in the hash table
+
+ No_Value : Value_Type;
+ -- An indicator for a non-existent value
+
+ Expansion_Threshold : Threshold_Type;
+ Expansion_Factor : Factor_Type;
+ -- Once the load factor goes over Expansion_Threshold, the size of the
+ -- buckets is increased using the formula
+ --
+ -- New_Size = Old_Size * Expansion_Factor
+ --
+ -- An Expansion_Threshold of 1.5 and Expansion_Factor of 2 indicate that
+ -- the size of the buckets will be doubled once the load factor exceeds
+ -- 1.5.
+
+ Compression_Threshold : Threshold_Type;
+ Compression_Factor : Factor_Type;
+ -- Once the load factor drops below Compression_Threshold, the size of
+ -- the buckets is decreased using the formula
+ --
+ -- New_Size = Old_Size / Compression_Factor
+ --
+ -- A Compression_Threshold of 0.5 and Compression_Factor of 2 indicate
+ -- that the size of the buckets will be halved once the load factor
+ -- drops below 0.5.
+
+ with function Equivalent_Keys
+ (Left : Key_Type;
+ Right : Key_Type) return Boolean;
+ -- Determine whether two keys are equivalent
+
+ with function Hash (Key : Key_Type) return Bucket_Range_Type;
+ -- Map an arbitrary key into the range of buckets
+
+ package Dynamic_HTable is
+
+ ----------------------
+ -- Table operations --
+ ----------------------
+
+ -- The following type denotes a hash table handle. Each instance must be
+ -- created using routine Create.
+
+ type Instance is private;
+ Nil : constant Instance;
+
+ Not_Created : exception;
+ -- This exception is raised when the hash table has not been created by
+ -- routine Create, and an attempt is made to read or mutate its state.
+
+ Table_Locked : exception;
+ -- This exception is raised when the hash table is being iterated on,
+ -- and an attempt is made to mutate its state.
+
+ function Create (Initial_Size : Bucket_Range_Type) return Instance;
+ -- Create a new table with bucket capacity Initial_Size. This routine
+ -- must be called at the start of a hash table's lifetime.
+
+ procedure Delete (T : Instance; Key : Key_Type);
+ -- Delete the value which corresponds to key Key from hash table T. The
+ -- routine has no effect if the value is not present in the hash table.
+ -- This action will raise Table_Locked if the hash table has outstanding
+ -- iterators. If the load factor drops below Compression_Threshold, the
+ -- size of the buckets is decreased by Copression_Factor.
+
+ procedure Destroy (T : in out Instance);
+ -- Destroy the contents of hash table T, rendering it unusable. This
+ -- routine must be called at the end of a hash table's lifetime. This
+ -- action will raise Table_Locked if the hash table has outstanding
+ -- iterators.
+
+ function Get (T : Instance; Key : Key_Type) return Value_Type;
+ -- Obtain the value which corresponds to key Key from hash table T. If
+ -- the value does not exist, return No_Value.
+
+ procedure Put
+ (T : Instance;
+ Key : Key_Type;
+ Value : Value_Type);
+ -- Associate value Value with key Key in hash table T. If the table
+ -- already contains a mapping of the same key to a previous value, the
+ -- previous value is overwritten. This action will raise Table_Locked
+ -- if the hash table has outstanding iterators. If the load factor goes
+ -- over Expansion_Threshold, the size of the buckets is increased by
+ -- Expansion_Factor.
+
+ procedure Reset (T : Instance);
+ -- Destroy the contents of hash table T, and reset it to its initial
+ -- created state. This action will raise Table_Locked if the hash table
+ -- has outstanding iterators.
+
+ function Size (T : Instance) return Pair_Count_Type;
+ -- Obtain the number of key-value pairs in hash table T
+
+ -------------------------
+ -- Iterator operations --
+ -------------------------
+
+ -- The following type represents a key iterator. An iterator locks
+ -- all mutation operations, and unlocks them once it is exhausted.
+ -- The iterator must be used with the following pattern:
+ --
+ -- Iter := Iterate (My_Table);
+ -- while Has_Next (Iter) loop
+ -- Key := Next (Iter);
+ -- . . .
+ -- end loop;
+ --
+ -- It is possible to advance the iterator by using Next only, however
+ -- this risks raising Iterator_Exhausted.
+
+ type Iterator is private;
+
+ Iterator_Exhausted : exception;
+ -- This exception is raised when an iterator is exhausted and further
+ -- attempts to advance it are made by calling routine Next.
+
+ function Iterate (T : Instance) return Iterator;
+ -- Obtain an iterator over the keys of hash table T. This action locks
+ -- all mutation functionality of the associated hash table.
+
+ function Has_Next (Iter : Iterator) return Boolean;
+ -- Determine whether iterator Iter has more keys to examine. If the
+ -- iterator has been exhausted, restore all mutation functionality of
+ -- the associated hash table.
+
+ procedure Next
+ (Iter : in out Iterator;
+ Key : out Key_Type);
+ -- Return the current key referenced by iterator Iter and advance to
+ -- the next available key. If the iterator has been exhausted and
+ -- further attempts are made to advance it, this routine restores
+ -- mutation functionality of the associated hash table, and then
+ -- raises Iterator_Exhausted.
+
+ private
+ -- The following type represents a doubly linked list node used to
+ -- store a key-value pair. There are several reasons to use a doubly
+ -- linked list:
+ --
+ -- * Most read and write operations utilize the same primitve
+ -- routines to locate, create, and delete a node, allowing for
+ -- greater degree of code sharing.
+ --
+ -- * Special cases are eliminated by maintaining a circular node
+ -- list with a dummy head (see type Bucket_Table).
+ --
+ -- A node is said to be "valid" if it is non-null, and does not refer to
+ -- the dummy head of some bucket.
+
+ type Node;
+ type Node_Ptr is access all Node;
+ type Node is record
+ Key : Key_Type;
+ Value : Value_Type := No_Value;
+ -- Key-value pair stored in a bucket
+
+ Prev : Node_Ptr := null;
+ Next : Node_Ptr := null;
+ end record;
+
+ -- The following type represents a bucket table. Each bucket contains a
+ -- circular doubly linked list of nodes with a dummy head. Initially,
+ -- the head does not refer to itself. This is intentional because it
+ -- improves the performance of creation, compression, and expansion by
+ -- avoiding a separate pass to link a head to itself. Several routines
+ -- ensure that the head is properly formed.
+
+ type Bucket_Table is array (Bucket_Range_Type range <>) of aliased Node;
+ type Bucket_Table_Ptr is access Bucket_Table;
+
+ -- The following type represents a hash table
+
+ type Hash_Table is record
+ Buckets : Bucket_Table_Ptr := null;
+ -- Reference to the compressing / expanding buckets
+
+ Initial_Size : Bucket_Range_Type := 0;
+ -- The initial size of the buckets as specified at creation time
+
+ Locked : Natural := 0;
+ -- Number of outstanding iterators
+
+ Pairs : Pair_Count_Type := 0;
+ -- Number of key-value pairs in the buckets
+ end record;
+
+ type Instance is access Hash_Table;
+ Nil : constant Instance := null;
+
+ -- The following type represents a key iterator
+
+ type Iterator is record
+ Idx : Bucket_Range_Type := 0;
+ -- Index of the current bucket being examined. This index is always
+ -- kept within the range of the buckets.
+
+ Nod : Node_Ptr := null;
+ -- Reference to the current node being examined within the current
+ -- bucket. The invariant of the iterator requires that this field
+ -- always point to a valid node. A value of null indicates that the
+ -- iterator is exhausted.
+
+ Table : Instance := null;
+ -- Reference to the associated hash table
+ end record;
+ end Dynamic_HTable;
+
end GNAT.Dynamic_HTables;
diff --git a/gcc/ada/libgnat/g-lists.adb b/gcc/ada/libgnat/g-lists.adb
new file mode 100644
index 0000000..a058f33
--- /dev/null
+++ b/gcc/ada/libgnat/g-lists.adb
@@ -0,0 +1,635 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . L I S T S --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with Ada.Unchecked_Deallocation;
+
+package body GNAT.Lists is
+
+ package body Doubly_Linked_List is
+ procedure Delete_Node (L : Instance; Nod : Node_Ptr);
+ pragma Inline (Delete_Node);
+ -- Detach and delete node Nod from list L
+
+ procedure Ensure_Circular (Head : Node_Ptr);
+ pragma Inline (Ensure_Circular);
+ -- Ensure that dummy head Head is circular with respect to itself
+
+ procedure Ensure_Created (L : Instance);
+ pragma Inline (Ensure_Created);
+ -- Verify that list L is created. Raise Not_Created if this is not the
+ -- case.
+
+ procedure Ensure_Full (L : Instance);
+ pragma Inline (Ensure_Full);
+ -- Verify that list L contains at least one element. Raise List_Empty if
+ -- this is not the case.
+
+ procedure Ensure_Unlocked (L : Instance);
+ pragma Inline (Ensure_Unlocked);
+ -- Verify that list L is unlocked. Raise List_Locked if this is not the
+ -- case.
+
+ function Find_Node
+ (Head : Node_Ptr;
+ Elem : Element_Type) return Node_Ptr;
+ pragma Inline (Find_Node);
+ -- Travers a list indicated by dummy head Head to determine whethe there
+ -- exists a node with element Elem. If such a node exists, return it,
+ -- otherwise return null;
+
+ procedure Free is new Ada.Unchecked_Deallocation (Linked_List, Instance);
+
+ procedure Free is new Ada.Unchecked_Deallocation (Node, Node_Ptr);
+
+ procedure Insert_Between
+ (L : Instance;
+ Elem : Element_Type;
+ Left : Node_Ptr;
+ Right : Node_Ptr);
+ pragma Inline (Insert_Between);
+ -- Insert element Elem between nodes Left and Right of list L
+
+ function Is_Valid (Iter : Iterator) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether iterator Iter refers to a valid element
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean;
+ pragma Inline (Is_Valid);
+ -- Determine whether node Nod is non-null and does not refer to dummy
+ -- head Head, thus making it valid.
+
+ procedure Lock (L : Instance);
+ pragma Inline (Lock);
+ -- Lock all mutation functionality of list L
+
+ procedure Unlock (L : Instance);
+ pragma Inline (Unlock);
+ -- Unlock all mutation functionality of list L
+
+ ------------
+ -- Append --
+ ------------
+
+ procedure Append (L : Instance; Elem : Element_Type) is
+ Head : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ -- Ensure that the dummy head of an empty list is circular with
+ -- respect to itself.
+
+ Head := L.Nodes'Access;
+ Ensure_Circular (Head);
+
+ -- Append the node by inserting it between the last node and the
+ -- dummy head.
+
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Head.Prev,
+ Right => Head);
+ end Append;
+
+ ------------
+ -- Create --
+ ------------
+
+ function Create return Instance is
+ begin
+ return new Linked_List;
+ end Create;
+
+ --------------
+ -- Contains --
+ --------------
+
+ function Contains (L : Instance; Elem : Element_Type) return Boolean is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Elem);
+
+ return Is_Valid (Nod, Head);
+ end Contains;
+
+ ------------
+ -- Delete --
+ ------------
+
+ procedure Delete (L : Instance; Elem : Element_Type) is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Elem);
+
+ if Is_Valid (Nod, Head) then
+ Delete_Node (L, Nod);
+ end if;
+ end Delete;
+
+ ------------------
+ -- Delete_First --
+ ------------------
+
+ procedure Delete_First (L : Instance) is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Head.Next;
+
+ if Is_Valid (Nod, Head) then
+ Delete_Node (L, Nod);
+ end if;
+ end Delete_First;
+
+ -----------------
+ -- Delete_Last --
+ -----------------
+
+ procedure Delete_Last (L : Instance) is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Head.Prev;
+
+ if Is_Valid (Nod, Head) then
+ Delete_Node (L, Nod);
+ end if;
+ end Delete_Last;
+
+ -----------------
+ -- Delete_Node --
+ -----------------
+
+ procedure Delete_Node (L : Instance; Nod : Node_Ptr) is
+ Ref : Node_Ptr := Nod;
+
+ pragma Assert (Ref /= null);
+
+ Next : constant Node_Ptr := Ref.Next;
+ Prev : constant Node_Ptr := Ref.Prev;
+
+ begin
+ pragma Assert (L /= null);
+ pragma Assert (Next /= null);
+ pragma Assert (Prev /= null);
+
+ Prev.Next := Next; -- Prev ---> Next
+ Next.Prev := Prev; -- Prev <--> Next
+
+ Ref.Next := null;
+ Ref.Prev := null;
+
+ L.Elements := L.Elements - 1;
+
+ Free (Ref);
+ end Delete_Node;
+
+ -------------
+ -- Destroy --
+ -------------
+
+ procedure Destroy (L : in out Instance) is
+ Head : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+
+ while Is_Valid (Head.Next, Head) loop
+ Delete_Node (L, Head.Next);
+ end loop;
+
+ Free (L);
+ end Destroy;
+
+ ---------------------
+ -- Ensure_Circular --
+ ---------------------
+
+ procedure Ensure_Circular (Head : Node_Ptr) is
+ pragma Assert (Head /= null);
+
+ begin
+ if Head.Next = null and then Head.Prev = null then
+ Head.Next := Head;
+ Head.Prev := Head;
+ end if;
+ end Ensure_Circular;
+
+ --------------------
+ -- Ensure_Created --
+ --------------------
+
+ procedure Ensure_Created (L : Instance) is
+ begin
+ if L = null then
+ raise Not_Created;
+ end if;
+ end Ensure_Created;
+
+ -----------------
+ -- Ensure_Full --
+ -----------------
+
+ procedure Ensure_Full (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ if L.Elements = 0 then
+ raise List_Empty;
+ end if;
+ end Ensure_Full;
+
+ ---------------------
+ -- Ensure_Unlocked --
+ ---------------------
+
+ procedure Ensure_Unlocked (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ -- The list has at least one outstanding iterator
+
+ if L.Locked > 0 then
+ raise List_Locked;
+ end if;
+ end Ensure_Unlocked;
+
+ ---------------
+ -- Find_Node --
+ ---------------
+
+ function Find_Node
+ (Head : Node_Ptr;
+ Elem : Element_Type) return Node_Ptr
+ is
+ pragma Assert (Head /= null);
+
+ Nod : Node_Ptr;
+
+ begin
+ -- Traverse the nodes of the list, looking for a matching element
+
+ Nod := Head.Next;
+ while Is_Valid (Nod, Head) loop
+ if Nod.Elem = Elem then
+ return Nod;
+ end if;
+
+ Nod := Nod.Next;
+ end loop;
+
+ return null;
+ end Find_Node;
+
+ -----------
+ -- First --
+ -----------
+
+ function First (L : Instance) return Element_Type is
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+
+ return L.Nodes.Next.Elem;
+ end First;
+
+ --------------
+ -- Has_Next --
+ --------------
+
+ function Has_Next (Iter : Iterator) return Boolean is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+
+ begin
+ -- The iterator is no longer valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the list because
+ -- the iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (Iter.List);
+ end if;
+
+ return Is_OK;
+ end Has_Next;
+
+ ------------------
+ -- Insert_After --
+ ------------------
+
+ procedure Insert_After
+ (L : Instance;
+ After : Element_Type;
+ Elem : Element_Type)
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, After);
+
+ if Is_Valid (Nod, Head) then
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Nod,
+ Right => Nod.Next);
+ end if;
+ end Insert_After;
+
+ -------------------
+ -- Insert_Before --
+ -------------------
+
+ procedure Insert_Before
+ (L : Instance;
+ Before : Element_Type;
+ Elem : Element_Type)
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Before);
+
+ if Is_Valid (Nod, Head) then
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Nod.Prev,
+ Right => Nod);
+ end if;
+ end Insert_Before;
+
+ --------------------
+ -- Insert_Between --
+ --------------------
+
+ procedure Insert_Between
+ (L : Instance;
+ Elem : Element_Type;
+ Left : Node_Ptr;
+ Right : Node_Ptr)
+ is
+ pragma Assert (L /= null);
+ pragma Assert (Left /= null);
+ pragma Assert (Right /= null);
+
+ Nod : constant Node_Ptr :=
+ new Node'(Elem => Elem,
+ Next => Right, -- Left Nod ---> Right
+ Prev => Left); -- Left <--- Nod ---> Right
+
+ begin
+ Left.Next := Nod; -- Left <--> Nod ---> Right
+ Right.Prev := Nod; -- Left <--> Nod <--> Right
+
+ L.Elements := L.Elements + 1;
+ end Insert_Between;
+
+ --------------
+ -- Is_Empty --
+ --------------
+
+ function Is_Empty (L : Instance) return Boolean is
+ begin
+ Ensure_Created (L);
+
+ return L.Elements = 0;
+ end Is_Empty;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Iter : Iterator) return Boolean is
+ begin
+ -- The invariant of Iterate and Next ensures that the iterator always
+ -- refers to a valid node if there exists one.
+
+ return Is_Valid (Iter.Nod, Iter.List.Nodes'Access);
+ end Is_Valid;
+
+ --------------
+ -- Is_Valid --
+ --------------
+
+ function Is_Valid (Nod : Node_Ptr; Head : Node_Ptr) return Boolean is
+ begin
+ -- A node is valid if it is non-null, and does not refer to the dummy
+ -- head of some list.
+
+ return Nod /= null and then Nod /= Head;
+ end Is_Valid;
+
+ -------------
+ -- Iterate --
+ -------------
+
+ function Iterate (L : Instance) return Iterator is
+ begin
+ Ensure_Created (L);
+
+ -- Lock all mutation functionality of the list while it is being
+ -- iterated on.
+
+ Lock (L);
+
+ return (List => L, Nod => L.Nodes.Next);
+ end Iterate;
+
+ ----------
+ -- Last --
+ ----------
+
+ function Last (L : Instance) return Element_Type is
+ begin
+ Ensure_Created (L);
+ Ensure_Full (L);
+
+ return L.Nodes.Prev.Elem;
+ end Last;
+
+ ------------
+ -- Length --
+ ------------
+
+ function Length (L : Instance) return Element_Count_Type is
+ begin
+ Ensure_Created (L);
+
+ return L.Elements;
+ end Length;
+
+ ----------
+ -- Lock --
+ ----------
+
+ procedure Lock (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ -- The list may be locked multiple times if multiple iterators are
+ -- operating over it.
+
+ L.Locked := L.Locked + 1;
+ end Lock;
+
+ ----------
+ -- Next --
+ ----------
+
+ procedure Next
+ (Iter : in out Iterator;
+ Elem : out Element_Type)
+ is
+ Is_OK : constant Boolean := Is_Valid (Iter);
+ Saved : constant Node_Ptr := Iter.Nod;
+
+ begin
+ -- The iterator is no linger valid which indicates that it has been
+ -- exhausted. Unlock all mutation functionality of the list as the
+ -- iterator cannot be advanced any further.
+
+ if not Is_OK then
+ Unlock (Iter.List);
+ raise Iterator_Exhausted;
+ end if;
+
+ -- Advance to the next node along the list
+
+ Iter.Nod := Iter.Nod.Next;
+ Elem := Saved.Elem;
+ end Next;
+
+ -------------
+ -- Prepend --
+ -------------
+
+ procedure Prepend (L : Instance; Elem : Element_Type) is
+ Head : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ -- Ensure that the dummy head of an empty list is circular with
+ -- respect to itself.
+
+ Head := L.Nodes'Access;
+ Ensure_Circular (Head);
+
+ -- Append the node by inserting it between the dummy head and the
+ -- first node.
+
+ Insert_Between
+ (L => L,
+ Elem => Elem,
+ Left => Head,
+ Right => Head.Next);
+ end Prepend;
+
+ -------------
+ -- Replace --
+ -------------
+
+ procedure Replace
+ (L : Instance;
+ Old_Elem : Element_Type;
+ New_Elem : Element_Type)
+ is
+ Head : Node_Ptr;
+ Nod : Node_Ptr;
+
+ begin
+ Ensure_Created (L);
+ Ensure_Unlocked (L);
+
+ Head := L.Nodes'Access;
+ Nod := Find_Node (Head, Old_Elem);
+
+ if Is_Valid (Nod, Head) then
+ Nod.Elem := New_Elem;
+ end if;
+ end Replace;
+
+ ------------
+ -- Unlock --
+ ------------
+
+ procedure Unlock (L : Instance) is
+ begin
+ pragma Assert (L /= null);
+
+ -- The list may be locked multiple times if multiple iterators are
+ -- operating over it.
+
+ L.Locked := L.Locked - 1;
+ end Unlock;
+ end Doubly_Linked_List;
+
+end GNAT.Lists;
diff --git a/gcc/ada/libgnat/g-lists.ads b/gcc/ada/libgnat/g-lists.ads
new file mode 100644
index 0000000..777b4f6
--- /dev/null
+++ b/gcc/ada/libgnat/g-lists.ads
@@ -0,0 +1,245 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- G N A T . L I S T S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Compiler_Unit_Warning;
+
+package GNAT.Lists is
+
+ ------------------------
+ -- Doubly_Linked_List --
+ ------------------------
+
+ -- The following package offers a doubly linked list abstraction with the
+ -- following characteristics:
+ --
+ -- * Creation of multiple instances, of different sizes.
+ -- * Iterable elements.
+ --
+ -- The following use pattern must be employed with this list:
+ --
+ -- List : Instance := Create;
+ --
+ -- <various operations>
+ --
+ -- Destroy (List)
+ --
+ -- The destruction of the list reclaims all storage occupied by it.
+
+ -- The following type denotes the number of elements stored in a list
+
+ type Element_Count_Type is range 0 .. 2 ** 31 - 1;
+
+ generic
+ type Element_Type is private;
+
+ with function "="
+ (Left : Element_Type;
+ Right : Element_Type) return Boolean;
+
+ package Doubly_Linked_List is
+
+ ---------------------
+ -- List operations --
+ ---------------------
+
+ type Instance is private;
+ Nil : constant Instance;
+
+ List_Empty : exception;
+ -- This exception is raised when the list is empty, and an attempt is
+ -- made to delete an element from it.
+
+ List_Locked : exception;
+ -- This exception is raised when the list is being iterated on, and an
+ -- attempt is made to mutate its state.
+
+ Not_Created : exception;
+ -- This exception is raised when the list has not been created by
+ -- routine Create, and an attempt is made to read or mutate its state.
+
+ procedure Append (L : Instance; Elem : Element_Type);
+ -- Insert element Elem at the end of list L. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ function Contains (L : Instance; Elem : Element_Type) return Boolean;
+ -- Determine whether list L contains element Elem
+
+ function Create return Instance;
+ -- Create a new list
+
+ procedure Delete (L : Instance; Elem : Element_Type);
+ -- Delete element Elem from list L. The routine has no effect if Elem is
+ -- not present. This action will raise
+ --
+ -- * List_Empty if the list is empty.
+ -- * List_Locked if the list has outstanding iterators.
+
+ procedure Delete_First (L : Instance);
+ -- Delete an element from the start of list L. This action will raise
+ --
+ -- * List_Empty if the list is empty.
+ -- * List_Locked if the list has outstanding iterators.
+
+ procedure Delete_Last (L : Instance);
+ -- Delete an element from the end of list L. This action will raise
+ --
+ -- * List_Empty if the list is empty.
+ -- * List_Locked if the list has outstanding iterators.
+
+ procedure Destroy (L : in out Instance);
+ -- Destroy the contents of list L. This routine must be called at the
+ -- end of a list's lifetime. This action will raise List_Locked if the
+ -- list has outstanding iterators.
+
+ function First (L : Instance) return Element_Type;
+ -- Obtain an element from the start of list L. This action will raise
+ -- List_Empty if the list is empty.
+
+ procedure Insert_After
+ (L : Instance;
+ After : Element_Type;
+ Elem : Element_Type);
+ -- Insert new element Elem after element After in list L. The routine
+ -- has no effect if After is not present. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ procedure Insert_Before
+ (L : Instance;
+ Before : Element_Type;
+ Elem : Element_Type);
+ -- Insert new element Elem before element Before in list L. The routine
+ -- has no effect if After is not present. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ function Is_Empty (L : Instance) return Boolean;
+ -- Determine whether list L is empty
+
+ function Last (L : Instance) return Element_Type;
+ -- Obtain an element from the end of list L. This action will raise
+ -- List_Empty if the list is empty.
+
+ function Length (L : Instance) return Element_Count_Type;
+ -- Obtain the number of elements in list L
+
+ procedure Prepend (L : Instance; Elem : Element_Type);
+ -- Insert element Elem at the start of list L. This action will raise
+ -- List_Locked if the list has outstanding iterators.
+
+ procedure Replace
+ (L : Instance;
+ Old_Elem : Element_Type;
+ New_Elem : Element_Type);
+ -- Replace old element Old_Elem with new element New_Elem in list L. The
+ -- routine has no effect if Old_Elem is not present. This action will
+ -- raise List_Locked if the list has outstanding iterators.
+
+ -------------------------
+ -- Iterator operations --
+ -------------------------
+
+ -- The following type represents an element iterator. An iterator locks
+ -- all mutation operations, and ulocks them once it is exhausted. The
+ -- iterator must be used with the following pattern:
+ --
+ -- Iter := Iterate (My_List);
+ -- while Has_Next (Iter) loop
+ -- Next (Iter, Element);
+ -- end loop;
+ --
+ -- It is possible to advance the iterator by using Next only, however
+ -- this risks raising Iterator_Exhausted.
+
+ type Iterator is private;
+
+ Iterator_Exhausted : exception;
+ -- This exception is raised when an iterator is exhausted and further
+ -- attempts to advance it are made by calling routine Next.
+
+ function Iterate (L : Instance) return Iterator;
+ -- Obtain an iterator over the elements of list L. This action locks all
+ -- mutation functionality of the associated list.
+
+ function Has_Next (Iter : Iterator) return Boolean;
+ -- Determine whether iterator Iter has more elements to examine. If the
+ -- iterator has been exhausted, restore all mutation functionality of
+ -- the associated list.
+
+ procedure Next
+ (Iter : in out Iterator;
+ Elem : out Element_Type);
+ -- Return the current element referenced by iterator Iter and advance
+ -- to the next available element. If the iterator has been exhausted
+ -- and further attempts are made to advance it, this routine restores
+ -- mutation functionality of the associated list, and then raises
+ -- Iterator_Exhausted.
+
+ private
+ -- The following type represents a list node
+
+ type Node;
+ type Node_Ptr is access all Node;
+ type Node is record
+ Elem : Element_Type;
+
+ Next : Node_Ptr := null;
+ Prev : Node_Ptr := null;
+ end record;
+
+ -- The following type represents a list
+
+ type Linked_List is record
+ Elements : Element_Count_Type := 0;
+ -- The number of elements in the list
+
+ Locked : Natural := 0;
+ -- Number of outstanding iterators
+
+ Nodes : aliased Node;
+ -- The dummy head of the list
+ end record;
+
+ type Instance is access all Linked_List;
+ Nil : constant Instance := null;
+
+ -- The following type represents an element iterator
+
+ type Iterator is record
+ List : Instance := null;
+ -- Reference to the associated list
+
+ Nod : Node_Ptr := null;
+ -- Reference to the current node being examined. The invariant of the
+ -- iterator requires that this field always points to a valid node. A
+ -- value of null indicates that the iterator is exhausted.
+ end record;
+ end Doubly_Linked_List;
+
+end GNAT.Lists;
diff --git a/gcc/ada/libgnat/s-dfmkio.ads b/gcc/ada/libgnat/s-dfmkio.ads
new file mode 100644
index 0000000..c9a96c2
--- /dev/null
+++ b/gcc/ada/libgnat/s-dfmkio.ads
@@ -0,0 +1,38 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . F L O A T _ M K S _ I O --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- Provides output facilities for the Float MKS dimension system (see
+-- System.Dim.Float_Mks and System.Dim.Float_IO).
+
+with System.Dim.Float_Mks; use System.Dim.Float_Mks;
+with System.Dim.Float_IO;
+
+package System.Dim.Float_Mks_IO is new System.Dim.Float_IO (Mks_Type);
diff --git a/gcc/ada/libgnat/s-dfmopr.ads b/gcc/ada/libgnat/s-dfmopr.ads
new file mode 100644
index 0000000..6938feb
--- /dev/null
+++ b/gcc/ada/libgnat/s-dfmopr.ads
@@ -0,0 +1,35 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . F L O A T _ M K S . O T H E R _ P R E F I X E S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks.Generic_Other_Prefixes;
+
+package System.Dim.Float_Mks.Other_Prefixes is
+ new System.Dim.Float_Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/libgnat/s-dgmgop.ads b/gcc/ada/libgnat/s-dgmgop.ads
new file mode 100644
index 0000000..496056d
--- /dev/null
+++ b/gcc/ada/libgnat/s-dgmgop.ads
@@ -0,0 +1,174 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . G E N E R I C _ M K S --
+-- . G E N E R I C _ O T H E R _ P R E F I X E S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2011-2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- Package that defines some other prefixes for the MKS base unit system.
+
+-- These prefixes have been defined in a child package in order to avoid too
+-- many constant declarations in System.Dim.Generic_Mks.
+
+generic
+package System.Dim.Generic_Mks.Generic_Other_Prefixes is
+
+ -- SI prefixes for Meter
+
+ pragma Warnings (Off);
+ -- Turn off the all the dimension warnings
+
+ ym : constant Length := 1.0E-24; -- yocto
+ zm : constant Length := 1.0E-21; -- zepto
+ am : constant Length := 1.0E-18; -- atto
+ fm : constant Length := 1.0E-15; -- femto
+ pm : constant Length := 1.0E-12; -- pico
+ nm : constant Length := 1.0E-09; -- nano
+ Gm : constant Length := 1.0E+09; -- giga
+ Tm : constant Length := 1.0E+12; -- tera
+ Pem : constant Length := 1.0E+15; -- peta
+ Em : constant Length := 1.0E+18; -- exa
+ Zem : constant Length := 1.0E+21; -- zetta
+ Yom : constant Length := 1.0E+24; -- yotta
+
+ -- SI prefixes for Kilogram
+
+ yg : constant Mass := 1.0E-27; -- yocto
+ zg : constant Mass := 1.0E-24; -- zepto
+ ag : constant Mass := 1.0E-21; -- atto
+ fg : constant Mass := 1.0E-18; -- femto
+ pg : constant Mass := 1.0E-15; -- pico
+ ng : constant Mass := 1.0E-12; -- nano
+ Gg : constant Mass := 1.0E+06; -- giga
+ Tg : constant Mass := 1.0E+09; -- tera
+ Peg : constant Mass := 1.0E+13; -- peta
+ Eg : constant Mass := 1.0E+15; -- exa
+ Zeg : constant Mass := 1.0E+18; -- zetta
+ Yog : constant Mass := 1.0E+21; -- yotta
+
+ -- SI prefixes for Second
+
+ ys : constant Time := 1.0E-24; -- yocto
+ zs : constant Time := 1.0E-21; -- zepto
+ as : constant Time := 1.0E-18; -- atto
+ fs : constant Time := 1.0E-15; -- femto
+ ps : constant Time := 1.0E-12; -- pico
+ ns : constant Time := 1.0E-09; -- nano
+ Gs : constant Time := 1.0E+09; -- giga
+ Ts : constant Time := 1.0E+12; -- tera
+ Pes : constant Time := 1.0E+15; -- peta
+ Es : constant Time := 1.0E+18; -- exa
+ Zes : constant Time := 1.0E+21; -- zetta
+ Yos : constant Time := 1.0E+24; -- yotta
+
+ -- SI prefixes for Ampere
+
+ yA : constant Electric_Current := 1.0E-24; -- yocto
+ zA : constant Electric_Current := 1.0E-21; -- zepto
+ aA : constant Electric_Current := 1.0E-18; -- atto
+ fA : constant Electric_Current := 1.0E-15; -- femto
+ nA : constant Electric_Current := 1.0E-09; -- nano
+ uA : constant Electric_Current := 1.0E-06; -- micro (u)
+ GA : constant Electric_Current := 1.0E+09; -- giga
+ TA : constant Electric_Current := 1.0E+12; -- tera
+ PeA : constant Electric_Current := 1.0E+15; -- peta
+ EA : constant Electric_Current := 1.0E+18; -- exa
+ ZeA : constant Electric_Current := 1.0E+21; -- zetta
+ YoA : constant Electric_Current := 1.0E+24; -- yotta
+
+ -- SI prefixes for Kelvin
+
+ yK : constant Thermodynamic_Temperature := 1.0E-24; -- yocto
+ zK : constant Thermodynamic_Temperature := 1.0E-21; -- zepto
+ aK : constant Thermodynamic_Temperature := 1.0E-18; -- atto
+ fK : constant Thermodynamic_Temperature := 1.0E-15; -- femto
+ pK : constant Thermodynamic_Temperature := 1.0E-12; -- pico
+ nK : constant Thermodynamic_Temperature := 1.0E-09; -- nano
+ uK : constant Thermodynamic_Temperature := 1.0E-06; -- micro (u)
+ mK : constant Thermodynamic_Temperature := 1.0E-03; -- milli
+ cK : constant Thermodynamic_Temperature := 1.0E-02; -- centi
+ dK : constant Thermodynamic_Temperature := 1.0E-01; -- deci
+ daK : constant Thermodynamic_Temperature := 1.0E+01; -- deka
+ hK : constant Thermodynamic_Temperature := 1.0E+02; -- hecto
+ kK : constant Thermodynamic_Temperature := 1.0E+03; -- kilo
+ MeK : constant Thermodynamic_Temperature := 1.0E+06; -- mega
+ GK : constant Thermodynamic_Temperature := 1.0E+09; -- giga
+ TK : constant Thermodynamic_Temperature := 1.0E+12; -- tera
+ PeK : constant Thermodynamic_Temperature := 1.0E+15; -- peta
+ EK : constant Thermodynamic_Temperature := 1.0E+18; -- exa
+ ZeK : constant Thermodynamic_Temperature := 1.0E+21; -- zetta
+ YoK : constant Thermodynamic_Temperature := 1.0E+24; -- yotta
+
+ -- SI prefixes for Mole
+
+ ymol : constant Amount_Of_Substance := 1.0E-24; -- yocto
+ zmol : constant Amount_Of_Substance := 1.0E-21; -- zepto
+ amol : constant Amount_Of_Substance := 1.0E-18; -- atto
+ fmol : constant Amount_Of_Substance := 1.0E-15; -- femto
+ pmol : constant Amount_Of_Substance := 1.0E-12; -- pico
+ nmol : constant Amount_Of_Substance := 1.0E-09; -- nano
+ umol : constant Amount_Of_Substance := 1.0E-06; -- micro (u)
+ mmol : constant Amount_Of_Substance := 1.0E-03; -- milli
+ cmol : constant Amount_Of_Substance := 1.0E-02; -- centi
+ dmol : constant Amount_Of_Substance := 1.0E-01; -- deci
+ damol : constant Amount_Of_Substance := 1.0E+01; -- deka
+ hmol : constant Amount_Of_Substance := 1.0E+02; -- hecto
+ kmol : constant Amount_Of_Substance := 1.0E+03; -- kilo
+ Memol : constant Amount_Of_Substance := 1.0E+06; -- mega
+ Gmol : constant Amount_Of_Substance := 1.0E+09; -- giga
+ Tmol : constant Amount_Of_Substance := 1.0E+12; -- tera
+ Pemol : constant Amount_Of_Substance := 1.0E+15; -- peta
+ Emol : constant Amount_Of_Substance := 1.0E+18; -- exa
+ Zemol : constant Amount_Of_Substance := 1.0E+21; -- zetta
+ Yomol : constant Amount_Of_Substance := 1.0E+24; -- yotta
+
+ -- SI prefixes for Candela
+
+ ycd : constant Luminous_Intensity := 1.0E-24; -- yocto
+ zcd : constant Luminous_Intensity := 1.0E-21; -- zepto
+ acd : constant Luminous_Intensity := 1.0E-18; -- atto
+ fcd : constant Luminous_Intensity := 1.0E-15; -- femto
+ pcd : constant Luminous_Intensity := 1.0E-12; -- pico
+ ncd : constant Luminous_Intensity := 1.0E-09; -- nano
+ ucd : constant Luminous_Intensity := 1.0E-06; -- micro (u)
+ mcd : constant Luminous_Intensity := 1.0E-03; -- milli
+ ccd : constant Luminous_Intensity := 1.0E-02; -- centi
+ dcd : constant Luminous_Intensity := 1.0E-01; -- deci
+ dacd : constant Luminous_Intensity := 1.0E+01; -- deka
+ hcd : constant Luminous_Intensity := 1.0E+02; -- hecto
+ kcd : constant Luminous_Intensity := 1.0E+03; -- kilo
+ Mecd : constant Luminous_Intensity := 1.0E+06; -- mega
+ Gcd : constant Luminous_Intensity := 1.0E+09; -- giga
+ Tcd : constant Luminous_Intensity := 1.0E+12; -- tera
+ Pecd : constant Luminous_Intensity := 1.0E+15; -- peta
+ Ecd : constant Luminous_Intensity := 1.0E+18; -- exa
+ Zecd : constant Luminous_Intensity := 1.0E+21; -- zetta
+ Yocd : constant Luminous_Intensity := 1.0E+24; -- yotta
+
+ pragma Warnings (On);
+end System.Dim.Generic_Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/libgnat/s-diflmk.ads b/gcc/ada/libgnat/s-diflmk.ads
new file mode 100644
index 0000000..435948e
--- /dev/null
+++ b/gcc/ada/libgnat/s-diflmk.ads
@@ -0,0 +1,34 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . F L O A T _ M K S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks;
+
+package System.Dim.Float_Mks is new System.Dim.Generic_Mks (Float);
diff --git a/gcc/ada/libgnat/s-digemk.ads b/gcc/ada/libgnat/s-digemk.ads
new file mode 100644
index 0000000..4f55ad4
--- /dev/null
+++ b/gcc/ada/libgnat/s-digemk.ads
@@ -0,0 +1,396 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . G E N E R I C _ M K S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2011-2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- Defines the MKS dimension system which is the SI system of units
+
+-- Some other prefixes of this system are defined in a child package (see
+-- System.Dim.Generic_Mks.Generic_Other_Prefixes) in order to avoid too many
+-- constant declarations in this package.
+
+-- The dimension terminology is defined in System.Dim package
+
+with Ada.Numerics;
+
+generic
+ type Float_Type is digits <>;
+
+package System.Dim.Generic_Mks is
+
+ e : constant := Ada.Numerics.e;
+ Pi : constant := Ada.Numerics.Pi;
+
+ -- Dimensioned type Mks_Type
+
+ type Mks_Type is new Float_Type
+ with
+ Dimension_System => (
+ (Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
+ (Unit_Name => Kilogram, Unit_Symbol => "kg", Dim_Symbol => 'M'),
+ (Unit_Name => Second, Unit_Symbol => 's', Dim_Symbol => 'T'),
+ (Unit_Name => Ampere, Unit_Symbol => 'A', Dim_Symbol => 'I'),
+ (Unit_Name => Kelvin, Unit_Symbol => 'K', Dim_Symbol => '@'),
+ (Unit_Name => Mole, Unit_Symbol => "mol", Dim_Symbol => 'N'),
+ (Unit_Name => Candela, Unit_Symbol => "cd", Dim_Symbol => 'J'));
+
+ -- SI Base dimensioned subtypes
+
+ subtype Length is Mks_Type
+ with
+ Dimension => (Symbol => 'm',
+ Meter => 1,
+ others => 0);
+
+ subtype Mass is Mks_Type
+ with
+ Dimension => (Symbol => "kg",
+ Kilogram => 1,
+ others => 0);
+
+ subtype Time is Mks_Type
+ with
+ Dimension => (Symbol => 's',
+ Second => 1,
+ others => 0);
+
+ subtype Electric_Current is Mks_Type
+ with
+ Dimension => (Symbol => 'A',
+ Ampere => 1,
+ others => 0);
+
+ subtype Thermodynamic_Temperature is Mks_Type
+ with
+ Dimension => (Symbol => 'K',
+ Kelvin => 1,
+ others => 0);
+
+ subtype Amount_Of_Substance is Mks_Type
+ with
+ Dimension => (Symbol => "mol",
+ Mole => 1,
+ others => 0);
+
+ subtype Luminous_Intensity is Mks_Type
+ with
+ Dimension => (Symbol => "cd",
+ Candela => 1,
+ others => 0);
+
+ -- Initialize SI Base unit values
+
+ -- Turn off the all the dimension warnings for these basic assignments
+ -- since otherwise we would get complaints about assigning dimensionless
+ -- values to dimensioned subtypes (we can't assign 1.0*m to m).
+
+ pragma Warnings (Off, "*assumed to be*");
+
+ m : constant Length := 1.0;
+ kg : constant Mass := 1.0;
+ s : constant Time := 1.0;
+ A : constant Electric_Current := 1.0;
+ K : constant Thermodynamic_Temperature := 1.0;
+ mol : constant Amount_Of_Substance := 1.0;
+ cd : constant Luminous_Intensity := 1.0;
+
+ pragma Warnings (On, "*assumed to be*");
+
+ -- SI Derived dimensioned subtypes
+
+ subtype Absorbed_Dose is Mks_Type
+ with
+ Dimension => (Symbol => "Gy",
+ Meter => 2,
+ Second => -2,
+ others => 0);
+
+ subtype Angle is Mks_Type
+ with
+ Dimension => (Symbol => "rad",
+ others => 0);
+
+ subtype Area is Mks_Type
+ with
+ Dimension => (
+ Meter => 2,
+ others => 0);
+
+ subtype Catalytic_Activity is Mks_Type
+ with
+ Dimension => (Symbol => "kat",
+ Second => -1,
+ Mole => 1,
+ others => 0);
+
+ subtype Celsius_Temperature is Mks_Type
+ with
+ Dimension => (Symbol => "°C",
+ Kelvin => 1,
+ others => 0);
+
+ subtype Electric_Capacitance is Mks_Type
+ with
+ Dimension => (Symbol => 'F',
+ Meter => -2,
+ Kilogram => -1,
+ Second => 4,
+ Ampere => 2,
+ others => 0);
+
+ subtype Electric_Charge is Mks_Type
+ with
+ Dimension => (Symbol => 'C',
+ Second => 1,
+ Ampere => 1,
+ others => 0);
+
+ subtype Electric_Conductance is Mks_Type
+ with
+ Dimension => (Symbol => 'S',
+ Meter => -2,
+ Kilogram => -1,
+ Second => 3,
+ Ampere => 2,
+ others => 0);
+
+ subtype Electric_Potential_Difference is Mks_Type
+ with
+ Dimension => (Symbol => 'V',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -3,
+ Ampere => -1,
+ others => 0);
+
+ -- Note the type punning below. The Symbol is a single "ohm" character
+ -- encoded in UTF-8 (ce a9 in hexadecimal), but this file is not compiled
+ -- with -gnatW8, so we're treating the string literal as a two-character
+ -- String.
+
+ subtype Electric_Resistance is Mks_Type
+ with
+ Dimension => (Symbol => "Ω",
+ Meter => 2,
+ Kilogram => 1,
+ Second => -3,
+ Ampere => -2,
+ others => 0);
+
+ subtype Energy is Mks_Type
+ with
+ Dimension => (Symbol => 'J',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -2,
+ others => 0);
+
+ subtype Equivalent_Dose is Mks_Type
+ with
+ Dimension => (Symbol => "Sv",
+ Meter => 2,
+ Second => -2,
+ others => 0);
+
+ subtype Force is Mks_Type
+ with
+ Dimension => (Symbol => 'N',
+ Meter => 1,
+ Kilogram => 1,
+ Second => -2,
+ others => 0);
+
+ subtype Frequency is Mks_Type
+ with
+ Dimension => (Symbol => "Hz",
+ Second => -1,
+ others => 0);
+
+ subtype Illuminance is Mks_Type
+ with
+ Dimension => (Symbol => "lx",
+ Meter => -2,
+ Candela => 1,
+ others => 0);
+
+ subtype Inductance is Mks_Type
+ with
+ Dimension => (Symbol => 'H',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -2,
+ Ampere => -2,
+ others => 0);
+
+ subtype Luminous_Flux is Mks_Type
+ with
+ Dimension => (Symbol => "lm",
+ Candela => 1,
+ others => 0);
+
+ subtype Magnetic_Flux is Mks_Type
+ with
+ Dimension => (Symbol => "Wb",
+ Meter => 2,
+ Kilogram => 1,
+ Second => -2,
+ Ampere => -1,
+ others => 0);
+
+ subtype Magnetic_Flux_Density is Mks_Type
+ with
+ Dimension => (Symbol => 'T',
+ Kilogram => 1,
+ Second => -2,
+ Ampere => -1,
+ others => 0);
+
+ subtype Power is Mks_Type
+ with
+ Dimension => (Symbol => 'W',
+ Meter => 2,
+ Kilogram => 1,
+ Second => -3,
+ others => 0);
+
+ subtype Pressure is Mks_Type
+ with
+ Dimension => (Symbol => "Pa",
+ Meter => -1,
+ Kilogram => 1,
+ Second => -2,
+ others => 0);
+
+ subtype Radioactivity is Mks_Type
+ with
+ Dimension => (Symbol => "Bq",
+ Second => -1,
+ others => 0);
+
+ subtype Solid_Angle is Mks_Type
+ with
+ Dimension => (Symbol => "sr",
+ others => 0);
+
+ subtype Speed is Mks_Type
+ with
+ Dimension => (
+ Meter => 1,
+ Second => -1,
+ others => 0);
+
+ subtype Volume is Mks_Type
+ with
+ Dimension => (
+ Meter => 3,
+ others => 0);
+
+ -- Initialize derived dimension values
+
+ -- Turn off the all the dimension warnings for these basic assignments
+ -- since otherwise we would get complaints about assigning dimensionless
+ -- values to dimensioned subtypes.
+
+ pragma Warnings (Off, "*assumed to be*");
+
+ rad : constant Angle := 1.0;
+ sr : constant Solid_Angle := 1.0;
+ Hz : constant Frequency := 1.0;
+ N : constant Force := 1.0;
+ Pa : constant Pressure := 1.0;
+ J : constant Energy := 1.0;
+ W : constant Power := 1.0;
+ C : constant Electric_Charge := 1.0;
+ V : constant Electric_Potential_Difference := 1.0;
+ F : constant Electric_Capacitance := 1.0;
+ Ohm : constant Electric_Resistance := 1.0;
+ Si : constant Electric_Conductance := 1.0;
+ Wb : constant Magnetic_Flux := 1.0;
+ T : constant Magnetic_Flux_Density := 1.0;
+ H : constant Inductance := 1.0;
+ dC : constant Celsius_Temperature := 273.15;
+ lm : constant Luminous_Flux := 1.0;
+ lx : constant Illuminance := 1.0;
+ Bq : constant Radioactivity := 1.0;
+ Gy : constant Absorbed_Dose := 1.0;
+ Sv : constant Equivalent_Dose := 1.0;
+ kat : constant Catalytic_Activity := 1.0;
+
+ -- SI prefixes for Meter
+
+ um : constant Length := 1.0E-06; -- micro (u)
+ mm : constant Length := 1.0E-03; -- milli
+ cm : constant Length := 1.0E-02; -- centi
+ dm : constant Length := 1.0E-01; -- deci
+ dam : constant Length := 1.0E+01; -- deka
+ hm : constant Length := 1.0E+02; -- hecto
+ km : constant Length := 1.0E+03; -- kilo
+ Mem : constant Length := 1.0E+06; -- mega
+
+ -- SI prefixes for Kilogram
+
+ ug : constant Mass := 1.0E-09; -- micro (u)
+ mg : constant Mass := 1.0E-06; -- milli
+ cg : constant Mass := 1.0E-05; -- centi
+ dg : constant Mass := 1.0E-04; -- deci
+ g : constant Mass := 1.0E-03; -- gram
+ dag : constant Mass := 1.0E-02; -- deka
+ hg : constant Mass := 1.0E-01; -- hecto
+ Meg : constant Mass := 1.0E+03; -- mega
+
+ -- SI prefixes for Second
+
+ us : constant Time := 1.0E-06; -- micro (u)
+ ms : constant Time := 1.0E-03; -- milli
+ cs : constant Time := 1.0E-02; -- centi
+ ds : constant Time := 1.0E-01; -- deci
+ das : constant Time := 1.0E+01; -- deka
+ hs : constant Time := 1.0E+02; -- hecto
+ ks : constant Time := 1.0E+03; -- kilo
+ Mes : constant Time := 1.0E+06; -- mega
+
+ -- Other constants for Second
+
+ min : constant Time := 60.0 * s;
+ hour : constant Time := 60.0 * min;
+ day : constant Time := 24.0 * hour;
+ year : constant Time := 365.25 * day;
+
+ -- SI prefixes for Ampere
+
+ mA : constant Electric_Current := 1.0E-03; -- milli
+ cA : constant Electric_Current := 1.0E-02; -- centi
+ dA : constant Electric_Current := 1.0E-01; -- deci
+ daA : constant Electric_Current := 1.0E+01; -- deka
+ hA : constant Electric_Current := 1.0E+02; -- hecto
+ kA : constant Electric_Current := 1.0E+03; -- kilo
+ MeA : constant Electric_Current := 1.0E+06; -- mega
+
+ pragma Warnings (On, "*assumed to be*");
+end System.Dim.Generic_Mks;
diff --git a/gcc/ada/libgnat/s-dilomk.ads b/gcc/ada/libgnat/s-dilomk.ads
new file mode 100644
index 0000000..2aaecae
--- /dev/null
+++ b/gcc/ada/libgnat/s-dilomk.ads
@@ -0,0 +1,34 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . L O N G _ M K S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks;
+
+package System.Dim.Long_Mks is new System.Dim.Generic_Mks (Long_Float);
diff --git a/gcc/ada/libgnat/s-dimmks.ads b/gcc/ada/libgnat/s-dimmks.ads
index f21f82d..bf89f1b 100644
--- a/gcc/ada/libgnat/s-dimmks.ads
+++ b/gcc/ada/libgnat/s-dimmks.ads
@@ -29,365 +29,6 @@
-- --
------------------------------------------------------------------------------
--- Defines the MKS dimension system which is the SI system of units
+with System.Dim.Generic_Mks;
--- Some other prefixes of this system are defined in a child package (see
--- System.Dim_Mks.Other_Prefixes) in order to avoid too many constant
--- declarations in this package.
-
--- The dimension terminology is defined in System.Dim_IO package
-
-with Ada.Numerics;
-
-package System.Dim.Mks is
-
- e : constant := Ada.Numerics.e;
- Pi : constant := Ada.Numerics.Pi;
-
- -- Dimensioned type Mks_Type
-
- type Mks_Type is new Long_Long_Float
- with
- Dimension_System => (
- (Unit_Name => Meter, Unit_Symbol => 'm', Dim_Symbol => 'L'),
- (Unit_Name => Kilogram, Unit_Symbol => "kg", Dim_Symbol => 'M'),
- (Unit_Name => Second, Unit_Symbol => 's', Dim_Symbol => 'T'),
- (Unit_Name => Ampere, Unit_Symbol => 'A', Dim_Symbol => 'I'),
- (Unit_Name => Kelvin, Unit_Symbol => 'K', Dim_Symbol => '@'),
- (Unit_Name => Mole, Unit_Symbol => "mol", Dim_Symbol => 'N'),
- (Unit_Name => Candela, Unit_Symbol => "cd", Dim_Symbol => 'J'));
-
- -- SI Base dimensioned subtypes
-
- subtype Length is Mks_Type
- with
- Dimension => (Symbol => 'm',
- Meter => 1,
- others => 0);
-
- subtype Mass is Mks_Type
- with
- Dimension => (Symbol => "kg",
- Kilogram => 1,
- others => 0);
-
- subtype Time is Mks_Type
- with
- Dimension => (Symbol => 's',
- Second => 1,
- others => 0);
-
- subtype Electric_Current is Mks_Type
- with
- Dimension => (Symbol => 'A',
- Ampere => 1,
- others => 0);
-
- subtype Thermodynamic_Temperature is Mks_Type
- with
- Dimension => (Symbol => 'K',
- Kelvin => 1,
- others => 0);
-
- subtype Amount_Of_Substance is Mks_Type
- with
- Dimension => (Symbol => "mol",
- Mole => 1,
- others => 0);
-
- subtype Luminous_Intensity is Mks_Type
- with
- Dimension => (Symbol => "cd",
- Candela => 1,
- others => 0);
-
- -- Initialize SI Base unit values
-
- -- Turn off the all the dimension warnings for these basic assignments
- -- since otherwise we would get complaints about assigning dimensionless
- -- values to dimensioned subtypes (we can't assign 1.0*m to m).
-
- pragma Warnings (Off, "*assumed to be*");
-
- m : constant Length := 1.0;
- kg : constant Mass := 1.0;
- s : constant Time := 1.0;
- A : constant Electric_Current := 1.0;
- K : constant Thermodynamic_Temperature := 1.0;
- mol : constant Amount_Of_Substance := 1.0;
- cd : constant Luminous_Intensity := 1.0;
-
- pragma Warnings (On, "*assumed to be*");
-
- -- SI Derived dimensioned subtypes
-
- subtype Absorbed_Dose is Mks_Type
- with
- Dimension => (Symbol => "Gy",
- Meter => 2,
- Second => -2,
- others => 0);
-
- subtype Angle is Mks_Type
- with
- Dimension => (Symbol => "rad",
- others => 0);
-
- subtype Area is Mks_Type
- with
- Dimension => (
- Meter => 2,
- others => 0);
-
- subtype Catalytic_Activity is Mks_Type
- with
- Dimension => (Symbol => "kat",
- Second => -1,
- Mole => 1,
- others => 0);
-
- subtype Celsius_Temperature is Mks_Type
- with
- Dimension => (Symbol => "°C",
- Kelvin => 1,
- others => 0);
-
- subtype Electric_Capacitance is Mks_Type
- with
- Dimension => (Symbol => 'F',
- Meter => -2,
- Kilogram => -1,
- Second => 4,
- Ampere => 2,
- others => 0);
-
- subtype Electric_Charge is Mks_Type
- with
- Dimension => (Symbol => 'C',
- Second => 1,
- Ampere => 1,
- others => 0);
-
- subtype Electric_Conductance is Mks_Type
- with
- Dimension => (Symbol => 'S',
- Meter => -2,
- Kilogram => -1,
- Second => 3,
- Ampere => 2,
- others => 0);
-
- subtype Electric_Potential_Difference is Mks_Type
- with
- Dimension => (Symbol => 'V',
- Meter => 2,
- Kilogram => 1,
- Second => -3,
- Ampere => -1,
- others => 0);
-
- -- Note the type punning below. The Symbol is a single "ohm" character
- -- encoded in UTF-8 (ce a9 in hexadecimal), but this file is not compiled
- -- with -gnatW8, so we're treating the string literal as a two-character
- -- String.
-
- subtype Electric_Resistance is Mks_Type
- with
- Dimension => (Symbol => "Ω",
- Meter => 2,
- Kilogram => 1,
- Second => -3,
- Ampere => -2,
- others => 0);
-
- subtype Energy is Mks_Type
- with
- Dimension => (Symbol => 'J',
- Meter => 2,
- Kilogram => 1,
- Second => -2,
- others => 0);
-
- subtype Equivalent_Dose is Mks_Type
- with
- Dimension => (Symbol => "Sv",
- Meter => 2,
- Second => -2,
- others => 0);
-
- subtype Force is Mks_Type
- with
- Dimension => (Symbol => 'N',
- Meter => 1,
- Kilogram => 1,
- Second => -2,
- others => 0);
-
- subtype Frequency is Mks_Type
- with
- Dimension => (Symbol => "Hz",
- Second => -1,
- others => 0);
-
- subtype Illuminance is Mks_Type
- with
- Dimension => (Symbol => "lx",
- Meter => -2,
- Candela => 1,
- others => 0);
-
- subtype Inductance is Mks_Type
- with
- Dimension => (Symbol => 'H',
- Meter => 2,
- Kilogram => 1,
- Second => -2,
- Ampere => -2,
- others => 0);
-
- subtype Luminous_Flux is Mks_Type
- with
- Dimension => (Symbol => "lm",
- Candela => 1,
- others => 0);
-
- subtype Magnetic_Flux is Mks_Type
- with
- Dimension => (Symbol => "Wb",
- Meter => 2,
- Kilogram => 1,
- Second => -2,
- Ampere => -1,
- others => 0);
-
- subtype Magnetic_Flux_Density is Mks_Type
- with
- Dimension => (Symbol => 'T',
- Kilogram => 1,
- Second => -2,
- Ampere => -1,
- others => 0);
-
- subtype Power is Mks_Type
- with
- Dimension => (Symbol => 'W',
- Meter => 2,
- Kilogram => 1,
- Second => -3,
- others => 0);
-
- subtype Pressure is Mks_Type
- with
- Dimension => (Symbol => "Pa",
- Meter => -1,
- Kilogram => 1,
- Second => -2,
- others => 0);
-
- subtype Radioactivity is Mks_Type
- with
- Dimension => (Symbol => "Bq",
- Second => -1,
- others => 0);
-
- subtype Solid_Angle is Mks_Type
- with
- Dimension => (Symbol => "sr",
- others => 0);
-
- subtype Speed is Mks_Type
- with
- Dimension => (
- Meter => 1,
- Second => -1,
- others => 0);
-
- subtype Volume is Mks_Type
- with
- Dimension => (
- Meter => 3,
- others => 0);
-
- -- Initialize derived dimension values
-
- -- Turn off the all the dimension warnings for these basic assignments
- -- since otherwise we would get complaints about assigning dimensionless
- -- values to dimensioned subtypes.
-
- pragma Warnings (Off, "*assumed to be*");
-
- rad : constant Angle := 1.0;
- sr : constant Solid_Angle := 1.0;
- Hz : constant Frequency := 1.0;
- N : constant Force := 1.0;
- Pa : constant Pressure := 1.0;
- J : constant Energy := 1.0;
- W : constant Power := 1.0;
- C : constant Electric_Charge := 1.0;
- V : constant Electric_Potential_Difference := 1.0;
- F : constant Electric_Capacitance := 1.0;
- Ohm : constant Electric_Resistance := 1.0;
- Si : constant Electric_Conductance := 1.0;
- Wb : constant Magnetic_Flux := 1.0;
- T : constant Magnetic_Flux_Density := 1.0;
- H : constant Inductance := 1.0;
- dC : constant Celsius_Temperature := 273.15;
- lm : constant Luminous_Flux := 1.0;
- lx : constant Illuminance := 1.0;
- Bq : constant Radioactivity := 1.0;
- Gy : constant Absorbed_Dose := 1.0;
- Sv : constant Equivalent_Dose := 1.0;
- kat : constant Catalytic_Activity := 1.0;
-
- -- SI prefixes for Meter
-
- um : constant Length := 1.0E-06; -- micro (u)
- mm : constant Length := 1.0E-03; -- milli
- cm : constant Length := 1.0E-02; -- centi
- dm : constant Length := 1.0E-01; -- deci
- dam : constant Length := 1.0E+01; -- deka
- hm : constant Length := 1.0E+02; -- hecto
- km : constant Length := 1.0E+03; -- kilo
- Mem : constant Length := 1.0E+06; -- mega
-
- -- SI prefixes for Kilogram
-
- ug : constant Mass := 1.0E-09; -- micro (u)
- mg : constant Mass := 1.0E-06; -- milli
- cg : constant Mass := 1.0E-05; -- centi
- dg : constant Mass := 1.0E-04; -- deci
- g : constant Mass := 1.0E-03; -- gram
- dag : constant Mass := 1.0E-02; -- deka
- hg : constant Mass := 1.0E-01; -- hecto
- Meg : constant Mass := 1.0E+03; -- mega
-
- -- SI prefixes for Second
-
- us : constant Time := 1.0E-06; -- micro (u)
- ms : constant Time := 1.0E-03; -- milli
- cs : constant Time := 1.0E-02; -- centi
- ds : constant Time := 1.0E-01; -- deci
- das : constant Time := 1.0E+01; -- deka
- hs : constant Time := 1.0E+02; -- hecto
- ks : constant Time := 1.0E+03; -- kilo
- Mes : constant Time := 1.0E+06; -- mega
-
- -- Other constants for Second
-
- min : constant Time := 60.0 * s;
- hour : constant Time := 60.0 * min;
- day : constant Time := 24.0 * hour;
- year : constant Time := 365.25 * day;
-
- -- SI prefixes for Ampere
-
- mA : constant Electric_Current := 1.0E-03; -- milli
- cA : constant Electric_Current := 1.0E-02; -- centi
- dA : constant Electric_Current := 1.0E-01; -- deci
- daA : constant Electric_Current := 1.0E+01; -- deka
- hA : constant Electric_Current := 1.0E+02; -- hecto
- kA : constant Electric_Current := 1.0E+03; -- kilo
- MeA : constant Electric_Current := 1.0E+06; -- mega
-
- pragma Warnings (On, "*assumed to be*");
-end System.Dim.Mks;
+package System.Dim.Mks is new System.Dim.Generic_Mks (Long_Long_Float);
diff --git a/gcc/ada/libgnat/s-dlmkio.ads b/gcc/ada/libgnat/s-dlmkio.ads
new file mode 100644
index 0000000..088727a
--- /dev/null
+++ b/gcc/ada/libgnat/s-dlmkio.ads
@@ -0,0 +1,38 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . L O N G _ M K S _ I O --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+-- Provides output facilities for the Long_Float MKS dimension system (see
+-- System.Dim.Long_Mks and System.Dim.Float_IO).
+
+with System.Dim.Long_Mks; use System.Dim.Long_Mks;
+with System.Dim.Float_IO;
+
+package System.Dim.Long_Mks_IO is new System.Dim.Float_IO (Mks_Type);
diff --git a/gcc/ada/libgnat/s-dlmopr.ads b/gcc/ada/libgnat/s-dlmopr.ads
new file mode 100644
index 0000000..c9280b4
--- /dev/null
+++ b/gcc/ada/libgnat/s-dlmopr.ads
@@ -0,0 +1,35 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT RUN-TIME COMPONENTS --
+-- --
+-- S Y S T E M . D I M . L O N G _ M K S . O T H E R _ P R E F I X E S --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, 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. --
+-- --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
+-- --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
+-- --
+------------------------------------------------------------------------------
+
+with System.Dim.Generic_Mks.Generic_Other_Prefixes;
+
+package System.Dim.Long_Mks.Other_Prefixes is
+ new System.Dim.Long_Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/libgnat/s-dmotpr.ads b/gcc/ada/libgnat/s-dmotpr.ads
index c0adcb3..041ce37 100644
--- a/gcc/ada/libgnat/s-dmotpr.ads
+++ b/gcc/ada/libgnat/s-dmotpr.ads
@@ -29,144 +29,7 @@
-- --
------------------------------------------------------------------------------
--- Package that defines some other prefixes for the MKS base unit system.
-
--- These prefixes have been defined in a child package in order to avoid too
--- many constant declarations in System.Dim_Mks.
+with System.Dim.Generic_Mks.Generic_Other_Prefixes;
package System.Dim.Mks.Other_Prefixes is
-
- -- SI prefixes for Meter
-
- pragma Warnings (Off);
- -- Turn off the all the dimension warnings
-
- ym : constant Length := 1.0E-24; -- yocto
- zm : constant Length := 1.0E-21; -- zepto
- am : constant Length := 1.0E-18; -- atto
- fm : constant Length := 1.0E-15; -- femto
- pm : constant Length := 1.0E-12; -- pico
- nm : constant Length := 1.0E-09; -- nano
- Gm : constant Length := 1.0E+09; -- giga
- Tm : constant Length := 1.0E+12; -- tera
- Pem : constant Length := 1.0E+15; -- peta
- Em : constant Length := 1.0E+18; -- exa
- Zem : constant Length := 1.0E+21; -- zetta
- Yom : constant Length := 1.0E+24; -- yotta
-
- -- SI prefixes for Kilogram
-
- yg : constant Mass := 1.0E-27; -- yocto
- zg : constant Mass := 1.0E-24; -- zepto
- ag : constant Mass := 1.0E-21; -- atto
- fg : constant Mass := 1.0E-18; -- femto
- pg : constant Mass := 1.0E-15; -- pico
- ng : constant Mass := 1.0E-12; -- nano
- Gg : constant Mass := 1.0E+06; -- giga
- Tg : constant Mass := 1.0E+09; -- tera
- Peg : constant Mass := 1.0E+13; -- peta
- Eg : constant Mass := 1.0E+15; -- exa
- Zeg : constant Mass := 1.0E+18; -- zetta
- Yog : constant Mass := 1.0E+21; -- yotta
-
- -- SI prefixes for Second
-
- ys : constant Time := 1.0E-24; -- yocto
- zs : constant Time := 1.0E-21; -- zepto
- as : constant Time := 1.0E-18; -- atto
- fs : constant Time := 1.0E-15; -- femto
- ps : constant Time := 1.0E-12; -- pico
- ns : constant Time := 1.0E-09; -- nano
- Gs : constant Time := 1.0E+09; -- giga
- Ts : constant Time := 1.0E+12; -- tera
- Pes : constant Time := 1.0E+15; -- peta
- Es : constant Time := 1.0E+18; -- exa
- Zes : constant Time := 1.0E+21; -- zetta
- Yos : constant Time := 1.0E+24; -- yotta
-
- -- SI prefixes for Ampere
-
- yA : constant Electric_Current := 1.0E-24; -- yocto
- zA : constant Electric_Current := 1.0E-21; -- zepto
- aA : constant Electric_Current := 1.0E-18; -- atto
- fA : constant Electric_Current := 1.0E-15; -- femto
- nA : constant Electric_Current := 1.0E-09; -- nano
- uA : constant Electric_Current := 1.0E-06; -- micro (u)
- GA : constant Electric_Current := 1.0E+09; -- giga
- TA : constant Electric_Current := 1.0E+12; -- tera
- PeA : constant Electric_Current := 1.0E+15; -- peta
- EA : constant Electric_Current := 1.0E+18; -- exa
- ZeA : constant Electric_Current := 1.0E+21; -- zetta
- YoA : constant Electric_Current := 1.0E+24; -- yotta
-
- -- SI prefixes for Kelvin
-
- yK : constant Thermodynamic_Temperature := 1.0E-24; -- yocto
- zK : constant Thermodynamic_Temperature := 1.0E-21; -- zepto
- aK : constant Thermodynamic_Temperature := 1.0E-18; -- atto
- fK : constant Thermodynamic_Temperature := 1.0E-15; -- femto
- pK : constant Thermodynamic_Temperature := 1.0E-12; -- pico
- nK : constant Thermodynamic_Temperature := 1.0E-09; -- nano
- uK : constant Thermodynamic_Temperature := 1.0E-06; -- micro (u)
- mK : constant Thermodynamic_Temperature := 1.0E-03; -- milli
- cK : constant Thermodynamic_Temperature := 1.0E-02; -- centi
- dK : constant Thermodynamic_Temperature := 1.0E-01; -- deci
- daK : constant Thermodynamic_Temperature := 1.0E+01; -- deka
- hK : constant Thermodynamic_Temperature := 1.0E+02; -- hecto
- kK : constant Thermodynamic_Temperature := 1.0E+03; -- kilo
- MeK : constant Thermodynamic_Temperature := 1.0E+06; -- mega
- GK : constant Thermodynamic_Temperature := 1.0E+09; -- giga
- TK : constant Thermodynamic_Temperature := 1.0E+12; -- tera
- PeK : constant Thermodynamic_Temperature := 1.0E+15; -- peta
- EK : constant Thermodynamic_Temperature := 1.0E+18; -- exa
- ZeK : constant Thermodynamic_Temperature := 1.0E+21; -- zetta
- YoK : constant Thermodynamic_Temperature := 1.0E+24; -- yotta
-
- -- SI prefixes for Mole
-
- ymol : constant Amount_Of_Substance := 1.0E-24; -- yocto
- zmol : constant Amount_Of_Substance := 1.0E-21; -- zepto
- amol : constant Amount_Of_Substance := 1.0E-18; -- atto
- fmol : constant Amount_Of_Substance := 1.0E-15; -- femto
- pmol : constant Amount_Of_Substance := 1.0E-12; -- pico
- nmol : constant Amount_Of_Substance := 1.0E-09; -- nano
- umol : constant Amount_Of_Substance := 1.0E-06; -- micro (u)
- mmol : constant Amount_Of_Substance := 1.0E-03; -- milli
- cmol : constant Amount_Of_Substance := 1.0E-02; -- centi
- dmol : constant Amount_Of_Substance := 1.0E-01; -- deci
- damol : constant Amount_Of_Substance := 1.0E+01; -- deka
- hmol : constant Amount_Of_Substance := 1.0E+02; -- hecto
- kmol : constant Amount_Of_Substance := 1.0E+03; -- kilo
- Memol : constant Amount_Of_Substance := 1.0E+06; -- mega
- Gmol : constant Amount_Of_Substance := 1.0E+09; -- giga
- Tmol : constant Amount_Of_Substance := 1.0E+12; -- tera
- Pemol : constant Amount_Of_Substance := 1.0E+15; -- peta
- Emol : constant Amount_Of_Substance := 1.0E+18; -- exa
- Zemol : constant Amount_Of_Substance := 1.0E+21; -- zetta
- Yomol : constant Amount_Of_Substance := 1.0E+24; -- yotta
-
- -- SI prefixes for Candela
-
- ycd : constant Luminous_Intensity := 1.0E-24; -- yocto
- zcd : constant Luminous_Intensity := 1.0E-21; -- zepto
- acd : constant Luminous_Intensity := 1.0E-18; -- atto
- fcd : constant Luminous_Intensity := 1.0E-15; -- femto
- pcd : constant Luminous_Intensity := 1.0E-12; -- pico
- ncd : constant Luminous_Intensity := 1.0E-09; -- nano
- ucd : constant Luminous_Intensity := 1.0E-06; -- micro (u)
- mcd : constant Luminous_Intensity := 1.0E-03; -- milli
- ccd : constant Luminous_Intensity := 1.0E-02; -- centi
- dcd : constant Luminous_Intensity := 1.0E-01; -- deci
- dacd : constant Luminous_Intensity := 1.0E+01; -- deka
- hcd : constant Luminous_Intensity := 1.0E+02; -- hecto
- kcd : constant Luminous_Intensity := 1.0E+03; -- kilo
- Mecd : constant Luminous_Intensity := 1.0E+06; -- mega
- Gcd : constant Luminous_Intensity := 1.0E+09; -- giga
- Tcd : constant Luminous_Intensity := 1.0E+12; -- tera
- Pecd : constant Luminous_Intensity := 1.0E+15; -- peta
- Ecd : constant Luminous_Intensity := 1.0E+18; -- exa
- Zecd : constant Luminous_Intensity := 1.0E+21; -- zetta
- Yocd : constant Luminous_Intensity := 1.0E+24; -- yotta
-
- pragma Warnings (On);
-end System.Dim.Mks.Other_Prefixes;
+ new System.Dim.Mks.Generic_Other_Prefixes;
diff --git a/gcc/ada/sa_messages.adb b/gcc/ada/sa_messages.adb
new file mode 100644
index 0000000..30ae48c
--- /dev/null
+++ b/gcc/ada/sa_messages.adb
@@ -0,0 +1,539 @@
+------------------------------------------------------------------------------
+-- C O D E P E E R / S P A R K --
+-- --
+-- Copyright (C) 2015-2018, AdaCore --
+-- --
+-- This 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. This software is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
+-- TABILITY 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 this software; see file --
+-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
+-- of the license. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Directories; use Ada.Directories;
+with Ada.Strings.Unbounded.Hash;
+
+with Ada.Text_IO; use Ada.Text_IO;
+with GNATCOLL.JSON; use GNATCOLL.JSON;
+
+package body SA_Messages is
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function "<" (Left, Right : SA_Message) return Boolean is
+ (if Left.Kind /= Right.Kind then
+ Left.Kind < Right.Kind
+ else
+ Left.Kind in Check_Kind
+ and then Left.Check_Result < Right.Check_Result);
+
+ function "<" (Left, Right : Simple_Source_Location) return Boolean is
+ (if Left.File_Name /= Right.File_Name then
+ Left.File_Name < Right.File_Name
+ elsif Left.Line /= Right.Line then
+ Left.Line < Right.Line
+ else
+ Left.Column < Right.Column);
+
+ function "<" (Left, Right : Source_Locations) return Boolean is
+ (if Left'Length /= Right'Length then
+ Left'Length < Right'Length
+ elsif Left'Length = 0 then
+ False
+ elsif Left (Left'Last) /= Right (Right'Last) then
+ Left (Left'Last) < Right (Right'Last)
+ else
+ Left (Left'First .. Left'Last - 1) <
+ Right (Right'First .. Right'Last - 1));
+
+ function "<" (Left, Right : Source_Location) return Boolean is
+ (Left.Locations < Right.Locations);
+
+ function Base_Location
+ (Location : Source_Location) return Simple_Source_Location is
+ (Location.Locations (1));
+
+ function Hash (Key : SA_Message) return Hash_Type;
+ function Hash (Key : Source_Location) return Hash_Type;
+
+ ---------
+ -- "<" --
+ ---------
+
+ function "<" (Left, Right : Message_And_Location) return Boolean is
+ (if Left.Message = Right.Message
+ then Left.Location < Right.Location
+ else Left.Message < Right.Message);
+
+ ------------
+ -- Column --
+ ------------
+
+ function Column (Location : Source_Location) return Column_Number is
+ (Base_Location (Location).Column);
+
+ ---------------
+ -- File_Name --
+ ---------------
+
+ function File_Name (Location : Source_Location) return String is
+ (To_String (Base_Location (Location).File_Name));
+
+ function File_Name (Location : Source_Location) return Unbounded_String is
+ (Base_Location (Location).File_Name);
+
+ ------------------------
+ -- Enclosing_Instance --
+ ------------------------
+
+ function Enclosing_Instance
+ (Location : Source_Location) return Source_Location_Or_Null is
+ (Count => Location.Count - 1,
+ Locations => Location.Locations (2 .. Location.Count));
+
+ ----------
+ -- Hash --
+ ----------
+
+ function Hash (Key : Message_And_Location) return Hash_Type is
+ (Hash (Key.Message) + Hash (Key.Location));
+
+ function Hash (Key : SA_Message) return Hash_Type is
+ begin
+ return Result : Hash_Type :=
+ Hash_Type'Mod (Message_Kind'Pos (Key.Kind))
+ do
+ if Key.Kind in Check_Kind then
+ Result := Result +
+ Hash_Type'Mod (SA_Check_Result'Pos (Key.Check_Result));
+ end if;
+ end return;
+ end Hash;
+
+ function Hash (Key : Source_Location) return Hash_Type is
+ begin
+ return Result : Hash_Type := Hash_Type'Mod (Key.Count) do
+ for Loc of Key.Locations loop
+ Result := Result + Hash (Loc.File_Name);
+ Result := Result + Hash_Type'Mod (Loc.Line);
+ Result := Result + Hash_Type'Mod (Loc.Column);
+ end loop;
+ end return;
+ end Hash;
+
+ ---------------
+ -- Iteration --
+ ---------------
+
+ function Iteration (Location : Source_Location) return Iteration_Id is
+ (Base_Location (Location).Iteration);
+
+ ----------
+ -- Line --
+ ----------
+
+ function Line (Location : Source_Location) return Line_Number is
+ (Base_Location (Location).Line);
+
+ --------------
+ -- Location --
+ --------------
+
+ function Location
+ (Item : Message_And_Location) return Source_Location is
+ (Item.Location);
+
+ ----------
+ -- Make --
+ ----------
+
+ function Make
+ (File_Name : String;
+ Line : Line_Number;
+ Column : Column_Number;
+ Iteration : Iteration_Id;
+ Enclosing_Instance : Source_Location_Or_Null) return Source_Location
+ is
+ begin
+ return Result : Source_Location
+ (Count => Enclosing_Instance.Count + 1)
+ do
+ Result.Locations (1) :=
+ (File_Name => To_Unbounded_String (File_Name),
+ Line => Line,
+ Column => Column,
+ Iteration => Iteration);
+
+ Result.Locations (2 .. Result.Count) := Enclosing_Instance.Locations;
+ end return;
+ end Make;
+
+ ------------------
+ -- Make_Msg_Loc --
+ ------------------
+
+ function Make_Msg_Loc
+ (Msg : SA_Message;
+ Loc : Source_Location) return Message_And_Location
+ is
+ begin
+ return Message_And_Location'(Count => Loc.Count,
+ Message => Msg,
+ Location => Loc);
+ end Make_Msg_Loc;
+
+ -------------
+ -- Message --
+ -------------
+
+ function Message (Item : Message_And_Location) return SA_Message is
+ (Item.Message);
+
+ package Field_Names is
+
+ -- A Source_Location value is represented in JSON as a two or three
+ -- field value having fields Message_Kind (a string) and Locations (an
+ -- array); if the Message_Kind indicates a check kind, then a third
+ -- field is present: Check_Result (a string). The element type of the
+ -- Locations array is a value having at least 4 fields:
+ -- File_Name (a string), Line (an integer), Column (an integer),
+ -- and Iteration_Kind (an integer); if the Iteration_Kind field
+ -- has the value corresponding to the enumeration literal Numbered,
+ -- then two additional integer fields are present, Iteration_Number
+ -- and Iteration_Of_Total.
+
+ Check_Result : constant String := "Check_Result";
+ Column : constant String := "Column";
+ File_Name : constant String := "File_Name";
+ Iteration_Kind : constant String := "Iteration_Kind";
+ Iteration_Number : constant String := "Iteration_Number";
+ Iteration_Of_Total : constant String := "Iteration_Total";
+ Line : constant String := "Line";
+ Locations : constant String := "Locations";
+ Message_Kind : constant String := "Message_Kind";
+ Messages : constant String := "Messages";
+ end Field_Names;
+
+ package body Writing is
+ File : File_Type;
+ -- The file to which output will be written (in Close, not in Write)
+
+ Messages : JSON_Array;
+ -- Successive calls to Write append messages to this list
+
+ -----------------------
+ -- Local subprograms --
+ -----------------------
+
+ function To_JSON_Array
+ (Locations : Source_Locations) return JSON_Array;
+ -- Represent a Source_Locations array as a JSON_Array
+
+ function To_JSON_Value
+ (Location : Simple_Source_Location) return JSON_Value;
+ -- Represent a Simple_Source_Location as a JSON_Value
+
+ -----------
+ -- Close --
+ -----------
+
+ procedure Close is
+ Value : constant JSON_Value := Create_Object;
+
+ begin
+ -- only one field for now
+ Set_Field (Value, Field_Names.Messages, Messages);
+ Put_Line (File, Write (Item => Value, Compact => False));
+ Clear (Messages);
+ Close (File => File);
+ end Close;
+
+ -------------
+ -- Is_Open --
+ -------------
+
+ function Is_Open return Boolean is (Is_Open (File));
+
+ ----------
+ -- Open --
+ ----------
+
+ procedure Open (File_Name : String) is
+ begin
+ Create (File => File, Mode => Out_File, Name => File_Name);
+ Clear (Messages);
+ end Open;
+
+ -------------------
+ -- To_JSON_Array --
+ -------------------
+
+ function To_JSON_Array
+ (Locations : Source_Locations) return JSON_Array
+ is
+ begin
+ return Result : JSON_Array := Empty_Array do
+ for Location of Locations loop
+ Append (Result, To_JSON_Value (Location));
+ end loop;
+ end return;
+ end To_JSON_Array;
+
+ -------------------
+ -- To_JSON_Value --
+ -------------------
+
+ function To_JSON_Value
+ (Location : Simple_Source_Location) return JSON_Value
+ is
+ begin
+ return Result : constant JSON_Value := Create_Object do
+ Set_Field (Result, Field_Names.File_Name, Location.File_Name);
+ Set_Field (Result, Field_Names.Line, Integer (Location.Line));
+ Set_Field (Result, Field_Names.Column, Integer (Location.Column));
+ Set_Field (Result, Field_Names.Iteration_Kind, Integer'(
+ Iteration_Kind'Pos (Location.Iteration.Kind)));
+
+ if Location.Iteration.Kind = Numbered then
+ Set_Field (Result, Field_Names.Iteration_Number,
+ Location.Iteration.Number);
+ Set_Field (Result, Field_Names.Iteration_Of_Total,
+ Location.Iteration.Of_Total);
+ end if;
+ end return;
+ end To_JSON_Value;
+
+ -----------
+ -- Write --
+ -----------
+
+ procedure Write (Message : SA_Message; Location : Source_Location) is
+ Value : constant JSON_Value := Create_Object;
+
+ begin
+ Set_Field (Value, Field_Names.Message_Kind, Message.Kind'Img);
+
+ if Message.Kind in Check_Kind then
+ Set_Field
+ (Value, Field_Names.Check_Result, Message.Check_Result'Img);
+ end if;
+
+ Set_Field
+ (Value, Field_Names.Locations, To_JSON_Array (Location.Locations));
+ Append (Messages, Value);
+ end Write;
+ end Writing;
+
+ package body Reading is
+ File : File_Type;
+ -- The file from which messages are read (in Open, not in Read)
+
+ Messages : JSON_Array;
+ -- The list of messages that were read in from File
+
+ Next_Index : Positive;
+ -- The index of the message in Messages which will be returned by the
+ -- next call to Get.
+
+ Parse_Full_Path : Boolean := True;
+ -- if the full path or only the base name of the file should be parsed
+
+ -----------
+ -- Close --
+ -----------
+
+ procedure Close is
+ begin
+ Clear (Messages);
+ Close (File);
+ end Close;
+
+ ----------
+ -- Done --
+ ----------
+
+ function Done return Boolean is (Next_Index > Length (Messages));
+
+ ---------
+ -- Get --
+ ---------
+
+ function Get return Message_And_Location is
+ Value : constant JSON_Value := Get (Messages, Next_Index);
+
+ function Get_Message (Kind : Message_Kind) return SA_Message;
+ -- Return SA_Message of given kind, filling in any non-discriminant
+ -- by reading from Value.
+
+ function Make
+ (Location : Source_Location;
+ Message : SA_Message) return Message_And_Location;
+ -- Constructor
+
+ function To_Location
+ (Encoded : JSON_Array;
+ Full_Path : Boolean) return Source_Location;
+ -- Decode a Source_Location from JSON_Array representation
+
+ function To_Simple_Location
+ (Encoded : JSON_Value;
+ Full_Path : Boolean) return Simple_Source_Location;
+ -- Decode a Simple_Source_Location from JSON_Value representation
+
+ -----------------
+ -- Get_Message --
+ -----------------
+
+ function Get_Message (Kind : Message_Kind) return SA_Message is
+ begin
+ -- If we had AI12-0086, then we could use aggregates here (which
+ -- would be better than field-by-field assignment for the usual
+ -- maintainability reasons). But we don't, so we won't.
+
+ return Result : SA_Message (Kind => Kind) do
+ if Kind in Check_Kind then
+ Result.Check_Result :=
+ SA_Check_Result'Value
+ (Get (Value, Field_Names.Check_Result));
+ end if;
+ end return;
+ end Get_Message;
+
+ ----------
+ -- Make --
+ ----------
+
+ function Make
+ (Location : Source_Location;
+ Message : SA_Message) return Message_And_Location
+ is
+ (Count => Location.Count, Message => Message, Location => Location);
+
+ -----------------
+ -- To_Location --
+ -----------------
+
+ function To_Location
+ (Encoded : JSON_Array;
+ Full_Path : Boolean) return Source_Location is
+ begin
+ return Result : Source_Location (Count => Length (Encoded)) do
+ for I in Result.Locations'Range loop
+ Result.Locations (I) :=
+ To_Simple_Location (Get (Encoded, I), Full_Path);
+ end loop;
+ end return;
+ end To_Location;
+
+ ------------------------
+ -- To_Simple_Location --
+ ------------------------
+
+ function To_Simple_Location
+ (Encoded : JSON_Value;
+ Full_Path : Boolean) return Simple_Source_Location
+ is
+ function Get_Iteration_Id
+ (Kind : Iteration_Kind) return Iteration_Id;
+ -- Given the discriminant for an Iteration_Id value, return the
+ -- entire value.
+
+ ----------------------
+ -- Get_Iteration_Id --
+ ----------------------
+
+ function Get_Iteration_Id (Kind : Iteration_Kind)
+ return Iteration_Id
+ is
+ begin
+ -- Initialize non-discriminant fields, if any
+
+ return Result : Iteration_Id (Kind => Kind) do
+ if Kind = Numbered then
+ Result :=
+ (Kind => Numbered,
+ Number =>
+ Get (Encoded, Field_Names.Iteration_Number),
+ Of_Total =>
+ Get (Encoded, Field_Names.Iteration_Of_Total));
+ end if;
+ end return;
+ end Get_Iteration_Id;
+
+ -- Local variables
+
+ FN : constant Unbounded_String :=
+ Get (Encoded, Field_Names.File_Name);
+
+ -- Start of processing for To_Simple_Location
+
+ begin
+ return
+ (File_Name =>
+ (if Full_Path then
+ FN
+ else
+ To_Unbounded_String (Simple_Name (To_String (FN)))),
+ Line =>
+ Line_Number (Integer'(Get (Encoded, Field_Names.Line))),
+ Column =>
+ Column_Number (Integer'(Get (Encoded, Field_Names.Column))),
+ Iteration =>
+ Get_Iteration_Id
+ (Kind => Iteration_Kind'Val (Integer'(Get
+ (Encoded, Field_Names.Iteration_Kind)))));
+ end To_Simple_Location;
+
+ -- Start of processing for Get
+
+ begin
+ Next_Index := Next_Index + 1;
+
+ return Make
+ (Message =>
+ Get_Message
+ (Message_Kind'Value (Get (Value, Field_Names.Message_Kind))),
+ Location =>
+ To_Location
+ (Get (Value, Field_Names.Locations), Parse_Full_Path));
+ end Get;
+
+ -------------
+ -- Is_Open --
+ -------------
+
+ function Is_Open return Boolean is (Is_Open (File));
+
+ ----------
+ -- Open --
+ ----------
+
+ procedure Open (File_Name : String; Full_Path : Boolean := True) is
+ File_Text : Unbounded_String := Null_Unbounded_String;
+
+ begin
+ Parse_Full_Path := Full_Path;
+ Open (File => File, Mode => In_File, Name => File_Name);
+
+ -- File read here, not in Get, but that's an implementation detail
+
+ while not End_Of_File (File) loop
+ Append (File_Text, Get_Line (File));
+ end loop;
+
+ Messages := Get (Read (File_Text), Field_Names.Messages);
+ Next_Index := 1;
+ end Open;
+ end Reading;
+
+end SA_Messages;
diff --git a/gcc/ada/sa_messages.ads b/gcc/ada/sa_messages.ads
new file mode 100644
index 0000000..93226a7
--- /dev/null
+++ b/gcc/ada/sa_messages.ads
@@ -0,0 +1,267 @@
+------------------------------------------------------------------------------
+-- C O D E P E E R / S P A R K --
+-- --
+-- Copyright (C) 2015-2018, AdaCore --
+-- --
+-- This 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. This software is distributed in the hope that it will be useful, --
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
+-- TABILITY 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 this software; see file --
+-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
+-- of the license. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Containers; use Ada.Containers;
+with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
+
+package SA_Messages is
+
+ -- This package can be used for reading/writing a file containing a
+ -- sequence of static anaysis results. Each element can describe a runtime
+ -- check whose outcome has been statically determined, or it might be a
+ -- warning or diagnostic message. It is expected that typically CodePeer
+ -- will do the writing and SPARK will do the reading; this will allow SPARK
+ -- to get the benefit of CodePeer's analysis.
+ --
+ -- Each item is represented as a pair consisting of a message and an
+ -- associated source location. Source locations may refer to a location
+ -- within the expansion of an instance of a generic; this is represented
+ -- by combining the corresponding location within the generic with the
+ -- location of the instance (repeated if the instance itself occurs within
+ -- a generic). In addition, the type Iteration_Id is intended for use in
+ -- distinguishing messages which refer to a specific iteration of a loop
+ -- (this case can arise, for example, if CodePeer chooses to unroll a
+ -- for-loop). This data structure is only general enough to support the
+ -- kinds of unrolling that are currently planned for CodePeer. For
+ -- example, an Iteration_Id can only identify an iteration of the nearest
+ -- enclosing loop of the associated File/Line/Column source location.
+ -- This is not a problem because CodePeer doesn't unroll loops which
+ -- contain other loops.
+
+ type Message_Kind is (
+
+ -- Check kinds
+
+ Array_Index_Check,
+ Divide_By_Zero_Check,
+ Tag_Check,
+ Discriminant_Check,
+ Range_Check,
+ Overflow_Check,
+ Assertion_Check,
+
+ -- Warning kinds
+
+ Suspicious_Range_Precondition_Warning,
+ Suspicious_First_Precondition_Warning,
+ Suspicious_Input_Warning,
+ Suspicious_Constant_Operation_Warning,
+ Unread_In_Out_Parameter_Warning,
+ Unassigned_In_Out_Parameter_Warning,
+ Non_Analyzed_Call_Warning,
+ Procedure_Does_Not_Return_Warning,
+ Check_Fails_On_Every_Call_Warning,
+ Unknown_Call_Warning,
+ Dead_Store_Warning,
+ Dead_Outparam_Store_Warning,
+ Potentially_Dead_Store_Warning,
+ Same_Value_Dead_Store_Warning,
+ Dead_Block_Warning,
+ Infinite_Loop_Warning,
+ Dead_Edge_Warning,
+ Plain_Dead_Edge_Warning,
+ True_Dead_Edge_Warning,
+ False_Dead_Edge_Warning,
+ True_Condition_Dead_Edge_Warning,
+ False_Condition_Dead_Edge_Warning,
+ Unrepeatable_While_Loop_Warning,
+ Dead_Block_Continuation_Warning,
+ Local_Lock_Of_Global_Object_Warning,
+ Analyzed_Module_Warning,
+ Non_Analyzed_Module_Warning,
+ Non_Analyzed_Procedure_Warning,
+ Incompletely_Analyzed_Procedure_Warning);
+
+ -- Assertion_Check includes checks for user-defined PPCs (both specific
+ -- and class-wide), Assert pragma checks, subtype predicate checks,
+ -- type invariant checks (specific and class-wide), and checks for
+ -- implementation-defined assertions such as Assert_And_Cut, Assume,
+ -- Contract_Cases, Default_Initial_Condition, Initial_Condition,
+ -- Loop_Invariant, Loop_Variant, and Refined_Post.
+ --
+ -- TBD: it might be nice to distinguish these different kinds of assertions
+ -- as is done in SPARK's VC_Kind enumeration type, but any distinction
+ -- which isn't already present in CP's BE_Message_Subkind enumeration type
+ -- would require more work on the CP side.
+ --
+ -- The warning kinds are pretty much a copy of the set of
+ -- Be_Message_Subkind values for which CP's Is_Warning predicate returns
+ -- True; see descriptive comment for each in CP's message_kinds.ads .
+
+ subtype Check_Kind is Message_Kind
+ range Array_Index_Check .. Assertion_Check;
+ subtype Warning_Kind is Message_Kind
+ range Message_Kind'Succ (Check_Kind'Last) .. Message_Kind'Last;
+
+ -- Possible outcomes of the static analysis of a runtime check
+ --
+ -- Not_Statically_Known_With_Low_Severity could be used instead of of
+ -- Not_Statically_Known if there is some reason to believe that (although
+ -- the tool couldn't prove it) the check is likely to always pass (in CP
+ -- terms, if the corresponding CP message has severity Low as opposed to
+ -- Medium). It's not clear yet whether SPARK will care about this
+ -- distinction.
+
+ type SA_Check_Result is
+ (Statically_Known_Success,
+ Not_Statically_Known_With_Low_Severity,
+ Not_Statically_Known,
+ Statically_Known_Failure);
+
+ type SA_Message (Kind : Message_Kind := Message_Kind'Last) is record
+ case Kind is
+ when Check_Kind =>
+ Check_Result : SA_Check_Result;
+
+ when Warning_Kind =>
+ null;
+ end case;
+ end record;
+
+ type Source_Location_Or_Null (<>) is private;
+ Null_Location : constant Source_Location_Or_Null;
+ subtype Source_Location is Source_Location_Or_Null with
+ Dynamic_Predicate => Source_Location /= Null_Location;
+
+ type Line_Number is new Positive;
+ type Column_Number is new Positive;
+
+ function File_Name (Location : Source_Location) return String;
+ function File_Name (Location : Source_Location) return Unbounded_String;
+ function Line (Location : Source_Location) return Line_Number;
+ function Column (Location : Source_Location) return Column_Number;
+
+ type Iteration_Kind is (None, Initial, Subsequent, Numbered);
+ -- None is for the usual no-unrolling case.
+ -- Initial and Subsequent are for use in the case where only the first
+ -- iteration of a loop (or some part thereof, such as the termination
+ -- test of a while-loop) is unrolled.
+ -- Numbered is for use in the case where a for-loop with a statically
+ -- known number of iterations is fully unrolled.
+
+ subtype Iteration_Number is Integer range 1 .. 255;
+ subtype Iteration_Total is Integer range 2 .. 255;
+
+ type Iteration_Id (Kind : Iteration_Kind := None) is record
+ case Kind is
+ when Numbered =>
+ Number : Iteration_Number;
+ Of_Total : Iteration_Total;
+ when others =>
+ null;
+ end case;
+ end record;
+
+ function Iteration (Location : Source_Location) return Iteration_Id;
+
+ function Enclosing_Instance
+ (Location : Source_Location) return Source_Location_Or_Null;
+ -- For a source location occurring within the expansion of an instance of a
+ -- generic unit, the Line, Column, and File_Name selectors will indicate a
+ -- location within the generic; the Enclosing_Instance selector yields the
+ -- location of the declaration of the instance.
+
+ function Make
+ (File_Name : String;
+ Line : Line_Number;
+ Column : Column_Number;
+ Iteration : Iteration_Id;
+ Enclosing_Instance : Source_Location_Or_Null) return Source_Location;
+ -- Constructor
+
+ type Message_And_Location (<>) is private;
+
+ function Location (Item : Message_And_Location) return Source_Location;
+ function Message (Item : Message_And_Location) return SA_Message;
+
+ function Make_Msg_Loc
+ (Msg : SA_Message;
+ Loc : Source_Location) return Message_And_Location;
+ -- Selectors
+
+ function "<" (Left, Right : Message_And_Location) return Boolean;
+ function Hash (Key : Message_And_Location) return Hash_Type;
+ -- Actuals for container instances
+
+ File_Extension : constant String; -- ".json" (but could change in future)
+ -- Clients may wish to use File_Extension in constructing
+ -- File_Name parameters for calls to Open.
+
+ package Writing is
+ function Is_Open return Boolean;
+
+ procedure Open (File_Name : String) with
+ Precondition => not Is_Open,
+ Postcondition => Is_Open;
+ -- Behaves like Text_IO.Create with respect to error cases
+
+ procedure Write (Message : SA_Message; Location : Source_Location);
+
+ procedure Close with
+ Precondition => Is_Open,
+ Postcondition => not Is_Open;
+ -- Behaves like Text_IO.Close with respect to error cases
+ end Writing;
+
+ package Reading is
+ function Is_Open return Boolean;
+
+ procedure Open (File_Name : String; Full_Path : Boolean := True) with
+ Precondition => not Is_Open,
+ Postcondition => Is_Open;
+ -- Behaves like Text_IO.Open with respect to error cases
+
+ function Done return Boolean with
+ Precondition => Is_Open;
+
+ function Get return Message_And_Location with
+ Precondition => not Done;
+
+ procedure Close with
+ Precondition => Is_Open,
+ Postcondition => not Is_Open;
+ -- Behaves like Text_IO.Close with respect to error cases
+ end Reading;
+
+private
+ type Simple_Source_Location is record
+ File_Name : Unbounded_String := Null_Unbounded_String;
+ Line : Line_Number := Line_Number'Last;
+ Column : Column_Number := Column_Number'Last;
+ Iteration : Iteration_Id := (Kind => None);
+ end record;
+
+ type Source_Locations is
+ array (Natural range <>) of Simple_Source_Location;
+
+ type Source_Location_Or_Null (Count : Natural) is record
+ Locations : Source_Locations (1 .. Count);
+ end record;
+
+ Null_Location : constant Source_Location_Or_Null :=
+ (Count => 0, Locations => (others => <>));
+
+ type Message_And_Location (Count : Positive) is record
+ Message : SA_Message;
+ Location : Source_Location (Count => Count);
+ end record;
+
+ File_Extension : constant String := ".json";
+end SA_Messages;
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index cb1b2d5d..96eb488 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -11245,6 +11245,15 @@ package body Sem_Attr is
New_Occurrence_Of (Standard_Short_Integer, Loc),
Expression =>
Make_Integer_Literal (Loc, Uint_0)));
+
+ -- The above sets the Scope of the flag entity to the
+ -- current scope, in which the attribute appears, but
+ -- the flag declaration has been inserted after that
+ -- of Subp_Id, so the scope of the flag the same as
+ -- that of Subp_Id. This is relevant when unnesting,
+ -- whereh processing depends on correct scope settingl
+
+ Set_Scope (Flag_Id, Scop);
end if;
-- Taking the 'Access of an expression function freezes its
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index 39ed046..e6d0ba5 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -34,7 +34,6 @@ with Elists; use Elists;
with Fname; use Fname;
with Fname.UF; use Fname.UF;
with Freeze; use Freeze;
-with Ghost; use Ghost;
with Impunit; use Impunit;
with Inline; use Inline;
with Lib; use Lib;
@@ -2912,8 +2911,6 @@ package body Sem_Ch10 is
Set_Fatal_Error (Current_Sem_Unit, Error_Ignored);
end if;
end case;
-
- Mark_Ghost_Clause (N);
end Analyze_With_Clause;
------------------------------
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 28a3dd8..00854c9 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -8765,44 +8765,45 @@ package body Sem_Ch13 is
if Raise_Expression_Present then
declare
- Map : constant Elist_Id := New_Elmt_List;
- New_V : Entity_Id := Empty;
+ function Reset_Loop_Variable
+ (N : Node_Id) return Traverse_Result;
- -- The unanalyzed expression will be copied and appear in
- -- both functions. Normally expressions do not declare new
- -- entities, but quantified expressions do, so we need to
- -- create new entities for their bound variables, to prevent
- -- multiple definitions in gigi.
-
- function Reset_Loop_Variable (N : Node_Id)
- return Traverse_Result;
-
- procedure Collect_Loop_Variables is
+ procedure Reset_Loop_Variables is
new Traverse_Proc (Reset_Loop_Variable);
------------------------
-- Reset_Loop_Variable --
------------------------
- function Reset_Loop_Variable (N : Node_Id)
- return Traverse_Result
+ function Reset_Loop_Variable
+ (N : Node_Id) return Traverse_Result
is
begin
if Nkind (N) = N_Iterator_Specification then
- New_V := Make_Defining_Identifier
- (Sloc (N), Chars (Defining_Identifier (N)));
-
- Set_Defining_Identifier (N, New_V);
+ Set_Defining_Identifier (N,
+ Make_Defining_Identifier
+ (Sloc (N), Chars (Defining_Identifier (N))));
end if;
return OK;
end Reset_Loop_Variable;
+ -- Local variables
+
+ Map : constant Elist_Id := New_Elmt_List;
+
begin
Append_Elmt (Object_Entity, Map);
Append_Elmt (Object_Entity_M, Map);
Expr_M := New_Copy_Tree (Expr, Map => Map);
- Collect_Loop_Variables (Expr_M);
+
+ -- The unanalyzed expression will be copied and appear in
+ -- both functions. Normally expressions do not declare new
+ -- entities, but quantified expressions do, so we need to
+ -- create new entities for their bound variables, to prevent
+ -- multiple definitions in gigi.
+
+ Reset_Loop_Variables (Expr_M);
end;
end if;
@@ -8856,6 +8857,43 @@ package body Sem_Ch13 is
Insert_After_And_Analyze (N, FBody);
+ -- The defining identifier of a quantified expression carries the
+ -- scope in which the type appears, but when unnesting we need
+ -- to indicate that its proper scope is the constructed predicate
+ -- function. The quantified expressions have been converted into
+ -- loops during analysis and expansion.
+
+ declare
+ function Reset_Quantified_Variable_Scope
+ (N : Node_Id) return Traverse_Result;
+
+ procedure Reset_Quantified_Variables_Scope is
+ new Traverse_Proc (Reset_Quantified_Variable_Scope);
+
+ -------------------------------------
+ -- Reset_Quantified_Variable_Scope --
+ -------------------------------------
+
+ function Reset_Quantified_Variable_Scope
+ (N : Node_Id) return Traverse_Result
+ is
+ begin
+ if Nkind_In (N, N_Iterator_Specification,
+ N_Loop_Parameter_Specification)
+ then
+ Set_Scope (Defining_Identifier (N),
+ Predicate_Function (Typ));
+ end if;
+
+ return OK;
+ end Reset_Quantified_Variable_Scope;
+
+ begin
+ if Unnest_Subprogram_Mode then
+ Reset_Quantified_Variables_Scope (Expr);
+ end if;
+ end;
+
-- within a generic unit, prevent a double analysis of the body
-- which will not be marked analyzed yet. This will happen when
-- the freeze node is created during the preanalysis of an
@@ -8972,6 +9010,8 @@ package body Sem_Ch13 is
Insert_Before_And_Analyze (N, FDecl);
Insert_After_And_Analyze (N, FBody);
+
+ -- Should quantified expressions be handled here as well ???
end;
end if;
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index 349ece7..cc84f9c 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -9453,6 +9453,7 @@ package body Sem_Ch3 is
(Derived_Type, Save_Discr_Constr);
Set_Stored_Constraint
(Derived_Type, Expand_To_Stored_Constraint (Parent_Type, Discs));
+
Replace_Components (Derived_Type, New_Decl);
end if;
@@ -13692,7 +13693,12 @@ package body Sem_Ch3 is
Related_Nod : Node_Id) return Entity_Id
is
T_Sub : constant Entity_Id :=
- Create_Itype (E_Record_Subtype, Related_Nod, Corr_Rec, 'C');
+ Create_Itype
+ (Ekind => E_Record_Subtype,
+ Related_Nod => Related_Nod,
+ Related_Id => Corr_Rec,
+ Suffix => 'C',
+ Suffix_Index => -1);
begin
Set_Etype (T_Sub, Corr_Rec);
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 2dd9d2f..b330426 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -285,208 +285,6 @@ package body Sem_Ch6 is
LocX : constant Source_Ptr := Sloc (Expr);
Spec : constant Node_Id := Specification (N);
- procedure Freeze_Expr_Types (Def_Id : Entity_Id);
- -- N is an expression function that is a completion and Def_Id its
- -- defining entity. Freeze before N all the types referenced by the
- -- expression of the function.
-
- -----------------------
- -- Freeze_Expr_Types --
- -----------------------
-
- procedure Freeze_Expr_Types (Def_Id : Entity_Id) is
- function Cloned_Expression return Node_Id;
- -- Build a duplicate of the expression of the return statement that
- -- has no defining entities shared with the original expression.
-
- function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result;
- -- Freeze all types referenced in the subtree rooted at Node
-
- -----------------------
- -- Cloned_Expression --
- -----------------------
-
- function Cloned_Expression return Node_Id is
- function Clone_Id (Node : Node_Id) return Traverse_Result;
- -- Tree traversal routine that clones the defining identifier of
- -- iterator and loop parameter specification nodes.
-
- --------------
- -- Clone_Id --
- --------------
-
- function Clone_Id (Node : Node_Id) return Traverse_Result is
- begin
- if Nkind_In (Node, N_Iterator_Specification,
- N_Loop_Parameter_Specification)
- then
- Set_Defining_Identifier (Node,
- New_Copy (Defining_Identifier (Node)));
- end if;
-
- return OK;
- end Clone_Id;
-
- procedure Clone_Def_Ids is new Traverse_Proc (Clone_Id);
-
- -- Local variable
-
- Dup_Expr : constant Node_Id := New_Copy_Tree (Expr);
-
- -- Start of processing for Cloned_Expression
-
- begin
- -- We must duplicate the expression with semantic information to
- -- inherit the decoration of global entities in generic instances.
- -- Set the parent of the new node to be the parent of the original
- -- to get the proper context, which is needed for complete error
- -- reporting and for semantic analysis.
-
- Set_Parent (Dup_Expr, Parent (Expr));
-
- -- Replace the defining identifier of iterators and loop param
- -- specifications by a clone to ensure that the cloned expression
- -- and the original expression don't have shared identifiers;
- -- otherwise, as part of the preanalysis of the expression, these
- -- shared identifiers may be left decorated with itypes which
- -- will not be available in the tree passed to the backend.
-
- Clone_Def_Ids (Dup_Expr);
-
- return Dup_Expr;
- end Cloned_Expression;
-
- ----------------------
- -- Freeze_Type_Refs --
- ----------------------
-
- function Freeze_Type_Refs (Node : Node_Id) return Traverse_Result is
- procedure Check_And_Freeze_Type (Typ : Entity_Id);
- -- Check that Typ is fully declared and freeze it if so
-
- ---------------------------
- -- Check_And_Freeze_Type --
- ---------------------------
-
- procedure Check_And_Freeze_Type (Typ : Entity_Id) is
- begin
- -- Skip Itypes created by the preanalysis, and itypes whose
- -- scope is another type (i.e. component subtypes that depend
- -- on a discriminant),
-
- if Is_Itype (Typ)
- and then (Scope_Within_Or_Same (Scope (Typ), Def_Id)
- or else Is_Type (Scope (Typ)))
- then
- return;
- end if;
-
- -- This provides a better error message than generating
- -- primitives whose compilation fails much later. Refine
- -- the error message if possible.
-
- Check_Fully_Declared (Typ, Node);
-
- if Error_Posted (Node) then
- if Has_Private_Component (Typ)
- and then not Is_Private_Type (Typ)
- then
- Error_Msg_NE ("\type& has private component", Node, Typ);
- end if;
-
- else
- Freeze_Before (N, Typ);
- end if;
- end Check_And_Freeze_Type;
-
- -- Start of processing for Freeze_Type_Refs
-
- begin
- -- Check that a type referenced by an entity can be frozen
-
- if Is_Entity_Name (Node) and then Present (Entity (Node)) then
- Check_And_Freeze_Type (Etype (Entity (Node)));
-
- -- Check that the enclosing record type can be frozen
-
- if Ekind_In (Entity (Node), E_Component, E_Discriminant) then
- Check_And_Freeze_Type (Scope (Entity (Node)));
- end if;
-
- -- Freezing an access type does not freeze the designated type,
- -- but freezing conversions between access to interfaces requires
- -- that the interface types themselves be frozen, so that dispatch
- -- table entities are properly created.
-
- -- Unclear whether a more general rule is needed ???
-
- elsif Nkind (Node) = N_Type_Conversion
- and then Is_Access_Type (Etype (Node))
- and then Is_Interface (Designated_Type (Etype (Node)))
- then
- Check_And_Freeze_Type (Designated_Type (Etype (Node)));
- end if;
-
- -- An implicit dereference freezes the designated type. In the
- -- case of a dispatching call whose controlling argument is an
- -- access type, the dereference is not made explicit, so we must
- -- check for such a call and freeze the designated type.
-
- if Nkind (Node) in N_Has_Etype
- and then Present (Etype (Node))
- and then Is_Access_Type (Etype (Node))
- and then Nkind (Parent (Node)) = N_Function_Call
- and then Node = Controlling_Argument (Parent (Node))
- then
- Check_And_Freeze_Type (Designated_Type (Etype (Node)));
- end if;
-
- -- No point in posting several errors on the same expression
-
- if Serious_Errors_Detected > 0 then
- return Abandon;
- else
- return OK;
- end if;
- end Freeze_Type_Refs;
-
- procedure Freeze_References is new Traverse_Proc (Freeze_Type_Refs);
-
- -- Local variables
-
- Saved_First_Entity : constant Entity_Id := First_Entity (Def_Id);
- Saved_Last_Entity : constant Entity_Id := Last_Entity (Def_Id);
- Dup_Expr : constant Node_Id := Cloned_Expression;
-
- -- Start of processing for Freeze_Expr_Types
-
- begin
- -- Preanalyze a duplicate of the expression to have available the
- -- minimum decoration needed to locate referenced unfrozen types
- -- without adding any decoration to the function expression.
-
- Push_Scope (Def_Id);
- Install_Formals (Def_Id);
-
- Preanalyze_Spec_Expression (Dup_Expr, Etype (Def_Id));
- End_Scope;
-
- -- Restore certain attributes of Def_Id since the preanalysis may
- -- have introduced itypes to this scope, thus modifying attributes
- -- First_Entity and Last_Entity.
-
- Set_First_Entity (Def_Id, Saved_First_Entity);
- Set_Last_Entity (Def_Id, Saved_Last_Entity);
-
- if Present (Last_Entity (Def_Id)) then
- Set_Next_Entity (Last_Entity (Def_Id), Empty);
- end if;
-
- -- Freeze all types referenced in the expression
-
- Freeze_References (Dup_Expr);
- end Freeze_Expr_Types;
-
-- Local variables
Asp : Node_Id;
@@ -600,7 +398,11 @@ package body Sem_Ch6 is
-- As elsewhere, we do not emit freeze nodes within a generic unit.
if not Inside_A_Generic then
- Freeze_Expr_Types (Def_Id);
+ Freeze_Expr_Types
+ (Def_Id => Def_Id,
+ Typ => Etype (Def_Id),
+ Expr => Expr,
+ N => N);
end if;
-- For navigation purposes, indicate that the function is a body
@@ -3347,8 +3149,12 @@ package body Sem_Ch6 is
end if;
if not Is_Frozen (Typ) then
- Set_Is_Frozen (Typ);
- Append_New_Elmt (Typ, Result);
+ if Scope (Typ) /= Current_Scope then
+ Set_Is_Frozen (Typ);
+ Append_New_Elmt (Typ, Result);
+ else
+ Freeze_Before (N, Typ);
+ end if;
end if;
end Mask_Type;
@@ -3838,28 +3644,28 @@ package body Sem_Ch6 is
-- They are necessary in any case to insure order of elaboration
-- in gigi.
- if not Is_Frozen (Spec_Id)
+ if Nkind (N) = N_Subprogram_Body
+ and then Was_Expression_Function (N)
+ and then not Has_Completion (Spec_Id)
+ and then Serious_Errors_Detected = 0
and then (Expander_Active
or else ASIS_Mode
- or else (Operating_Mode = Check_Semantics
- and then Serious_Errors_Detected = 0))
+ or else Operating_Mode = Check_Semantics)
then
-- The body generated for an expression function that is not a
-- completion is a freeze point neither for the profile nor for
-- anything else. That's why, in order to prevent any freezing
-- during analysis, we need to mask types declared outside the
- -- expression that are not yet frozen.
+ -- expression (and in an outer scope) that are not yet frozen.
- if Nkind (N) = N_Subprogram_Body
- and then Was_Expression_Function (N)
- and then not Has_Completion (Spec_Id)
- then
- Set_Is_Frozen (Spec_Id);
- Mask_Types := Mask_Unfrozen_Types (Spec_Id);
- else
- Set_Has_Delayed_Freeze (Spec_Id);
- Freeze_Before (N, Spec_Id);
- end if;
+ Set_Is_Frozen (Spec_Id);
+ Mask_Types := Mask_Unfrozen_Types (Spec_Id);
+
+ elsif not Is_Frozen (Spec_Id)
+ and then Serious_Errors_Detected = 0
+ then
+ Set_Has_Delayed_Freeze (Spec_Id);
+ Freeze_Before (N, Spec_Id);
end if;
end if;
@@ -7439,14 +7245,16 @@ package body Sem_Ch6 is
end if;
end;
- -- Functions can override abstract interface functions
+ -- Functions can override abstract interface functions. Return
+ -- types must be subtype conformant.
elsif Ekind (Def_Id) = E_Function
and then Ekind (Subp) = E_Function
and then Matches_Prefixed_View_Profile
(Parameter_Specifications (Parent (Def_Id)),
Parameter_Specifications (Parent (Subp)))
- and then Etype (Def_Id) = Etype (Subp)
+ and then Conforming_Types
+ (Etype (Def_Id), Etype (Subp), Subtype_Conformant)
then
Candidate := Subp;
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index ddfa543..2002b75 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -6067,7 +6067,10 @@ package body Sem_Res is
-- (including the body of another expression function) which would
-- place the freeze node in the wrong scope. An expression function
-- is frozen in the usual fashion, by the appearance of a real body,
- -- or at the end of a declarative part.
+ -- or at the end of a declarative part. However an implcit call to
+ -- an expression function may appear when it is part of a default
+ -- expression in a call to an initialiation procedure, and must be
+ -- frozen now, even if the body is inserted at a later point.
if Is_Entity_Name (Subp)
and then not In_Spec_Expression
@@ -6076,12 +6079,20 @@ package body Sem_Res is
(not Is_Expression_Function_Or_Completion (Entity (Subp))
or else Scope (Entity (Subp)) = Current_Scope)
then
+ if Is_Expression_Function (Entity (Subp)) then
+
+ -- Force freeze of expression function in call
+
+ Set_Comes_From_Source (Subp, True);
+ Set_Must_Not_Freeze (Subp, False);
+ end if;
+
Freeze_Expression (Subp);
end if;
-- For a predefined operator, the type of the result is the type imposed
-- by context, except for a predefined operation on universal fixed.
- -- Otherwise The type of the call is the type returned by the subprogram
+ -- Otherwise the type of the call is the type returned by the subprogram
-- being called.
if Is_Predefined_Op (Nam) then
@@ -6117,7 +6128,25 @@ package body Sem_Res is
Ret_Type : constant Entity_Id := Etype (Nam);
begin
- if Is_Access_Type (Ret_Type)
+ -- If this is a parameterless call there is no ambiguity and the
+ -- call has the type of the function.
+
+ if No (First_Actual (N)) then
+ Set_Etype (N, Etype (Nam));
+
+ if Present (First_Formal (Nam)) then
+ Resolve_Actuals (N, Nam);
+ end if;
+
+ -- Annotate the tree by creating a call marker in case the
+ -- original call is transformed by expansion. The call marker
+ -- is automatically saved for later examination by the ABE
+ -- Processing phase.
+
+ Build_Call_Marker (N);
+
+ elsif Is_Access_Type (Ret_Type)
+
and then Ret_Type = Component_Type (Designated_Type (Ret_Type))
then
Error_Msg_N
diff --git a/gcc/ada/sem_spark.adb b/gcc/ada/sem_spark.adb
index 3abfd99..e522620 100644
--- a/gcc/ada/sem_spark.adb
+++ b/gcc/ada/sem_spark.adb
@@ -52,15 +52,16 @@ package body Sem_SPARK is
type Elaboration_Context_Index is range 0 .. Elaboration_Context_Max - 1;
- function Elaboration_Context_Hash
- (Key : Entity_Id) return Elaboration_Context_Index;
+ function Elaboration_Context_Hash (Key : Entity_Id)
+ return Elaboration_Context_Index;
-- Function to hash any node of the AST
- type Perm_Kind is (No_Access, Read_Only, Read_Write, Write_Only);
- -- Permission type associated with paths
-
- subtype Read_Perm is Perm_Kind range Read_Only .. Read_Write;
- subtype Write_Perm is Perm_Kind range Read_Write .. Write_Only;
+ type Perm_Kind is (Borrowed, Observed, Unrestricted, Moved);
+ -- Permission type associated with paths. The Moved permission is
+ -- equivalent to the Unrestricted one (same permissions). The Moved is
+ -- however used to mark the RHS after a move (which still unrestricted).
+ -- This way, we may generate warnings when manipulating the RHS
+ -- afterwads since it is set to Null after the assignment.
type Perm_Tree_Wrapper;
@@ -94,6 +95,7 @@ package body Sem_SPARK is
-- The definition of permission trees. This is a tree, which has a
-- permission at each node, and depending on the type of the node,
-- can have zero, one, or more children pointed to by an access to tree.
+
type Perm_Tree (Kind : Path_Kind := Entire_Object) is record
Permission : Perm_Kind;
-- Permission at this level in the path
@@ -103,7 +105,6 @@ package body Sem_SPARK is
-- path.
case Kind is
-
-- An entire object is either a leaf (an object which cannot be
-- extended further in a path) or a subtree in folded form (which
-- could later be unfolded further in another kind of node). The
@@ -111,19 +112,19 @@ package body Sem_SPARK is
-- extension of that node if that permission is different from
-- the node's permission.
- when Entire_Object =>
+ when Entire_Object =>
Children_Permission : Perm_Kind;
-- Unfolded path of access type. The permission of the object
-- pointed to is given in Get_All.
- when Reference =>
+ when Reference =>
Get_All : Perm_Tree_Access;
-- Unfolded path of array type. The permission of the elements is
-- given in Get_Elem.
- when Array_Component =>
+ when Array_Component =>
Get_Elem : Perm_Tree_Access;
-- Unfolded path of record type. The permission of the regular
@@ -229,7 +230,7 @@ package body Sem_SPARK is
--------------------
procedure Perm_Mismatch
- (Exp_Perm, Act_Perm : Perm_Kind;
+ (Exp_Perm, Act_Perm : Perm_Kind;
N : Node_Id);
-- Issues a continuation error message about a mismatch between a
-- desired permission Exp_Perm and a permission obtained Act_Perm. N
@@ -243,10 +244,7 @@ package body Sem_SPARK is
-- Children_Permission --
-------------------------
- function Children_Permission
- (T : Perm_Tree_Access)
- return Perm_Kind
- is
+ function Children_Permission (T : Perm_Tree_Access) return Perm_Kind is
begin
return T.all.Tree.Children_Permission;
end Children_Permission;
@@ -257,7 +255,7 @@ package body Sem_SPARK is
function Component
(T : Perm_Tree_Access)
- return Perm_Tree_Maps.Instance
+ return Perm_Tree_Maps.Instance
is
begin
return T.all.Tree.Component;
@@ -267,13 +265,10 @@ package body Sem_SPARK is
-- Copy_Env --
--------------
- procedure Copy_Env
- (From : Perm_Env;
- To : in out Perm_Env)
- is
+ procedure Copy_Env (From : Perm_Env; To : in out Perm_Env) is
Comp_From : Perm_Tree_Access;
- Key_From : Perm_Tree_Maps.Key_Option;
- Son : Perm_Tree_Access;
+ Key_From : Perm_Tree_Maps.Key_Option;
+ Son : Perm_Tree_Access;
begin
Reset (To);
@@ -296,7 +291,7 @@ package body Sem_SPARK is
procedure Copy_Init_Map
(From : Initialization_Map;
- To : in out Initialization_Map)
+ To : in out Initialization_Map)
is
Comp_From : Boolean;
Key_From : Boolean_Variables_Maps.Key_Option;
@@ -315,25 +310,19 @@ package body Sem_SPARK is
-- Copy_Tree --
---------------
- procedure Copy_Tree
- (From : Perm_Tree_Access;
- To : Perm_Tree_Access)
- is
+ procedure Copy_Tree (From : Perm_Tree_Access; To : Perm_Tree_Access) is
begin
To.all := From.all;
-
case Kind (From) is
when Entire_Object =>
null;
when Reference =>
To.all.Tree.Get_All := new Perm_Tree_Wrapper;
-
Copy_Tree (Get_All (From), Get_All (To));
when Array_Component =>
To.all.Tree.Get_Elem := new Perm_Tree_Wrapper;
-
Copy_Tree (Get_Elem (From), Get_Elem (To));
when Record_Component =>
@@ -346,31 +335,26 @@ package body Sem_SPARK is
-- We put a new hash table, so that it gets dealiased from the
-- Component (From) hash table.
To.all.Tree.Component := Hash_Table;
-
To.all.Tree.Other_Components :=
new Perm_Tree_Wrapper'(Other_Components (From).all);
-
Copy_Tree (Other_Components (From), Other_Components (To));
-
Key_From := Perm_Tree_Maps.Get_First_Key
(Component (From));
+
while Key_From.Present loop
Comp_From := Perm_Tree_Maps.Get
(Component (From), Key_From.K);
-
pragma Assert (Comp_From /= null);
Son := new Perm_Tree_Wrapper;
-
Copy_Tree (Comp_From, Son);
-
Perm_Tree_Maps.Set
(To.all.Tree.Component, Key_From.K, Son);
-
Key_From := Perm_Tree_Maps.Get_Next_Key
(Component (From));
end loop;
end;
end case;
+
end Copy_Tree;
------------------------------
@@ -402,9 +386,7 @@ package body Sem_SPARK is
-- Free_Perm_Tree --
--------------------
- procedure Free_Perm_Tree
- (PT : in out Perm_Tree_Access)
- is
+ procedure Free_Perm_Tree (PT : in out Perm_Tree_Access) is
procedure Free_Perm_Tree_Dealloc is
new Ada.Unchecked_Deallocation
(Perm_Tree_Wrapper, Perm_Tree_Access);
@@ -430,6 +412,7 @@ package body Sem_SPARK is
Free_Perm_Tree (PT.all.Tree.Other_Components);
Comp := Perm_Tree_Maps.Get_First (Component (PT));
while Comp /= null loop
+
-- Free every Component subtree
Free_Perm_Tree (Comp);
@@ -444,10 +427,7 @@ package body Sem_SPARK is
-- Get_All --
-------------
- function Get_All
- (T : Perm_Tree_Access)
- return Perm_Tree_Access
- is
+ function Get_All (T : Perm_Tree_Access) return Perm_Tree_Access is
begin
return T.all.Tree.Get_All;
end Get_All;
@@ -456,10 +436,7 @@ package body Sem_SPARK is
-- Get_Elem --
--------------
- function Get_Elem
- (T : Perm_Tree_Access)
- return Perm_Tree_Access
- is
+ function Get_Elem (T : Perm_Tree_Access) return Perm_Tree_Access is
begin
return T.all.Tree.Get_Elem;
end Get_Elem;
@@ -468,10 +445,7 @@ package body Sem_SPARK is
-- Is_Node_Deep --
------------------
- function Is_Node_Deep
- (T : Perm_Tree_Access)
- return Boolean
- is
+ function Is_Node_Deep (T : Perm_Tree_Access) return Boolean is
begin
return T.all.Tree.Is_Node_Deep;
end Is_Node_Deep;
@@ -480,10 +454,7 @@ package body Sem_SPARK is
-- Kind --
----------
- function Kind
- (T : Perm_Tree_Access)
- return Path_Kind
- is
+ function Kind (T : Perm_Tree_Access) return Path_Kind is
begin
return T.all.Tree.Kind;
end Kind;
@@ -494,7 +465,7 @@ package body Sem_SPARK is
function Other_Components
(T : Perm_Tree_Access)
- return Perm_Tree_Access
+ return Perm_Tree_Access
is
begin
return T.all.Tree.Other_Components;
@@ -504,10 +475,7 @@ package body Sem_SPARK is
-- Permission --
----------------
- function Permission
- (T : Perm_Tree_Access)
- return Perm_Kind
- is
+ function Permission (T : Perm_Tree_Access) return Perm_Kind is
begin
return T.all.Tree.Permission;
end Permission;
@@ -516,13 +484,10 @@ package body Sem_SPARK is
-- Perm_Mismatch --
-------------------
- procedure Perm_Mismatch
- (Exp_Perm, Act_Perm : Perm_Kind;
- N : Node_Id)
- is
+ procedure Perm_Mismatch (Exp_Perm, Act_Perm : Perm_Kind; N : Node_Id) is
begin
- Error_Msg_N ("\expected at least `"
- & Perm_Kind'Image (Exp_Perm) & "`, got `"
+ Error_Msg_N ("\expected state `"
+ & Perm_Kind'Image (Exp_Perm) & "` at least, got `"
& Perm_Kind'Image (Act_Perm) & "`", N);
end Perm_Mismatch;
@@ -543,34 +508,29 @@ package body Sem_SPARK is
-- Default mode. Checks that paths have Read_Perm permission.
Move,
- -- Regular moving semantics (not under 'Access). Checks that paths have
- -- Read_Write permission. After moving a path, its permission is set to
- -- Write_Only and the permission of its extensions is set to No_Access.
+ -- Regular moving semantics. Checks that paths have
+ -- Unrestricted permission. After moving a path, its permission is set
+ -- to Unrestricted and the permission of its extensions is set
+ -- to Unrestricted.
Assign,
-- Used for the target of an assignment, or an actual parameter with
- -- mode OUT. Checks that paths have Write_Perm permission. After
- -- assigning to a path, its permission is set to Read_Write.
-
- Super_Move,
- -- Enhanced moving semantics (under 'Access). Checks that paths have
- -- Read_Write permission (shallow types may have only Write permission).
- -- After moving a path, its permission is set to No_Access, as well as
- -- the permission of its extensions and the permission of its prefixes
- -- up to the first Reference node.
-
- Borrow_Out,
- -- Used for actual OUT parameters. Checks that paths have Write_Perm
- -- permission. After checking a path, its permission is set to Read_Only
- -- when of a by-copy type, to No_Access otherwise. After the call, its
- -- permission is set to Read_Write.
+ -- mode OUT. Checks that paths have Unrestricted permission. After
+ -- assigning to a path, its permission is set to Unrestricted.
+
+ Borrow,
+ -- Used for the source of an assignement when initializes a stand alone
+ -- object of anonymous type, constant, or IN parameter and also OUT
+ -- or IN OUT composite object.
+ -- In the borrowed state, the access object is completely "dead".
Observe
-- Used for actual IN parameters of a scalar type. Checks that paths
-- have Read_Perm permission. After checking a path, its permission
- -- is set to Read_Only.
+ -- is set to Observed.
--
-- Also used for formal IN parameters
+
);
type Result_Kind is (Folded, Unfolded, Function_Call);
@@ -593,11 +553,6 @@ package body Sem_SPARK is
-- Local subprograms --
-----------------------
- function "<=" (P1, P2 : Perm_Kind) return Boolean;
- function ">=" (P1, P2 : Perm_Kind) return Boolean;
- function Glb (P1, P2 : Perm_Kind) return Perm_Kind;
- function Lub (P1, P2 : Perm_Kind) return Perm_Kind;
-
-- Checking proceduress for safe pointer usage. These procedures traverse
-- the AST, check nodes for correct permissions according to SPARK RM
-- 6.4.2, and update permissions depending on the node kind.
@@ -608,24 +563,15 @@ package body Sem_SPARK is
-- We are not in End_Of_Callee mode, hence we will save the environment
-- and start from a new one. We will add in the environment all formal
-- parameters as well as global used during the subprogram, with the
- -- appropriate permissions (write-only for out, read-only for observed,
- -- read-write for others).
- --
- -- After that we analyze the body of the function, and finaly, we check
- -- that each borrowed parameter and global has read-write permission. We
- -- then clean up the environment and put back the saved environment.
+ -- appropriate permissions (unrestricted for borrowed and moved, observed
+ -- for observed names).
procedure Check_Declaration (Decl : Node_Id);
procedure Check_Expression (Expr : Node_Id);
- procedure Check_Globals (N : Node_Id; Check_Mode : Checking_Mode);
- -- This procedure takes a global pragma and checks depending on mode:
- -- Mode Read: every in global is readable
- -- Mode Observe: same as Check_Param_Observes but on globals
- -- Mode Borrow_Out: Check_Param_Outs for globals
- -- Mode Move: Check_Param for globals with mode Read
- -- Mode Assign: Check_Param for globals with mode Assign
+ procedure Check_Globals (N : Node_Id);
+ -- This procedure takes a global pragma and checks it
procedure Check_List (L : List_Id);
-- Calls Check_Node on each element of the list
@@ -638,25 +584,15 @@ package body Sem_SPARK is
procedure Check_Package_Body (Pack : Node_Id);
- procedure Check_Param (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and calls the
- -- analyze node if the parameter is borrowed with mode in out, with the
- -- appropriate Checking_Mode (Move).
-
- procedure Check_Param_Observes (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and calls
- -- the analyze node if the parameter is observed, with the appropriate
- -- Checking_Mode.
-
- procedure Check_Param_Outs (Formal : Entity_Id; Actual : Node_Id);
- -- This procedure takes a formal and an actual parameter and calls the
- -- analyze node if the parameter is of mode out, with the appropriate
- -- Checking_Mode.
+ procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id);
+ -- This procedure takes a formal and an actual parameter and checks the
+ -- permission of every in-mode parameter. This includes Observing and
+ -- Borrowing.
- procedure Check_Param_Read (Formal : Entity_Id; Actual : Node_Id);
+ procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id);
-- This procedure takes a formal and an actual parameter and checks the
- -- readability of every in-mode parameter. This includes observed in, and
- -- also borrowed in, that are then checked afterwards.
+ -- state of every out-mode and in out-mode parameter. This includes
+ -- Moving and Borrowing.
procedure Check_Statement (Stmt : Node_Id);
@@ -674,20 +610,6 @@ package body Sem_SPARK is
-- appropriate subtree for that Node_Id. If the tree is folded, then
-- it unrolls the tree up to the appropriate level.
- function Has_Alias
- (N : Node_Id)
- return Boolean;
- -- Function that returns whether the path given as parameter contains an
- -- extension that is declared as aliased.
-
- function Has_Array_Component (N : Node_Id) return Boolean;
- -- This function gets a Node_Id and looks recursively to find if the given
- -- path has any array component.
-
- function Has_Function_Component (N : Node_Id) return Boolean;
- -- This function gets a Node_Id and looks recursively to find if the given
- -- path has any function component.
-
procedure Hp (P : Perm_Env);
-- A procedure that outputs the hash table. This function is used only in
-- the debugger to look into a hash table.
@@ -698,28 +620,13 @@ package body Sem_SPARK is
-- A procedure that is called when deep globals or aliased globals are used
-- without any global aspect.
- function Is_Borrowed_In (E : Entity_Id) return Boolean;
- -- Function that tells if the given entity is a borrowed in a formal
- -- parameter, that is, if it is an access-to-variable type.
-
function Is_Deep (E : Entity_Id) return Boolean;
-- A function that can tell if a type is deep or not. Returns true if the
-- type passed as argument is deep.
- function Is_Shallow (E : Entity_Id) return Boolean;
- -- A function that can tell if a type is shallow or not. Returns true if
- -- the type passed as argument is shallow.
-
- function Loop_Of_Exit (N : Node_Id) return Entity_Id;
- -- A function that takes an exit statement node and returns the entity of
- -- the loop that this statement is exiting from.
-
- procedure Merge_Envs (Target : in out Perm_Env; Source : in out Perm_Env);
- -- Merge Target and Source into Target, and then deallocate the Source
-
procedure Perm_Error
- (N : Node_Id;
- Perm : Perm_Kind;
+ (N : Node_Id;
+ Perm : Perm_Kind;
Found_Perm : Perm_Kind);
-- A procedure that is called when the permissions found contradict the
-- rules established by the RM. This function is called with the node, its
@@ -742,7 +649,7 @@ package body Sem_SPARK is
procedure Return_Declarations (L : List_Id);
-- Check correct permissions on every declared object at the end of a
-- callee. Used at the end of the body of a callable entity. Checks that
- -- paths of all borrowed formal parameters and global have Read_Write
+ -- paths of all borrowed formal parameters and global have Unrestricted
-- permission.
procedure Return_Globals (Subp : Entity_Id);
@@ -750,65 +657,32 @@ package body Sem_SPARK is
-- of the subprogram indeed have RW permission at the end of the subprogram
-- execution.
- procedure Return_Parameter_Or_Global
- (Id : Entity_Id;
- Mode : Formal_Kind;
- Subp : Entity_Id;
- Global_Var : Boolean);
- -- Auxiliary procedure to Return_Parameters and Return_Globals
-
- procedure Return_Parameters (Subp : Entity_Id);
- -- Takes a subprogram as input, and checks that all borrowed parameters of
- -- the subprogram indeed have RW permission at the end of the subprogram
- -- execution.
+ procedure Return_The_Global
+ (Id : Entity_Id;
+ Mode : Formal_Kind;
+ Subp : Entity_Id);
+ -- Auxiliary procedure to Return_Globals
+ -- There is no need to return parameters because they will be reassigned
+ -- their state once the subprogram returns. Local variables that have
+ -- borrowed, observed, or moved an actual parameter go out of the scope.
procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind);
-- This procedure takes an access to a permission tree and modifies the
-- tree so that any strict extensions of the given tree become of the
-- access specified by parameter P.
- procedure Set_Perm_Extensions_Move (T : Perm_Tree_Access; E : Entity_Id);
- -- Set permissions to
- -- No for any extension with more .all
- -- W for any deep extension with same number of .all
- -- RW for any shallow extension with same number of .all
-
- function Set_Perm_Prefixes_Assign (N : Node_Id) return Perm_Tree_Access;
- -- This function takes a name as an input and sets in the permission
- -- tree the given permission to the given name. The general rule here is
- -- that everybody updates the permission of the subtree it is returning.
- -- The permission of the assigned path has been set to RW by the caller.
- --
- -- Case where we have to normalize a tree after the correct permissions
- -- have been assigned already. We look for the right subtree at the given
- -- path, actualize its permissions, and then call the normalization on its
- -- parent.
- --
- -- Example: We assign x.y and x.z then during Set_Perm_Prefixes_Move will
- -- change the permission of x to RW because all of its components have
- -- permission have permission RW.
-
- function Set_Perm_Prefixes_Borrow_Out (N : Node_Id) return Perm_Tree_Access;
+ function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access;
-- This function modifies the permissions of a given node_id in the
-- permission environment as well as in all the prefixes of the path,
-- given that the path is borrowed with mode out.
- function Set_Perm_Prefixes_Move
- (N : Node_Id; Mode : Checking_Mode)
+ function Set_Perm_Prefixes
+ (N : Node_Id;
+ New_Perm : Perm_Kind)
return Perm_Tree_Access;
- pragma Precondition (Mode = Move or Mode = Super_Move);
- -- Given a node and a mode (that can be either Move or Super_Move), this
- -- function modifies the permissions of a given node_id in the permission
- -- environment as well as all the prefixes of the path, given that the path
- -- is moved with or without 'Access. The general rule here is everybody
- -- updates the permission of the subtree they are returning.
- --
- -- This case describes a move either under 'Access or without 'Access.
-
- function Set_Perm_Prefixes_Observe (N : Node_Id) return Perm_Tree_Access;
- -- This function modifies the permissions of a given node_id in the
- -- permission environment as well as all the prefixes of the path,
- -- given that the path is observed.
+ -- This function sets the permissions of a given node_id in the
+ -- permission environment as well as in all the prefixes of the path
+ -- to the one given in parameter (P).
procedure Setup_Globals (Subp : Entity_Id);
-- Takes a subprogram as input, and sets up the environment by adding
@@ -824,6 +698,15 @@ package body Sem_SPARK is
-- Takes a subprogram as input, and sets up the environment by adding
-- formal parameters with appropriate permissions.
+ function Has_Ownership_Aspect_True
+ (N : Node_Id;
+ Msg : String)
+ return Boolean;
+ -- Takes a node as an input, and finds out whether it has ownership aspect
+ -- True or False. This function is recursive whenever the node has a
+ -- composite type. Access-to-objects have ownership aspect False if they
+ -- have a general access type.
+
----------------------
-- Global Variables --
----------------------
@@ -861,31 +744,6 @@ package body Sem_SPARK is
-- after declaration. Hence we can exclude from analysis variables that
-- are just declared and never accessed, typically at package declaration.
- ----------
- -- "<=" --
- ----------
-
- function "<=" (P1, P2 : Perm_Kind) return Boolean
- is
- begin
- return P2 >= P1;
- end "<=";
-
- ----------
- -- ">=" --
- ----------
-
- function ">=" (P1, P2 : Perm_Kind) return Boolean
- is
- begin
- case P2 is
- when No_Access => return True;
- when Read_Only => return P1 in Read_Perm;
- when Write_Only => return P1 in Write_Perm;
- when Read_Write => return P1 = Read_Write;
- end case;
- end ">=";
-
--------------------------
-- Check_Call_Statement --
--------------------------
@@ -893,64 +751,40 @@ package body Sem_SPARK is
procedure Check_Call_Statement (Call : Node_Id) is
Saved_Env : Perm_Env;
- procedure Iterate_Call is new
- Iterate_Call_Parameters (Check_Param);
- procedure Iterate_Call_Observes is new
- Iterate_Call_Parameters (Check_Param_Observes);
- procedure Iterate_Call_Outs is new
- Iterate_Call_Parameters (Check_Param_Outs);
- procedure Iterate_Call_Read is new
- Iterate_Call_Parameters (Check_Param_Read);
+ procedure Iterate_Call_In is new
+ Iterate_Call_Parameters (Check_Param_In);
+ procedure Iterate_Call_Out is new
+ Iterate_Call_Parameters (Check_Param_Out);
begin
-- Save environment, so that the modifications done by analyzing the
-- parameters are not kept at the end of the call.
- Copy_Env (Current_Perm_Env,
- Saved_Env);
-
- -- We first check the Read access on every in parameter
-
- Current_Checking_Mode := Read;
- Iterate_Call_Read (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global), Read);
-
- -- We first observe, then borrow with mode out, and then with other
- -- modes. This ensures that we do not have to check for by-copy types
- -- specially, because we read them before borrowing them.
- Iterate_Call_Observes (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global),
- Observe);
+ Copy_Env (Current_Perm_Env, Saved_Env);
- Iterate_Call_Outs (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global),
- Borrow_Out);
+ -- We first check the globals then parameters to handle the
+ -- No_Parameter_Aliasing Restriction. An out or in-out global is
+ -- considered as borrowing while a parameter with the same mode is
+ -- a move. This order disallow passing a part of a variable to a
+ -- subprogram if it is referenced as a global by the callable (when
+ -- writable).
+ -- For paremeters, we fisrt check in parameters and then the out ones.
+ -- This is to avoid Observing or Borrowing objects that are already
+ -- moved. This order is not mandatory but allows to catch runtime
+ -- errors like null pointer dereferencement at the analysis time.
- Iterate_Call (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global), Move);
+ Current_Checking_Mode := Read;
+ Check_Globals (Get_Pragma (Get_Called_Entity (Call), Pragma_Global));
+ Iterate_Call_In (Call);
+ Iterate_Call_Out (Call);
-- Restore environment, because after borrowing/observing actual
-- parameters, they get their permission reverted to the ones before
-- the call.
Free_Env (Current_Perm_Env);
-
- Copy_Env (Saved_Env,
- Current_Perm_Env);
-
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (Saved_Env);
-
- -- We assign the out parameters (necessarily borrowed per RM)
- Current_Checking_Mode := Assign;
- Iterate_Call (Call);
- Check_Globals (Get_Pragma
- (Get_Called_Entity (Call), Pragma_Global),
- Assign);
-
end Check_Call_Statement;
-------------------------
@@ -959,15 +793,12 @@ package body Sem_SPARK is
procedure Check_Callable_Body (Body_N : Node_Id) is
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
-
- Saved_Env : Perm_Env;
+ Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ Saved_Env : Perm_Env;
Saved_Init_Map : Initialization_Map;
-
- New_Env : Perm_Env;
-
- Body_Id : constant Entity_Id := Defining_Entity (Body_N);
- Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
+ New_Env : Perm_Env;
+ Body_Id : constant Entity_Id := Defining_Entity (Body_N);
+ Spec_Id : constant Entity_Id := Unique_Entity (Body_Id);
begin
-- Check if SPARK pragma is not set to Off
@@ -989,9 +820,8 @@ package body Sem_SPARK is
-- Save initialization map
Copy_Init_Map (Current_Initialization_Map, Saved_Init_Map);
-
Current_Checking_Mode := Read;
- Current_Perm_Env := New_Env;
+ Current_Perm_Env := New_Env;
-- Add formals and globals to the environment with adequate permissions
@@ -1010,23 +840,18 @@ package body Sem_SPARK is
if Ekind_In (Spec_Id, E_Procedure, E_Entry)
and then not No_Return (Spec_Id)
then
- Return_Parameters (Spec_Id);
Return_Globals (Spec_Id);
end if;
-- Free the environments
Free_Env (Current_Perm_Env);
-
- Copy_Env (Saved_Env,
- Current_Perm_Env);
-
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (Saved_Env);
-- Restore initialization map
Copy_Init_Map (Saved_Init_Map, Current_Initialization_Map);
-
Reset (Saved_Init_Map);
-- The assignment of all out parameters will be done by caller
@@ -1039,51 +864,248 @@ package body Sem_SPARK is
-----------------------
procedure Check_Declaration (Decl : Node_Id) is
+
+ Target_Ent : constant Entity_Id := Defining_Identifier (Decl);
+ Target_Typ : Node_Id renames Etype (Target_Ent);
+ Check : Boolean := True;
begin
case N_Declaration'(Nkind (Decl)) is
when N_Full_Type_Declaration =>
+ if not Has_Ownership_Aspect_True (Target_Ent, "type declaration")
+ then
+ Check := False;
+ end if;
- -- Nothing to do here ??? NOT TRUE IF CONSTRAINT ON TYPE
-
- null;
+ -- ??? What about component declarations with defaults.
when N_Object_Declaration =>
+ if (Is_Access_Type (Target_Typ)
+ or else Is_Deep (Target_Typ))
+ and then not Has_Ownership_Aspect_True
+ (Target_Ent, "Object declaration ")
+ then
+ Check := False;
+ end if;
+
+ if Is_Anonymous_Access_Type (Target_Typ)
+ and then not Present (Expression (Decl))
+ then
+
+ -- ??? Check the case of default value (AI)
+ -- ??? How an anonymous access type can be with default exp?
+
+ Error_Msg_NE ("? object declaration & has OAF (Anonymous "
+ & "access-to-object with no initialization)",
+ Decl, Target_Ent);
+
+ -- If it it an initialization
+
+ elsif Present (Expression (Decl)) and Check then
+
+ -- Find out the operation to be done on the right-hand side
+
+ -- Initializing object, access type
+
+ if Is_Access_Type (Target_Typ) then
+
+ -- Initializing object, constant access type
- -- First move the right-hand side
+ if Is_Constant_Object (Target_Ent) then
- Current_Checking_Mode := Move;
- Check_Node (Expression (Decl));
+ -- Initializing object, constant access to variable type
+
+ if not Is_Access_Constant (Target_Typ) then
+ Current_Checking_Mode := Borrow;
+
+ -- Initializing object, constant access to constant type
+
+ -- Initializing object,
+ -- constant access to constant anonymous type.
+
+ elsif Is_Anonymous_Access_Type (Target_Typ) then
+
+ -- This is an object declaration so the target
+ -- of the assignement is a stand-alone object.
+
+ Current_Checking_Mode := Observe;
+
+ -- Initializing object, constant access to constant
+ -- named type.
+
+ else
+ -- If named then it is a general access type
+ -- Hence, Has_Ownership_Aspec_True is False.
+
+ raise Program_Error;
+ end if;
+
+ -- Initializing object, variable access type
+
+ else
+ -- Initializing object, variable access to variable type
+
+ if not Is_Access_Constant (Target_Typ) then
+
+ -- Initializing object, variable named access to
+ -- variable type.
+
+ if not Is_Anonymous_Access_Type (Target_Typ) then
+ Current_Checking_Mode := Move;
+
+ -- Initializing object, variable anonymous access to
+ -- variable type.
+
+ else
+ -- This is an object declaration so the target
+ -- object of the assignement is a stand-alone
+ -- object.
+
+ Current_Checking_Mode := Borrow;
+ end if;
+
+ -- Initializing object, variable access to constant type
+
+ else
+ -- Initializing object,
+ -- variable named access to constant type.
+
+ if not Is_Anonymous_Access_Type (Target_Typ) then
+ Error_Msg_N ("assignment not allowed, Ownership "
+ & "Aspect False (Anonymous Access "
+ & "Object)", Decl);
+ Check := False;
+
+ -- Initializing object,
+ -- variable anonymous access to constant type.
+
+ else
+ -- This is an object declaration so the target
+ -- of the assignement is a stand-alone object.
+
+ Current_Checking_Mode := Observe;
+ end if;
+ end if;
+ end if;
+
+ -- Initializing object, composite (deep) type
+
+ elsif Is_Deep (Target_Typ) then
+
+ -- Initializing object, constant composite type
+
+ if Is_Constant_Object (Target_Ent) then
+ Current_Checking_Mode := Observe;
+
+ -- Initializing object, variable composite type
+
+ else
+
+ -- Initializing object, variable anonymous composite type
+
+ if Nkind (Object_Definition (Decl)) =
+ N_Constrained_Array_Definition
+
+ -- An N_Constrained_Array_Definition is an anonymous
+ -- array (to be checked). Record types are always
+ -- named and are considered in the else part.
+
+ then
+ declare
+ Com_Ty : constant Node_Id :=
+ Component_Type (Etype (Target_Typ));
+ begin
+
+ if Is_Access_Type (Com_Ty) then
+
+ -- If components are of anonymous type
+
+ if Is_Anonymous_Access_Type (Com_Ty) then
+ if Is_Access_Constant (Com_Ty) then
+ Current_Checking_Mode := Observe;
+
+ else
+ Current_Checking_Mode := Borrow;
+ end if;
+
+ else
+ Current_Checking_Mode := Move;
+ end if;
+
+ elsif Is_Deep (Com_Ty) then
+
+ -- This is certainly named so it is a move
+
+ Current_Checking_Mode := Move;
+ end if;
+ end;
+
+ else
+ Current_Checking_Mode := Move;
+ end if;
+ end if;
+
+ elsif Nkind_In (Expression (Decl),
+ N_Attribute_Reference,
+ N_Attribute_Reference,
+ N_Expanded_Name,
+ N_Explicit_Dereference,
+ N_Indexed_Component,
+ N_Reference,
+ N_Selected_Component,
+ N_Slice)
+ then
+ if Is_Access_Type (Etype (Prefix (Expression (Decl))))
+ or else Is_Deep (Etype (Prefix (Expression (Decl))))
+ then
+ Current_Checking_Mode := Observe;
+ Check := True;
+ end if;
+ end if;
+ end if;
+
+ if Check then
+ Check_Node (Expression (Decl));
+ end if;
+
+ -- If lhs is not a pointer, we still give it the appropriate
+ -- state which is useless but not harmful.
declare
- Deep : constant Boolean :=
- Is_Deep (Etype (Defining_Identifier (Decl)));
Elem : Perm_Tree_Access;
+ Deep : constant Boolean := Is_Deep (Target_Typ);
begin
- Elem := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Deep,
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- -- If unitialized declaration, then set to Write_Only. If a
- -- pointer declaration, it has a null default initialization.
-
- if No (Expression (Decl))
- and then not Has_Full_Default_Initialization
- (Etype (Defining_Identifier (Decl)))
- and then not Is_Access_Type
- (Etype (Defining_Identifier (Decl)))
-
- -- Objects of shallow types are considered as always
- -- initialized, leaving the checking of initialization to
- -- flow analysis.
-
- and then Deep
- then
- Elem.all.Tree.Permission := Write_Only;
- Elem.all.Tree.Children_Permission := Write_Only;
+ -- Note that all declared variables are set to the unrestricted
+ -- state.
+ --
+ -- If variables are not initialized:
+ -- unrestricted to every declared object.
+ -- Exp:
+ -- R : Rec
+ -- S : Rec := (...)
+ -- R := S
+ -- The assignement R := S is not allowed in the new rules
+ -- if R is not unrestricted.
+ --
+ -- If variables are initialized:
+ -- If it is a move, then the target is unrestricted
+ -- If it is a borrow, then the target is unrestricted
+ -- If it is an observe, then the target should be observed
+
+ if Current_Checking_Mode = Observe then
+ Elem := new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Deep,
+ Permission => Observed,
+ Children_Permission => Observed));
+ else
+ Elem := new Perm_Tree_Wrapper'
+ (Tree =>
+ (Kind => Entire_Object,
+ Is_Node_Deep => Deep,
+ Permission => Unrestricted,
+ Children_Permission => Unrestricted));
end if;
-- Create new tree for defining identifier
@@ -1091,7 +1113,6 @@ package body Sem_SPARK is
Set (Current_Perm_Env,
Unique_Entity (Defining_Identifier (Decl)),
Elem);
-
pragma Assert (Get_First (Current_Perm_Env) /= null);
end;
@@ -1099,19 +1120,17 @@ package body Sem_SPARK is
Check_Node (Subtype_Indication (Decl));
when N_Iterator_Specification =>
- pragma Assert (Is_Shallow (Etype (Defining_Identifier (Decl))));
null;
when N_Loop_Parameter_Specification =>
- pragma Assert (Is_Shallow (Etype (Defining_Identifier (Decl))));
null;
-- Checking should not be called directly on these nodes
- when N_Component_Declaration
- | N_Function_Specification
+ when N_Function_Specification
| N_Entry_Declaration
| N_Procedure_Specification
+ | N_Component_Declaration
=>
raise Program_Error;
@@ -1141,29 +1160,33 @@ package body Sem_SPARK is
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
case N_Subexpr'(Nkind (Expr)) is
- when N_Procedure_Call_Statement =>
+ when N_Procedure_Call_Statement
+ | N_Function_Call
+ =>
Check_Call_Statement (Expr);
when N_Identifier
| N_Expanded_Name
=>
-- Check if identifier is pointing to nothing (On/Off/...)
+
if not Present (Entity (Expr)) then
return;
end if;
-- Do not analyze things that are not of object Kind
+
if Ekind (Entity (Expr)) not in Object_Kind then
return;
end if;
-- Consider as ident
+
Process_Path (Expr);
-- Switch to read mode and then check the readability of each operand
when N_Binary_Op =>
-
Current_Checking_Mode := Read;
Check_Node (Left_Opnd (Expr));
Check_Node (Right_Opnd (Expr));
@@ -1175,7 +1198,6 @@ package body Sem_SPARK is
| N_Op_Not
| N_Op_Plus
=>
- pragma Assert (Is_Shallow (Etype (Expr)));
Current_Checking_Mode := Read;
Check_Node (Right_Opnd (Expr));
@@ -1184,32 +1206,7 @@ package body Sem_SPARK is
when N_Attribute_Reference =>
case Attribute_Name (Expr) is
when Name_Access =>
- case Current_Checking_Mode is
- when Read =>
- Check_Node (Prefix (Expr));
-
- when Move =>
- Current_Checking_Mode := Super_Move;
- Check_Node (Prefix (Expr));
-
- -- Only assign names, not expressions
-
- when Assign =>
- raise Program_Error;
-
- -- Prefix in Super_Move should be a name, error here
-
- when Super_Move =>
- raise Program_Error;
-
- -- Could only borrow names of mode out, not n'Access
-
- when Borrow_Out =>
- raise Program_Error;
-
- when Observe =>
- Check_Node (Prefix (Expr));
- end case;
+ Error_Msg_N ("access attribute not allowed in SPARK", Expr);
when Name_Last
| Name_First
@@ -1239,7 +1236,7 @@ package body Sem_SPARK is
Check_Node (Prefix (Expr));
when Name_Pred
- | Name_Succ
+ | Name_Succ
=>
Check_List (Expressions (Expr));
Check_Node (Prefix (Expr));
@@ -1254,12 +1251,12 @@ package body Sem_SPARK is
-- analysis.
when Name_Address
- | Name_Alignment
- | Name_Component_Size
- | Name_First_Bit
- | Name_Last_Bit
- | Name_Size
- | Name_Position
+ | Name_Alignment
+ | Name_Component_Size
+ | Name_First_Bit
+ | Name_Last_Bit
+ | Name_Size
+ | Name_Position
=>
null;
@@ -1270,7 +1267,6 @@ package body Sem_SPARK is
| Name_Val
=>
null;
-
-- Other attributes that fall out of the scope of the analysis
when others =>
@@ -1292,17 +1288,12 @@ package body Sem_SPARK is
when N_And_Then
| N_Or_Else
=>
- pragma Assert (Is_Shallow (Etype (Expr)));
Current_Checking_Mode := Read;
Check_Node (Left_Opnd (Expr));
Check_Node (Right_Opnd (Expr));
-- Check the arguments of the call
- when N_Function_Call =>
- Current_Checking_Mode := Read;
- Check_List (Parameter_Associations (Expr));
-
when N_Explicit_Dereference =>
Process_Path (Expr);
@@ -1315,20 +1306,16 @@ package body Sem_SPARK is
-- Accumulator for the different branches
New_Env : Perm_Env;
-
- Elmt : Node_Id := First (Expressions (Expr));
+ Elmt : Node_Id := First (Expressions (Expr));
begin
Current_Checking_Mode := Read;
-
Check_Node (Elmt);
-
Current_Checking_Mode := Mode_Before;
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy, and new aliased.
@@ -1341,15 +1328,10 @@ package body Sem_SPARK is
-- Here the new_environment contains curr env after then block
-- ELSE part
-
-- Restore environment before if
- Copy_Env (Current_Perm_Env,
- New_Env);
-
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
-- Here new environment contains the environment after then and
-- current the fresh copy of old one.
@@ -1357,14 +1339,9 @@ package body Sem_SPARK is
Next (Elmt);
Check_Node (Elmt);
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
-- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
-
+ Copy_Env (New_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
end;
@@ -1380,6 +1357,7 @@ package body Sem_SPARK is
when N_Quantified_Expression =>
declare
Saved_Env : Perm_Env;
+
begin
Copy_Env (Current_Perm_Env, Saved_Env);
Current_Checking_Mode := Read;
@@ -1391,7 +1369,6 @@ package body Sem_SPARK is
Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (Saved_Env);
end;
-
-- Analyze the list of associations in the aggregate
when N_Aggregate =>
@@ -1408,19 +1385,16 @@ package body Sem_SPARK is
-- Accumulator for the different branches
New_Env : Perm_Env;
-
Elmt : Node_Id := First (Alternatives (Expr));
begin
Current_Checking_Mode := Read;
Check_Node (Expression (Expr));
-
Current_Checking_Mode := Mode_Before;
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy, and new aliased.
@@ -1429,43 +1403,29 @@ package body Sem_SPARK is
Check_Node (Elmt);
Next (Elmt);
-
- Copy_Env (Current_Perm_Env,
- New_Env);
-
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-- Other alternatives
while Present (Elmt) loop
- -- Restore environment
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ -- Restore environment
+ Copy_Env (Saved_Env, Current_Perm_Env);
Check_Node (Elmt);
-
- -- Merge Current_Perm_Env into New_Env
-
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
Next (Elmt);
end loop;
-
-- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
end;
-
-- Analyze the list of associates in the aggregate as well as the
-- ancestor part.
when N_Extension_Aggregate =>
-
Check_Node (Ancestor_Part (Expr));
Check_List (Expressions (Expr));
@@ -1507,7 +1467,6 @@ package body Sem_SPARK is
| N_Raise_xxx_Error
=>
null;
-
-- The following nodes are never generated in GNATprove mode
when N_Expression_With_Actions
@@ -1515,7 +1474,6 @@ package body Sem_SPARK is
| N_Unchecked_Expression
=>
raise Program_Error;
-
end case;
end Check_Expression;
@@ -1523,150 +1481,63 @@ package body Sem_SPARK is
-- Check_Globals --
-------------------
- procedure Check_Globals (N : Node_Id; Check_Mode : Checking_Mode) is
+ procedure Check_Globals (N : Node_Id) is
begin
if Nkind (N) = N_Empty then
return;
end if;
declare
- pragma Assert
- (List_Length (Pragma_Argument_Associations (N)) = 1);
-
- PAA : constant Node_Id :=
- First (Pragma_Argument_Associations (N));
+ pragma Assert (List_Length (Pragma_Argument_Associations (N)) = 1);
+ PAA : constant Node_Id := First (Pragma_Argument_Associations (N));
pragma Assert (Nkind (PAA) = N_Pragma_Argument_Association);
-
Row : Node_Id;
The_Mode : Name_Id;
RHS : Node_Id;
- procedure Process (Mode : Name_Id;
- The_Global : Entity_Id);
-
- procedure Process (Mode : Name_Id;
- The_Global : Node_Id)
- is
- Ident_Elt : constant Entity_Id :=
+ procedure Process (Mode : Name_Id; The_Global : Entity_Id);
+ procedure Process (Mode : Name_Id; The_Global : Node_Id) is
+ Ident_Elt : constant Entity_Id :=
Unique_Entity (Entity (The_Global));
-
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
if Ekind (Ident_Elt) = E_Abstract_State then
return;
end if;
-
- case Check_Mode is
- when Read =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- Check_Node (The_Global);
-
- when Name_Output
- | Name_In_Out
- =>
- null;
-
- when others =>
- raise Program_Error;
-
- end case;
-
- when Observe =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- if not Is_Borrowed_In (Ident_Elt) then
- -- Observed in
-
- Current_Checking_Mode := Observe;
- Check_Node (The_Global);
- end if;
-
- when others =>
- null;
-
- end case;
-
- when Borrow_Out =>
-
- case Mode is
- when Name_Output =>
- -- Borrowed out
- Current_Checking_Mode := Borrow_Out;
- Check_Node (The_Global);
-
- when others =>
- null;
-
- end case;
-
- when Move =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- if Is_Borrowed_In (Ident_Elt) then
- -- Borrowed in
-
- Current_Checking_Mode := Move;
- else
- -- Observed
-
- return;
- end if;
-
- when Name_Output =>
- return;
-
- when Name_In_Out =>
- -- Borrowed in out
-
- Current_Checking_Mode := Move;
-
- when others =>
- raise Program_Error;
- end case;
-
+ case Mode is
+ when Name_Input
+ | Name_Proof_In
+ =>
+ Current_Checking_Mode := Observe;
Check_Node (The_Global);
- when Assign =>
- case Mode is
- when Name_Input
- | Name_Proof_In
- =>
- null;
-
- when Name_Output
- | Name_In_Out
- =>
- -- Borrowed out or in out
-
- Process_Path (The_Global);
- when others =>
- raise Program_Error;
- end case;
+ when Name_Output
+ | Name_In_Out
+ =>
+ -- ??? Borrow not Move?
+ Current_Checking_Mode := Borrow;
+ Check_Node (The_Global);
when others =>
raise Program_Error;
end case;
-
Current_Checking_Mode := Mode_Before;
end Process;
begin
if Nkind (Expression (PAA)) = N_Null then
+
-- global => null
-- No globals, nothing to do
+
return;
elsif Nkind_In (Expression (PAA), N_Identifier, N_Expanded_Name) then
+
-- global => foo
-- A single input
+
Process (Name_Input, Expression (PAA));
elsif Nkind (Expression (PAA)) = N_Aggregate
@@ -1674,6 +1545,7 @@ package body Sem_SPARK is
then
-- global => (foo, bar)
-- Inputs
+
RHS := First (Expressions (Expression (PAA)));
while Present (RHS) loop
case Nkind (RHS) is
@@ -1687,7 +1559,6 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
-
end case;
RHS := Next (RHS);
end loop;
@@ -1707,8 +1578,8 @@ package body Sem_SPARK is
while Present (Row) loop
pragma Assert (List_Length (Choices (Row)) = 1);
The_Mode := Chars (First (Choices (Row)));
-
RHS := Expression (Row);
+
case Nkind (RHS) is
when N_Aggregate =>
RHS := First (Expressions (RHS));
@@ -1719,7 +1590,6 @@ package body Sem_SPARK is
when others =>
Process (The_Mode, RHS);
-
end case;
RHS := Next (RHS);
end loop;
@@ -1737,9 +1607,7 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
-
end case;
-
Row := Next (Row);
end loop;
end;
@@ -1770,339 +1638,6 @@ package body Sem_SPARK is
procedure Check_Loop_Statement (Loop_N : Node_Id) is
- -- Local Subprograms
-
- procedure Check_Is_Less_Restrictive_Env
- (Exiting_Env : Perm_Env;
- Entry_Env : Perm_Env);
- -- This procedure checks that the Exiting_Env environment is less
- -- restrictive than the Entry_Env environment.
-
- procedure Check_Is_Less_Restrictive_Tree
- (New_Tree : Perm_Tree_Access;
- Orig_Tree : Perm_Tree_Access;
- E : Entity_Id);
- -- Auxiliary procedure to check that the tree New_Tree is less
- -- restrictive than the tree Orig_Tree for the entity E.
-
- procedure Perm_Error_Loop_Exit
- (E : Entity_Id;
- Loop_Id : Node_Id;
- Perm : Perm_Kind;
- Found_Perm : Perm_Kind);
- -- A procedure that is called when the permissions found contradict
- -- the rules established by the RM at the exit of loops. This function
- -- is called with the entity, the node of the enclosing loop, the
- -- permission that was expected and the permission found, and issues
- -- an appropriate error message.
-
- -----------------------------------
- -- Check_Is_Less_Restrictive_Env --
- -----------------------------------
-
- procedure Check_Is_Less_Restrictive_Env
- (Exiting_Env : Perm_Env;
- Entry_Env : Perm_Env)
- is
- Comp_Entry : Perm_Tree_Maps.Key_Option;
- Iter_Entry, Iter_Exit : Perm_Tree_Access;
-
- begin
- Comp_Entry := Get_First_Key (Entry_Env);
- while Comp_Entry.Present loop
- Iter_Entry := Get (Entry_Env, Comp_Entry.K);
- pragma Assert (Iter_Entry /= null);
- Iter_Exit := Get (Exiting_Env, Comp_Entry.K);
- pragma Assert (Iter_Exit /= null);
- Check_Is_Less_Restrictive_Tree
- (New_Tree => Iter_Exit,
- Orig_Tree => Iter_Entry,
- E => Comp_Entry.K);
- Comp_Entry := Get_Next_Key (Entry_Env);
- end loop;
- end Check_Is_Less_Restrictive_Env;
-
- ------------------------------------
- -- Check_Is_Less_Restrictive_Tree --
- ------------------------------------
-
- procedure Check_Is_Less_Restrictive_Tree
- (New_Tree : Perm_Tree_Access;
- Orig_Tree : Perm_Tree_Access;
- E : Entity_Id)
- is
- -----------------------
- -- Local Subprograms --
- -----------------------
-
- procedure Check_Is_Less_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id);
- -- Auxiliary procedure to check that the tree N is less restrictive
- -- than the given permission P.
-
- procedure Check_Is_More_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id);
- -- Auxiliary procedure to check that the tree N is more restrictive
- -- than the given permission P.
-
- -----------------------------------------
- -- Check_Is_Less_Restrictive_Tree_Than --
- -----------------------------------------
-
- procedure Check_Is_Less_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id)
- is
- begin
- if not (Permission (Tree) >= Perm) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Permission (Tree), Perm);
- end if;
-
- case Kind (Tree) is
- when Entire_Object =>
- if not (Children_Permission (Tree) >= Perm) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Children_Permission (Tree), Perm);
-
- end if;
-
- when Reference =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_All (Tree), Perm, E);
-
- when Array_Component =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_Elem (Tree), Perm, E);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First (Component (Tree));
- while Comp /= null loop
- Check_Is_Less_Restrictive_Tree_Than (Comp, Perm, E);
- Comp :=
- Perm_Tree_Maps.Get_Next (Component (Tree));
- end loop;
-
- Check_Is_Less_Restrictive_Tree_Than
- (Other_Components (Tree), Perm, E);
- end;
- end case;
- end Check_Is_Less_Restrictive_Tree_Than;
-
- -----------------------------------------
- -- Check_Is_More_Restrictive_Tree_Than --
- -----------------------------------------
-
- procedure Check_Is_More_Restrictive_Tree_Than
- (Tree : Perm_Tree_Access;
- Perm : Perm_Kind;
- E : Entity_Id)
- is
- begin
- if not (Perm >= Permission (Tree)) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Permission (Tree), Perm);
- end if;
-
- case Kind (Tree) is
- when Entire_Object =>
- if not (Perm >= Children_Permission (Tree)) then
- Perm_Error_Loop_Exit
- (E, Loop_N, Children_Permission (Tree), Perm);
- end if;
-
- when Reference =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_All (Tree), Perm, E);
-
- when Array_Component =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_Elem (Tree), Perm, E);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First (Component (Tree));
- while Comp /= null loop
- Check_Is_More_Restrictive_Tree_Than (Comp, Perm, E);
- Comp :=
- Perm_Tree_Maps.Get_Next (Component (Tree));
- end loop;
-
- Check_Is_More_Restrictive_Tree_Than
- (Other_Components (Tree), Perm, E);
- end;
- end case;
- end Check_Is_More_Restrictive_Tree_Than;
-
- -- Start of processing for Check_Is_Less_Restrictive_Tree
-
- begin
- if not (Permission (New_Tree) <= Permission (Orig_Tree)) then
- Perm_Error_Loop_Exit
- (E => E,
- Loop_Id => Loop_N,
- Perm => Permission (New_Tree),
- Found_Perm => Permission (Orig_Tree));
- end if;
-
- case Kind (New_Tree) is
-
- -- Potentially folded tree. We check the other tree Orig_Tree to
- -- check whether it is folded or not. If folded we just compare
- -- their Permission and Children_Permission, if not, then we
- -- look at the Children_Permission of the folded tree against
- -- the unfolded tree Orig_Tree.
-
- when Entire_Object =>
- case Kind (Orig_Tree) is
- when Entire_Object =>
- if not (Children_Permission (New_Tree) <=
- Children_Permission (Orig_Tree))
- then
- Perm_Error_Loop_Exit
- (E, Loop_N,
- Children_Permission (New_Tree),
- Children_Permission (Orig_Tree));
- end if;
-
- when Reference =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_All (Orig_Tree), Children_Permission (New_Tree), E);
-
- when Array_Component =>
- Check_Is_More_Restrictive_Tree_Than
- (Get_Elem (Orig_Tree), Children_Permission (New_Tree), E);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First
- (Component (Orig_Tree));
- while Comp /= null loop
- Check_Is_More_Restrictive_Tree_Than
- (Comp, Children_Permission (New_Tree), E);
- Comp := Perm_Tree_Maps.Get_Next
- (Component (Orig_Tree));
- end loop;
-
- Check_Is_More_Restrictive_Tree_Than
- (Other_Components (Orig_Tree),
- Children_Permission (New_Tree), E);
- end;
- end case;
-
- when Reference =>
- case Kind (Orig_Tree) is
- when Entire_Object =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_All (New_Tree), Children_Permission (Orig_Tree), E);
-
- when Reference =>
- Check_Is_Less_Restrictive_Tree
- (Get_All (New_Tree), Get_All (Orig_Tree), E);
-
- when others =>
- raise Program_Error;
- end case;
-
- when Array_Component =>
- case Kind (Orig_Tree) is
- when Entire_Object =>
- Check_Is_Less_Restrictive_Tree_Than
- (Get_Elem (New_Tree), Children_Permission (Orig_Tree), E);
-
- when Array_Component =>
- Check_Is_Less_Restrictive_Tree
- (Get_Elem (New_Tree), Get_Elem (Orig_Tree), E);
-
- when others =>
- raise Program_Error;
- end case;
-
- when Record_Component =>
- declare
- CompN : Perm_Tree_Access;
- begin
- CompN :=
- Perm_Tree_Maps.Get_First (Component (New_Tree));
- case Kind (Orig_Tree) is
- when Entire_Object =>
- while CompN /= null loop
- Check_Is_Less_Restrictive_Tree_Than
- (CompN, Children_Permission (Orig_Tree), E);
-
- CompN :=
- Perm_Tree_Maps.Get_Next (Component (New_Tree));
- end loop;
-
- Check_Is_Less_Restrictive_Tree_Than
- (Other_Components (New_Tree),
- Children_Permission (Orig_Tree),
- E);
-
- when Record_Component =>
- declare
-
- KeyO : Perm_Tree_Maps.Key_Option;
- CompO : Perm_Tree_Access;
- begin
- KeyO := Perm_Tree_Maps.Get_First_Key
- (Component (Orig_Tree));
- while KeyO.Present loop
- pragma Assert (CompO /= null);
-
- Check_Is_Less_Restrictive_Tree (CompN, CompO, E);
-
- KeyO := Perm_Tree_Maps.Get_Next_Key
- (Component (Orig_Tree));
- CompN := Perm_Tree_Maps.Get
- (Component (New_Tree), KeyO.K);
- CompO := Perm_Tree_Maps.Get
- (Component (Orig_Tree), KeyO.K);
- end loop;
-
- Check_Is_Less_Restrictive_Tree
- (Other_Components (New_Tree),
- Other_Components (Orig_Tree),
- E);
- end;
-
- when others =>
- raise Program_Error;
- end case;
- end;
- end case;
- end Check_Is_Less_Restrictive_Tree;
-
- --------------------------
- -- Perm_Error_Loop_Exit --
- --------------------------
-
- procedure Perm_Error_Loop_Exit
- (E : Entity_Id;
- Loop_Id : Node_Id;
- Perm : Perm_Kind;
- Found_Perm : Perm_Kind)
- is
- begin
- Error_Msg_Node_2 := Loop_Id;
- Error_Msg_N ("insufficient permission for & when exiting loop &", E);
- Perm_Mismatch (Exp_Perm => Perm,
- Act_Perm => Found_Perm,
- N => Loop_Id);
- end Perm_Error_Loop_Exit;
-
-- Local variables
Loop_Name : constant Entity_Id := Entity (Identifier (Loop_N));
@@ -2126,6 +1661,7 @@ package body Sem_SPARK is
if Present (Iteration_Scheme (Loop_N)) then
declare
Exit_Env : constant Perm_Env_Access := new Perm_Env;
+
begin
Copy_Env (From => Current_Perm_Env, To => Exit_Env.all);
Set (Current_Loops_Accumulators, Loop_Name, Exit_Env);
@@ -2137,12 +1673,6 @@ package body Sem_SPARK is
Check_Node (Iteration_Scheme (Loop_N));
Check_List (Statements (Loop_N));
- -- Check that environment gets less restrictive at end of loop
-
- Check_Is_Less_Restrictive_Env
- (Exiting_Env => Current_Perm_Env,
- Entry_Env => Loop_Env.all);
-
-- Set environment to the one for exiting the loop
declare
@@ -2208,6 +1738,7 @@ package body Sem_SPARK is
when N_Package_Declaration =>
declare
Spec : constant Node_Id := Specification (N);
+
begin
Current_Checking_Mode := Read;
Check_List (Visible_Declarations (Spec));
@@ -2274,7 +1805,6 @@ package body Sem_SPARK is
| N_Delay_Alternative
| N_Derived_Type_Definition
| N_Designator
- | N_Discriminant_Association
| N_Discriminant_Specification
| N_Elsif_Part
| N_Entry_Body_Formal_Part
@@ -2366,9 +1896,12 @@ package body Sem_SPARK is
| N_Use_Type_Clause
| N_Validate_Unchecked_Conversion
| N_Variable_Reference_Marker
+ | N_Discriminant_Association
+
+ -- ??? check whether we should do sth special for
+ -- N_Discriminant_Association, or maybe raise a program error.
=>
null;
-
-- The following nodes are rewritten by semantic analysis
when N_Single_Protected_Declaration
@@ -2408,15 +1941,12 @@ package body Sem_SPARK is
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
-
+ Copy_Env (Current_Perm_Env, Saved_Env);
Check_List (Private_Declarations (CorSp));
-- Set mode to Read, and then analyze declarations and statements
Current_Checking_Mode := Read;
-
Check_List (Declarations (Pack));
Check_Node (Handled_Statement_Sequence (Pack));
@@ -2430,137 +1960,129 @@ package body Sem_SPARK is
-- declaration) from environment.
Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
end Check_Package_Body;
- -----------------
- -- Check_Param --
- -----------------
+ --------------------
+ -- Check_Param_In --
+ --------------------
- procedure Check_Param (Formal : Entity_Id; Actual : Node_Id) is
+ procedure Check_Param_In (Formal : Entity_Id; Actual : Node_Id) is
Mode : constant Entity_Kind := Ekind (Formal);
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
-
begin
- case Current_Checking_Mode is
- when Read =>
- case Formal_Kind'(Mode) is
- when E_In_Parameter =>
- if Is_Borrowed_In (Formal) then
- -- Borrowed in
-
- Current_Checking_Mode := Move;
- else
- -- Observed
+ case Formal_Kind'(Mode) is
- return;
- end if;
+ -- Formal IN parameter
- when E_Out_Parameter =>
- return;
+ when E_In_Parameter =>
- when E_In_Out_Parameter =>
- -- Borrowed in out
+ -- Formal IN parameter, access type
- Current_Checking_Mode := Move;
+ if Is_Access_Type (Etype (Formal)) then
- end case;
+ -- Formal IN parameter, access to variable type
- Check_Node (Actual);
+ if not Is_Access_Constant (Etype (Formal)) then
- when Assign =>
- case Formal_Kind'(Mode) is
- when E_In_Parameter =>
- null;
+ -- Formal IN parameter, named/anonymous access to variable
+ -- type.
- when E_Out_Parameter
- | E_In_Out_Parameter
- =>
- -- Borrowed out or in out
+ Current_Checking_Mode := Borrow;
+ Check_Node (Actual);
- Process_Path (Actual);
+ -- Formal IN parameter, access to constant type
+ -- Formal IN parameter, access to named constant type
- end case;
+ elsif not Is_Anonymous_Access_Type (Etype (Formal)) then
+ Error_Msg_N ("assignment not allowed, Ownership Aspect"
+ & " False (Named general access type)",
+ Formal);
- when others =>
- raise Program_Error;
+ -- Formal IN parameter, access to anonymous constant type
- end case;
- Current_Checking_Mode := Mode_Before;
- end Check_Param;
+ else
+ Current_Checking_Mode := Observe;
+ Check_Node (Actual);
+ end if;
- --------------------------
- -- Check_Param_Observes --
- --------------------------
+ -- Formal IN parameter, composite type
- procedure Check_Param_Observes (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
- Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ elsif Is_Deep (Etype (Formal)) then
- begin
- case Mode is
- when E_In_Parameter =>
- if not Is_Borrowed_In (Formal) then
- -- Observed in
+ -- Composite formal types should be named
+ -- Formal IN parameter, composite named type
Current_Checking_Mode := Observe;
Check_Node (Actual);
end if;
- when others =>
+ when E_Out_Parameter
+ | E_In_Out_Parameter
+ =>
null;
-
end case;
Current_Checking_Mode := Mode_Before;
- end Check_Param_Observes;
+ end Check_Param_In;
----------------------
- -- Check_Param_Outs --
+ -- Check_Param_Out --
----------------------
- procedure Check_Param_Outs (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
+ procedure Check_Param_Out (Formal : Entity_Id; Actual : Node_Id) is
+ Mode : constant Entity_Kind := Ekind (Formal);
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
begin
+ case Formal_Kind'(Mode) is
- case Mode is
- when E_Out_Parameter =>
- -- Borrowed out
- Current_Checking_Mode := Borrow_Out;
- Check_Node (Actual);
+ -- Formal OUT/IN OUT parameter
- when others =>
- null;
+ when E_Out_Parameter
+ | E_In_Out_Parameter
+ =>
- end case;
+ -- Formal OUT/IN OUT parameter, access type
- Current_Checking_Mode := Mode_Before;
- end Check_Param_Outs;
+ if Is_Access_Type (Etype (Formal)) then
- ----------------------
- -- Check_Param_Read --
- ----------------------
+ -- Formal OUT/IN OUT parameter, access to variable type
- procedure Check_Param_Read (Formal : Entity_Id; Actual : Node_Id) is
- Mode : constant Entity_Kind := Ekind (Formal);
+ if not Is_Access_Constant (Etype (Formal)) then
- begin
- pragma Assert (Current_Checking_Mode = Read);
+ -- Cannot have anonymous out access parameter
+ -- Formal out/in out parameter, access to named variable
+ -- type.
- case Formal_Kind'(Mode) is
- when E_In_Parameter =>
- Check_Node (Actual);
+ Current_Checking_Mode := Move;
+ Check_Node (Actual);
- when E_Out_Parameter
- | E_In_Out_Parameter
- =>
- null;
+ -- Formal out/in out parameter, access to constant type
+
+ else
+ Error_Msg_N ("assignment not allowed, Ownership Aspect False"
+ & " (Named general access type)", Formal);
+
+ end if;
+ -- Formal out/in out parameter, composite type
+
+ elsif Is_Deep (Etype (Formal)) then
+
+ -- Composite formal types should be named
+ -- Formal out/in out Parameter, Composite Named type.
+
+ Current_Checking_Mode := Borrow;
+ Check_Node (Actual);
+ end if;
+
+ when E_In_Parameter =>
+ null;
end case;
- end Check_Param_Read;
+
+ Current_Checking_Mode := Mode_Before;
+ end Check_Param_Out;
-------------------------
-- Check_Safe_Pointers --
@@ -2605,13 +2127,13 @@ package body Sem_SPARK is
-- Local variables
Prag : Node_Id;
+
-- SPARK_Mode pragma in application
-- Start of processing for Check_Safe_Pointers
begin
Initialize;
-
case Nkind (N) is
when N_Compilation_Unit =>
Check_Safe_Pointers (Unit (N));
@@ -2647,6 +2169,42 @@ package body Sem_SPARK is
procedure Check_Statement (Stmt : Node_Id) is
Mode_Before : constant Checking_Mode := Current_Checking_Mode;
+ State_N : Perm_Kind;
+ Check : Boolean := True;
+ St_Name : Node_Id;
+ Ty_St_Name : Node_Id;
+
+ function Get_Root (Comp_Stmt : Node_Id) return Node_Id;
+ -- Return the root of the name given as input
+
+ function Get_Root (Comp_Stmt : Node_Id) return Node_Id is
+ begin
+ case Nkind (Comp_Stmt) is
+ when N_Identifier
+ | N_Expanded_Name
+ => return Comp_Stmt;
+
+ when N_Type_Conversion
+ | N_Unchecked_Type_Conversion
+ | N_Qualified_Expression
+ =>
+ return Get_Root (Expression (Comp_Stmt));
+
+ when N_Parameter_Specification =>
+ return Get_Root (Defining_Identifier (Comp_Stmt));
+
+ when N_Selected_Component
+ | N_Indexed_Component
+ | N_Slice
+ | N_Explicit_Dereference
+ =>
+ return Get_Root (Prefix (Comp_Stmt));
+
+ when others =>
+ raise Program_Error;
+ end case;
+ end Get_Root;
+
begin
case N_Statement_Other_Than_Procedure_Call'(Nkind (Stmt)) is
when N_Entry_Call_Statement =>
@@ -2655,25 +2213,189 @@ package body Sem_SPARK is
-- Move right-hand side first, and then assign left-hand side
when N_Assignment_Statement =>
- if Is_Deep (Etype (Expression (Stmt))) then
- Current_Checking_Mode := Move;
- else
- Current_Checking_Mode := Read;
- end if;
- Check_Node (Expression (Stmt));
- Current_Checking_Mode := Assign;
- Check_Node (Name (Stmt));
+ St_Name := Name (Stmt);
+ Ty_St_Name := Etype (Name (Stmt));
+
+ -- Check that is not a *general* access type
+
+ if Has_Ownership_Aspect_True (St_Name, "assigning to") then
+
+ -- Assigning to access type
+
+ if Is_Access_Type (Ty_St_Name) then
+
+ -- Assigning to access to variable type
+
+ if not Is_Access_Constant (Ty_St_Name) then
+
+ -- Assigning to named access to variable type
+
+ if not Is_Anonymous_Access_Type (Ty_St_Name) then
+ Current_Checking_Mode := Move;
+
+ -- Assigning to anonymous access to variable type
+
+ else
+ -- Target /= source root
+
+ if Nkind_In (Expression (Stmt), N_Allocator, N_Null)
+ or else St_Name /= Get_Root (Expression (Stmt))
+ then
+ Error_Msg_N ("assignment not allowed, anonymous "
+ & "access Object with Different Root",
+ Stmt);
+ Check := False;
+
+ -- Target = source root
+
+ else
+ -- Here we do nothing on the source nor on the
+ -- target. However, we check the the legality rule:
+ -- "The source shall be an owning access object
+ -- denoted by a name that is not in the observed
+ -- state".
+
+ State_N := Get_Perm (Expression (Stmt));
+ if State_N = Observed then
+ Error_Msg_N ("assignment not allowed, Anonymous "
+ & "access object with the same root"
+ & " but source Observed", Stmt);
+ Check := False;
+ end if;
+ end if;
+ end if;
+
+ -- else access-to-constant
+
+ -- Assigning to anonymous access-to-constant type
+
+ elsif Is_Anonymous_Access_Type (Ty_St_Name) then
+
+ -- ??? Check the follwing condition. We may have to
+ -- add that the root is in the observed state too.
+
+ State_N := Get_Perm (Expression (Stmt));
+ if State_N /= Observed then
+ Error_Msg_N ("assignment not allowed, anonymous "
+ & "access-to-constant object not in "
+ & "the observed state)", Stmt);
+ Check := False;
+
+ else
+ Error_Msg_N ("?here check accessibility level cited in"
+ & " the second legality rule of assign",
+ Stmt);
+ Check := False;
+ end if;
+
+ -- Assigning to named access-to-constant type:
+ -- This case should have been detected when checking
+ -- Has_Onwership_Aspect_True (Name (Stmt), "msg").
+
+ else
+ raise Program_Error;
+ end if;
+
+ -- Assigning to composite (deep) type.
+
+ elsif Is_Deep (Ty_St_Name) then
+ if Ekind (Ty_St_Name) = E_Record_Type then
+ declare
+ Elmt : Entity_Id :=
+ First_Component_Or_Discriminant (Ty_St_Name);
+
+ begin
+ while Present (Elmt) loop
+ if Is_Anonymous_Access_Type (Etype (Elmt)) or
+ Ekind (Elmt) = E_General_Access_Type
+ then
+ Error_Msg_N ("assignment not allowed, Ownership "
+ & "Aspect False (Components have "
+ & "Ownership Aspect False)", Stmt);
+ Check := False;
+ exit;
+ end if;
+
+ Next_Component_Or_Discriminant (Elmt);
+ end loop;
+ end;
+
+ -- Record types are always named so this is a move
+
+ if Check then
+ Current_Checking_Mode := Move;
+ end if;
+ end if;
+
+ -- Now handle legality rules of using a borrowed, observed,
+ -- or moved name as a prefix in an assignment.
+
+ else
+ if Nkind_In (St_Name,
+ N_Attribute_Reference,
+ N_Expanded_Name,
+ N_Explicit_Dereference,
+ N_Indexed_Component,
+ N_Reference,
+ N_Selected_Component,
+ N_Slice)
+ then
+
+ if Is_Access_Type (Etype (Prefix (St_Name))) or
+ Is_Deep (Etype (Prefix (St_Name)))
+ then
+
+ -- We set the Check variable to True so that we can
+ -- Check_Node of the expression and the name first
+ -- under the assumption of Current_Checking_Mode =
+ -- Read => nothing to be done for the RHS if the
+ -- following check on the expression fails, and
+ -- Current_Checking_Mode := Assign => the name should
+ -- not be borrowed or observed so that we can use it
+ -- as a prefix in the target of an assignement.
+ --
+ -- Note that we do not need to check the OA here
+ -- because we are allowed to read and write "through"
+ -- an object of OAF (example: traversing a DS).
+
+ Check := True;
+ end if;
+ end if;
+
+ if Nkind_In (Expression (Stmt),
+ N_Attribute_Reference,
+ N_Expanded_Name,
+ N_Explicit_Dereference,
+ N_Indexed_Component,
+ N_Reference,
+ N_Selected_Component,
+ N_Slice)
+ then
+
+ if Is_Access_Type (Etype (Prefix (Expression (Stmt))))
+ or else Is_Deep (Etype (Prefix (Expression (Stmt))))
+ then
+ Current_Checking_Mode := Observe;
+ Check := True;
+ end if;
+ end if;
+ end if;
+
+ if Check then
+ Check_Node (Expression (Stmt));
+ Current_Checking_Mode := Assign;
+ Check_Node (St_Name);
+ end if;
+ end if;
when N_Block_Statement =>
declare
Saved_Env : Perm_Env;
-
begin
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Analyze declarations and Handled_Statement_Sequences
@@ -2684,8 +2406,7 @@ package body Sem_SPARK is
-- Restore environment
Free_Env (Current_Perm_Env);
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
end;
when N_Case_Statement =>
@@ -2695,7 +2416,6 @@ package body Sem_SPARK is
-- Accumulator for the different branches
New_Env : Perm_Env;
-
Elmt : Node_Id := First (Alternatives (Stmt));
begin
@@ -2705,8 +2425,7 @@ package body Sem_SPARK is
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy, and new aliased.
@@ -2715,33 +2434,21 @@ package body Sem_SPARK is
Check_Node (Elmt);
Next (Elmt);
-
- Copy_Env (Current_Perm_Env,
- New_Env);
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-- Other alternatives
while Present (Elmt) loop
- -- Restore environment
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ -- Restore environment
+ Copy_Env (Saved_Env, Current_Perm_Env);
Check_Node (Elmt);
-
- -- Merge Current_Perm_Env into New_Env
-
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
Next (Elmt);
end loop;
- -- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
-
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
end;
@@ -2755,7 +2462,7 @@ package body Sem_SPARK is
when N_Loop_Statement =>
Check_Loop_Statement (Stmt);
- -- If deep type expression, then move, else read
+ -- If deep type expression, then move, else read
when N_Simple_Return_Statement =>
case Nkind (Expression (Stmt)) is
@@ -2767,65 +2474,42 @@ package body Sem_SPARK is
Subp : constant Entity_Id :=
Return_Applies_To (Return_Statement_Entity (Stmt));
begin
- Return_Parameters (Subp);
Return_Globals (Subp);
end;
when others =>
if Is_Deep (Etype (Expression (Stmt))) then
Current_Checking_Mode := Move;
- elsif Is_Shallow (Etype (Expression (Stmt))) then
- Current_Checking_Mode := Read;
else
- raise Program_Error;
+ Check := False;
end if;
- Check_Node (Expression (Stmt));
+ if Check then
+ Check_Node (Expression (Stmt));
+ end if;
end case;
when N_Extended_Return_Statement =>
Check_List (Return_Object_Declarations (Stmt));
Check_Node (Handled_Statement_Sequence (Stmt));
-
Return_Declarations (Return_Object_Declarations (Stmt));
-
declare
-- ??? This does not take into account the fact that a simple
-- return inside an extended return statement applies to the
-- extended return statement.
Subp : constant Entity_Id :=
Return_Applies_To (Return_Statement_Entity (Stmt));
+
begin
- Return_Parameters (Subp);
Return_Globals (Subp);
end;
- -- Merge the current_Perm_Env with the accumulator for the given loop
+ -- Nothing to do when exiting a loop. No merge needed
when N_Exit_Statement =>
- declare
- Loop_Name : constant Entity_Id := Loop_Of_Exit (Stmt);
-
- Saved_Accumulator : constant Perm_Env_Access :=
- Get (Current_Loops_Accumulators, Loop_Name);
-
- Environment_Copy : constant Perm_Env_Access :=
- new Perm_Env;
- begin
-
- Copy_Env (Current_Perm_Env,
- Environment_Copy.all);
-
- if Saved_Accumulator = null then
- Set (Current_Loops_Accumulators,
- Loop_Name, Environment_Copy);
- else
- Merge_Envs (Saved_Accumulator.all,
- Environment_Copy.all);
- end if;
- end;
+ null;
- -- Copy environment, run on each branch, and then merge
+ -- Copy environment, run on each branch
when N_If_Statement =>
declare
@@ -2836,13 +2520,11 @@ package body Sem_SPARK is
New_Env : Perm_Env;
begin
-
Check_Node (Condition (Stmt));
-- Save environment
- Copy_Env (Current_Perm_Env,
- Saved_Env);
+ Copy_Env (Current_Perm_Env, Saved_Env);
-- Here we have the original env in saved, current with a fresh
-- copy.
@@ -2850,34 +2532,25 @@ package body Sem_SPARK is
-- THEN PART
Check_List (Then_Statements (Stmt));
-
- Copy_Env (Current_Perm_Env,
- New_Env);
-
+ Copy_Env (Current_Perm_Env, New_Env);
Free_Env (Current_Perm_Env);
-- Here the new_environment contains curr env after then block
-- ELSIF part
+
declare
Elmt : Node_Id;
begin
Elmt := First (Elsif_Parts (Stmt));
while Present (Elmt) loop
- -- Transfer into accumulator, and restore from save
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ -- Transfer into accumulator, and restore from save
+ Copy_Env (Saved_Env, Current_Perm_Env);
Check_Node (Condition (Elmt));
Check_List (Then_Statements (Stmt));
-
- -- Merge Current_Perm_Env into New_Env
-
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
Next (Elmt);
end loop;
end;
@@ -2886,21 +2559,16 @@ package body Sem_SPARK is
-- Restore environment before if
- Copy_Env (Saved_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
-- Here new environment contains the environment after then and
-- current the fresh copy of old one.
Check_List (Else_Statements (Stmt));
- Merge_Envs (New_Env,
- Current_Perm_Env);
-
-- CLEANUP
- Copy_Env (New_Env,
- Current_Perm_Env);
+ Copy_Env (Saved_Env, Current_Perm_Env);
Free_Env (New_Env);
Free_Env (Saved_Env);
@@ -2956,8 +2624,7 @@ package body Sem_SPARK is
-- which means that the association permission is RW.
when Function_Call =>
- return Read_Write;
-
+ return Unrestricted;
end case;
end Get_Perm;
@@ -2980,7 +2647,6 @@ package body Sem_SPARK is
=>
declare
P : constant Entity_Id := Entity (N);
-
C : constant Perm_Tree_Access :=
Get (Current_Perm_Env, Unique_Entity (P));
@@ -2990,13 +2656,13 @@ package body Sem_SPARK is
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
-
if C = null then
-- No null possible here, there are no parents for the path.
-- This means we are using a global variable without adding
-- it in environment with a global aspect.
Illegal_Global_Usage (N);
+
else
return (R => Unfolded, Tree_Access => C);
end if;
@@ -3023,8 +2689,7 @@ package body Sem_SPARK is
when N_Selected_Component =>
declare
- C : constant Perm_Or_Tree :=
- Get_Perm_Or_Tree (Prefix (N));
+ C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
begin
case C.R is
@@ -3035,7 +2700,6 @@ package body Sem_SPARK is
when Unfolded =>
pragma Assert (C.Tree_Access /= null);
-
pragma Assert (Kind (C.Tree_Access) = Entire_Object
or else
Kind (C.Tree_Access) = Record_Component);
@@ -3044,30 +2708,32 @@ package body Sem_SPARK is
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
Selected_C : constant Perm_Tree_Access :=
Perm_Tree_Maps.Get
(Component (C.Tree_Access), Selected_Component);
begin
if Selected_C = null then
- return (R => Unfolded,
+ return (R => Unfolded,
Tree_Access =>
Other_Components (C.Tree_Access));
+
else
- return (R => Unfolded,
+ return (R => Unfolded,
Tree_Access => Selected_C);
end if;
end;
+
elsif Kind (C.Tree_Access) = Entire_Object then
- return (R => Folded, Found_Permission =>
+ return (R => Folded,
+ Found_Permission =>
Children_Permission (C.Tree_Access));
+
else
raise Program_Error;
end if;
end case;
end;
-
-- We get the permission tree of its prefix, and then get either the
-- subtree associated with that specific selection, or if we have a
-- leaf that folds its children, we take the children's permission
@@ -3077,8 +2743,7 @@ package body Sem_SPARK is
| N_Slice
=>
declare
- C : constant Perm_Or_Tree :=
- Get_Perm_Or_Tree (Prefix (N));
+ C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
begin
case C.R is
@@ -3089,25 +2754,24 @@ package body Sem_SPARK is
when Unfolded =>
pragma Assert (C.Tree_Access /= null);
-
pragma Assert (Kind (C.Tree_Access) = Entire_Object
or else
Kind (C.Tree_Access) = Array_Component);
if Kind (C.Tree_Access) = Array_Component then
pragma Assert (Get_Elem (C.Tree_Access) /= null);
-
return (R => Unfolded,
Tree_Access => Get_Elem (C.Tree_Access));
+
elsif Kind (C.Tree_Access) = Entire_Object then
return (R => Folded, Found_Permission =>
Children_Permission (C.Tree_Access));
+
else
raise Program_Error;
end if;
end case;
end;
-
-- We get the permission tree of its prefix, and then get either the
-- subtree associated with that specific selection, or if we have a
-- leaf that folds its children, we take the children's permission
@@ -3115,8 +2779,7 @@ package body Sem_SPARK is
when N_Explicit_Dereference =>
declare
- C : constant Perm_Or_Tree :=
- Get_Perm_Or_Tree (Prefix (N));
+ C : constant Perm_Or_Tree := Get_Perm_Or_Tree (Prefix (N));
begin
case C.R is
@@ -3127,29 +2790,32 @@ package body Sem_SPARK is
when Unfolded =>
pragma Assert (C.Tree_Access /= null);
-
pragma Assert (Kind (C.Tree_Access) = Entire_Object
or else
Kind (C.Tree_Access) = Reference);
if Kind (C.Tree_Access) = Reference then
if Get_All (C.Tree_Access) = null then
+
-- Hash_Table_Error
+
raise Program_Error;
+
else
return
(R => Unfolded,
Tree_Access => Get_All (C.Tree_Access));
end if;
+
elsif Kind (C.Tree_Access) = Entire_Object then
return (R => Folded, Found_Permission =>
Children_Permission (C.Tree_Access));
+
else
raise Program_Error;
end if;
end case;
end;
-
-- The name contains a function call, hence the given path is always
-- new. We do not have to check for anything.
@@ -3165,10 +2831,7 @@ package body Sem_SPARK is
-- Get_Perm_Tree --
-------------------
- function Get_Perm_Tree
- (N : Node_Id)
- return Perm_Tree_Access
- is
+ function Get_Perm_Tree (N : Node_Id) return Perm_Tree_Access is
begin
case Nkind (N) is
@@ -3183,7 +2846,6 @@ package body Sem_SPARK is
=>
declare
P : constant Node_Id := Entity (N);
-
C : constant Perm_Tree_Access :=
Get (Current_Perm_Env, Unique_Entity (P));
@@ -3193,13 +2855,13 @@ package body Sem_SPARK is
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
-
if C = null then
-- No null possible here, there are no parents for the path.
-- This means we are using a global variable without adding
-- it in environment with a global aspect.
Illegal_Global_Usage (N);
+
else
return C;
end if;
@@ -3220,11 +2882,11 @@ package body Sem_SPARK is
when N_Selected_Component =>
declare
- C : constant Perm_Tree_Access :=
- Get_Perm_Tree (Prefix (N));
+ C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
begin
if C = null then
+
-- If null then it means we went through a function call
return null;
@@ -3234,6 +2896,7 @@ package body Sem_SPARK is
or else Kind (C) = Record_Component);
if Kind (C) = Record_Component then
+
-- The tree is unfolded. We just return the subtree.
declare
@@ -3247,9 +2910,9 @@ package body Sem_SPARK is
if Selected_C = null then
return Other_Components (C);
end if;
-
return Selected_C;
end;
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with
@@ -3265,7 +2928,6 @@ package body Sem_SPARK is
Children_Permission (C);
begin
-
-- We change the current node from Entire_Object to
-- Record_Component with same permission and an empty
-- hash table as component list.
@@ -3288,6 +2950,7 @@ package body Sem_SPARK is
-- We fill the hash table with all sons of the record,
-- with basic Entire_Objects nodes.
+
Elem := First_Component_Or_Discriminant
(Etype (Prefix (N)));
@@ -3301,10 +2964,8 @@ package body Sem_SPARK is
Perm_Tree_Maps.Set
(C.all.Tree.Component, Elem, Son);
-
Next_Component_Or_Discriminant (Elem);
end loop;
-
-- we return the tree to the sons, so that the recursion
-- can continue.
@@ -3318,16 +2979,13 @@ package body Sem_SPARK is
begin
pragma Assert (Selected_C /= null);
-
return Selected_C;
end;
-
end;
else
raise Program_Error;
end if;
end;
-
-- We set the permission tree of its prefix, and then we extract from
-- the returned pointer the subtree. If folded, we unroll the tree at
-- one step.
@@ -3336,8 +2994,7 @@ package body Sem_SPARK is
| N_Slice
=>
declare
- C : constant Perm_Tree_Access :=
- Get_Perm_Tree (Prefix (N));
+ C : constant Perm_Tree_Access := Get_Perm_Tree (Prefix (N));
begin
if C = null then
@@ -3345,16 +3002,16 @@ package body Sem_SPARK is
return null;
end if;
-
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Array_Component);
if Kind (C) = Array_Component then
+
-- The tree is unfolded. We just return the elem subtree
pragma Assert (Get_Elem (C) = null);
-
return Get_Elem (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace node with Array_Component.
@@ -3377,14 +3034,12 @@ package body Sem_SPARK is
Is_Node_Deep => Is_Node_Deep (C),
Permission => Permission (C),
Get_Elem => Son);
-
return Get_Elem (C);
end;
else
raise Program_Error;
end if;
end;
-
-- We get the permission tree of its prefix, and then get either the
-- subtree associated with that specific selection, or if we have a
-- leaf that folds its children, we unroll the tree.
@@ -3397,6 +3052,7 @@ package body Sem_SPARK is
C := Get_Perm_Tree (Prefix (N));
if C = null then
+
-- If null, we went through a function call
return null;
@@ -3406,14 +3062,17 @@ package body Sem_SPARK is
or else Kind (C) = Reference);
if Kind (C) = Reference then
+
-- The tree is unfolded. We return the elem subtree
if Get_All (C) = null then
+
-- Hash_Table_Error
+
raise Program_Error;
end if;
-
return Get_All (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with Reference.
@@ -3432,19 +3091,16 @@ package body Sem_SPARK is
-- Reference with same permission and the previous son.
pragma Assert (Is_Node_Deep (C));
-
C.all.Tree := (Kind => Reference,
Is_Node_Deep => Is_Node_Deep (C),
Permission => Permission (C),
Get_All => Son);
-
return Get_All (C);
end;
else
raise Program_Error;
end if;
end;
-
-- No permission tree for function calls
when N_Function_Call =>
@@ -3455,245 +3111,6 @@ package body Sem_SPARK is
end case;
end Get_Perm_Tree;
- ---------
- -- Glb --
- ---------
-
- function Glb (P1, P2 : Perm_Kind) return Perm_Kind
- is
- begin
- case P1 is
- when No_Access =>
- return No_Access;
-
- when Read_Only =>
- case P2 is
- when No_Access
- | Write_Only
- =>
- return No_Access;
-
- when Read_Perm =>
- return Read_Only;
- end case;
-
- when Write_Only =>
- case P2 is
- when No_Access
- | Read_Only
- =>
- return No_Access;
-
- when Write_Perm =>
- return Write_Only;
- end case;
-
- when Read_Write =>
- return P2;
- end case;
- end Glb;
-
- ---------------
- -- Has_Alias --
- ---------------
-
- function Has_Alias
- (N : Node_Id)
- return Boolean
- is
- function Has_Alias_Deep (Typ : Entity_Id) return Boolean;
- function Has_Alias_Deep (Typ : Entity_Id) return Boolean
- is
- Comp : Node_Id;
- begin
-
- if Is_Array_Type (Typ)
- and then Has_Aliased_Components (Typ)
- then
- return True;
-
- -- Note: Has_Aliased_Components applies only to arrays
-
- elsif Is_Record_Type (Typ) then
- -- It is possible to have an aliased discriminant, so they must be
- -- checked along with normal components.
-
- Comp := First_Component_Or_Discriminant (Typ);
- while Present (Comp) loop
- if Is_Aliased (Comp)
- or else Is_Aliased (Etype (Comp))
- then
- return True;
- end if;
-
- if Has_Alias_Deep (Etype (Comp)) then
- return True;
- end if;
-
- Next_Component_Or_Discriminant (Comp);
- end loop;
- return False;
- else
- return Is_Aliased (Typ);
- end if;
- end Has_Alias_Deep;
-
- begin
- case Nkind (N) is
-
- when N_Identifier
- | N_Expanded_Name
- =>
- return Is_Aliased (Entity (N)) or else Has_Alias_Deep (Etype (N));
-
- when N_Defining_Identifier =>
- return Is_Aliased (N) or else Has_Alias_Deep (Etype (N));
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Has_Alias (Expression (N));
-
- when N_Parameter_Specification =>
- return Has_Alias (Defining_Identifier (N));
-
- when N_Selected_Component =>
- case Nkind (Selector_Name (N)) is
- when N_Identifier =>
- if Is_Aliased (Entity (Selector_Name (N))) then
- return True;
- end if;
-
- when others => null;
-
- end case;
-
- return Has_Alias (Prefix (N));
-
- when N_Indexed_Component
- | N_Slice
- =>
- return Has_Alias (Prefix (N));
-
- when N_Explicit_Dereference =>
- return True;
-
- when N_Function_Call =>
- return False;
-
- when N_Attribute_Reference =>
- if Is_Deep (Etype (Prefix (N))) then
- raise Program_Error;
- end if;
- return False;
-
- when others =>
- return False;
- end case;
- end Has_Alias;
-
- -------------------------
- -- Has_Array_Component --
- -------------------------
-
- function Has_Array_Component (N : Node_Id) return Boolean is
- begin
- case Nkind (N) is
- -- Base identifier. There is no array component here.
-
- when N_Identifier
- | N_Expanded_Name
- | N_Defining_Identifier
- =>
- return False;
-
- -- We check if the expression inside the conversion has an array
- -- component.
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Has_Array_Component (Expression (N));
-
- -- We check if the prefix has an array component
-
- when N_Selected_Component =>
- return Has_Array_Component (Prefix (N));
-
- -- We found the array component, return True
-
- when N_Indexed_Component
- | N_Slice
- =>
- return True;
-
- -- We check if the prefix has an array component
-
- when N_Explicit_Dereference =>
- return Has_Array_Component (Prefix (N));
-
- when N_Function_Call =>
- return False;
-
- when others =>
- raise Program_Error;
- end case;
- end Has_Array_Component;
-
- ----------------------------
- -- Has_Function_Component --
- ----------------------------
-
- function Has_Function_Component (N : Node_Id) return Boolean is
- begin
- case Nkind (N) is
- -- Base identifier. There is no function component here.
-
- when N_Identifier
- | N_Expanded_Name
- | N_Defining_Identifier
- =>
- return False;
-
- -- We check if the expression inside the conversion has a function
- -- component.
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Has_Function_Component (Expression (N));
-
- -- We check if the prefix has a function component
-
- when N_Selected_Component =>
- return Has_Function_Component (Prefix (N));
-
- -- We check if the prefix has a function component
-
- when N_Indexed_Component
- | N_Slice
- =>
- return Has_Function_Component (Prefix (N));
-
- -- We check if the prefix has a function component
-
- when N_Explicit_Dereference =>
- return Has_Function_Component (Prefix (N));
-
- -- We found the function component, return True
-
- when N_Function_Call =>
- return True;
-
- when others =>
- raise Program_Error;
-
- end case;
- end Has_Function_Component;
-
--------
-- Hp --
--------
@@ -3717,29 +3134,17 @@ package body Sem_SPARK is
begin
Error_Msg_NE ("cannot use global variable & of deep type", N, N);
Error_Msg_N ("\without prior declaration in a Global aspect", N);
-
Errout.Finalize (Last_Call => True);
Errout.Output_Messages;
Exit_Program (E_Errors);
end Illegal_Global_Usage;
- --------------------
- -- Is_Borrowed_In --
- --------------------
-
- function Is_Borrowed_In (E : Entity_Id) return Boolean is
- begin
- return Is_Access_Type (Etype (E))
- and then not Is_Access_Constant (Etype (E));
- end Is_Borrowed_In;
-
-------------
-- Is_Deep --
-------------
function Is_Deep (E : Entity_Id) return Boolean is
function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean;
-
function Is_Private_Entity_Mode_Off (E : Entity_Id) return Boolean is
Decl : Node_Id;
Pack_Decl : Node_Id;
@@ -3762,9 +3167,9 @@ package body Sem_SPARK is
and then Get_SPARK_Mode_From_Annotation
(SPARK_Aux_Pragma (Defining_Entity (Pack_Decl))) = Off;
end Is_Private_Entity_Mode_Off;
+
begin
pragma Assert (Is_Type (E));
-
case Ekind (E) is
when Scalar_Kind =>
return False;
@@ -3793,7 +3198,7 @@ package body Sem_SPARK is
when E_Record_Type
| E_Record_Subtype
- =>
+ =>
declare
Elmt : Entity_Id;
@@ -3806,7 +3211,6 @@ package body Sem_SPARK is
Next_Component_Or_Discriminant (Elmt);
end if;
end loop;
-
return False;
end;
@@ -3821,10 +3225,9 @@ package body Sem_SPARK is
end if;
end if;
- when E_Incomplete_Type =>
- return True;
-
- when E_Incomplete_Subtype =>
+ when E_Incomplete_Type
+ | E_Incomplete_Subtype
+ =>
return True;
-- No problem with synchronized types
@@ -3845,311 +3248,6 @@ package body Sem_SPARK is
end Is_Deep;
----------------
- -- Is_Shallow --
- ----------------
-
- function Is_Shallow (E : Entity_Id) return Boolean is
- begin
- pragma Assert (Is_Type (E));
- return not Is_Deep (E);
- end Is_Shallow;
-
- ------------------
- -- Loop_Of_Exit --
- ------------------
-
- function Loop_Of_Exit (N : Node_Id) return Entity_Id is
- Nam : Node_Id := Name (N);
- Stmt : Node_Id := N;
- begin
- if No (Nam) then
- while Present (Stmt) loop
- Stmt := Parent (Stmt);
- if Nkind (Stmt) = N_Loop_Statement then
- Nam := Identifier (Stmt);
- exit;
- end if;
- end loop;
- end if;
- return Entity (Nam);
- end Loop_Of_Exit;
- ---------
- -- Lub --
- ---------
-
- function Lub (P1, P2 : Perm_Kind) return Perm_Kind
- is
- begin
- case P1 is
- when No_Access =>
- return P2;
-
- when Read_Only =>
- case P2 is
- when No_Access
- | Read_Only
- =>
- return Read_Only;
-
- when Write_Perm =>
- return Read_Write;
- end case;
-
- when Write_Only =>
- case P2 is
- when No_Access
- | Write_Only
- =>
- return Write_Only;
-
- when Read_Perm =>
- return Read_Write;
- end case;
-
- when Read_Write =>
- return Read_Write;
- end case;
- end Lub;
-
- ----------------
- -- Merge_Envs --
- ----------------
-
- procedure Merge_Envs
- (Target : in out Perm_Env;
- Source : in out Perm_Env)
- is
- procedure Merge_Trees
- (Target : Perm_Tree_Access;
- Source : Perm_Tree_Access);
-
- procedure Merge_Trees
- (Target : Perm_Tree_Access;
- Source : Perm_Tree_Access)
- is
- procedure Apply_Glb_Tree
- (A : Perm_Tree_Access;
- P : Perm_Kind);
-
- procedure Apply_Glb_Tree
- (A : Perm_Tree_Access;
- P : Perm_Kind)
- is
- begin
- A.all.Tree.Permission := Glb (Permission (A), P);
-
- case Kind (A) is
- when Entire_Object =>
- A.all.Tree.Children_Permission :=
- Glb (Children_Permission (A), P);
-
- when Reference =>
- Apply_Glb_Tree (Get_All (A), P);
-
- when Array_Component =>
- Apply_Glb_Tree (Get_Elem (A), P);
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- begin
- Comp := Perm_Tree_Maps.Get_First (Component (A));
- while Comp /= null loop
- Apply_Glb_Tree (Comp, P);
- Comp := Perm_Tree_Maps.Get_Next (Component (A));
- end loop;
-
- Apply_Glb_Tree (Other_Components (A), P);
- end;
- end case;
- end Apply_Glb_Tree;
-
- Perm : constant Perm_Kind :=
- Glb (Permission (Target), Permission (Source));
-
- begin
- pragma Assert (Is_Node_Deep (Target) = Is_Node_Deep (Source));
- Target.all.Tree.Permission := Perm;
-
- case Kind (Target) is
- when Entire_Object =>
- declare
- Child_Perm : constant Perm_Kind :=
- Children_Permission (Target);
-
- begin
- case Kind (Source) is
- when Entire_Object =>
- Target.all.Tree.Children_Permission :=
- Glb (Child_Perm, Children_Permission (Source));
-
- when Reference =>
- Copy_Tree (Source, Target);
- Target.all.Tree.Permission := Perm;
- Apply_Glb_Tree (Get_All (Target), Child_Perm);
-
- when Array_Component =>
- Copy_Tree (Source, Target);
- Target.all.Tree.Permission := Perm;
- Apply_Glb_Tree (Get_Elem (Target), Child_Perm);
-
- when Record_Component =>
- Copy_Tree (Source, Target);
- Target.all.Tree.Permission := Perm;
- declare
- Comp : Perm_Tree_Access;
-
- begin
- Comp :=
- Perm_Tree_Maps.Get_First (Component (Target));
- while Comp /= null loop
- -- Apply glb tree on every component subtree
-
- Apply_Glb_Tree (Comp, Child_Perm);
- Comp := Perm_Tree_Maps.Get_Next
- (Component (Target));
- end loop;
- end;
- Apply_Glb_Tree (Other_Components (Target), Child_Perm);
-
- end case;
- end;
- when Reference =>
- case Kind (Source) is
- when Entire_Object =>
- Apply_Glb_Tree (Get_All (Target),
- Children_Permission (Source));
-
- when Reference =>
- Merge_Trees (Get_All (Target), Get_All (Source));
-
- when others =>
- raise Program_Error;
-
- end case;
-
- when Array_Component =>
- case Kind (Source) is
- when Entire_Object =>
- Apply_Glb_Tree (Get_Elem (Target),
- Children_Permission (Source));
-
- when Array_Component =>
- Merge_Trees (Get_Elem (Target), Get_Elem (Source));
-
- when others =>
- raise Program_Error;
-
- end case;
-
- when Record_Component =>
- case Kind (Source) is
- when Entire_Object =>
- declare
- Child_Perm : constant Perm_Kind :=
- Children_Permission (Source);
-
- Comp : Perm_Tree_Access;
-
- begin
- Comp := Perm_Tree_Maps.Get_First
- (Component (Target));
- while Comp /= null loop
- -- Apply glb tree on every component subtree
-
- Apply_Glb_Tree (Comp, Child_Perm);
- Comp :=
- Perm_Tree_Maps.Get_Next (Component (Target));
- end loop;
- Apply_Glb_Tree (Other_Components (Target), Child_Perm);
- end;
-
- when Record_Component =>
- declare
- Key_Source : Perm_Tree_Maps.Key_Option;
- CompTarget : Perm_Tree_Access;
- CompSource : Perm_Tree_Access;
-
- begin
- Key_Source := Perm_Tree_Maps.Get_First_Key
- (Component (Source));
-
- while Key_Source.Present loop
- CompSource := Perm_Tree_Maps.Get
- (Component (Source), Key_Source.K);
- CompTarget := Perm_Tree_Maps.Get
- (Component (Target), Key_Source.K);
-
- pragma Assert (CompSource /= null);
- Merge_Trees (CompTarget, CompSource);
-
- Key_Source := Perm_Tree_Maps.Get_Next_Key
- (Component (Source));
- end loop;
-
- Merge_Trees (Other_Components (Target),
- Other_Components (Source));
- end;
-
- when others =>
- raise Program_Error;
-
- end case;
- end case;
- end Merge_Trees;
-
- CompTarget : Perm_Tree_Access;
- CompSource : Perm_Tree_Access;
- KeyTarget : Perm_Tree_Maps.Key_Option;
-
- begin
- KeyTarget := Get_First_Key (Target);
- -- Iterate over every tree of the environment in the target, and merge
- -- it with the source if there is such a similar one that exists. If
- -- there is none, then skip.
- while KeyTarget.Present loop
-
- CompSource := Get (Source, KeyTarget.K);
- CompTarget := Get (Target, KeyTarget.K);
-
- pragma Assert (CompTarget /= null);
-
- if CompSource /= null then
- Merge_Trees (CompTarget, CompSource);
- Remove (Source, KeyTarget.K);
- end if;
-
- KeyTarget := Get_Next_Key (Target);
- end loop;
-
- -- Iterate over every tree of the environment of the source. And merge
- -- again. If there is not any tree of the target then just copy the tree
- -- from source to target.
- declare
- KeySource : Perm_Tree_Maps.Key_Option;
- begin
- KeySource := Get_First_Key (Source);
- while KeySource.Present loop
-
- CompSource := Get (Source, KeySource.K);
- CompTarget := Get (Target, KeySource.K);
-
- if CompTarget = null then
- CompTarget := new Perm_Tree_Wrapper'(CompSource.all);
- Copy_Tree (CompSource, CompTarget);
- Set (Target, KeySource.K, CompTarget);
- else
- Merge_Trees (CompTarget, CompSource);
- end if;
-
- KeySource := Get_Next_Key (Source);
- end loop;
- end;
-
- Free_Env (Source);
- end Merge_Envs;
-
- ----------------
-- Perm_Error --
----------------
@@ -4202,7 +3300,6 @@ package body Sem_SPARK is
raise Program_Error;
end case;
end Set_Root_Object;
-
-- Local variables
Root : Entity_Id;
@@ -4245,8 +3342,8 @@ package body Sem_SPARK is
------------------
procedure Process_Path (N : Node_Id) is
- Root : constant Entity_Id := Get_Enclosing_Object (N);
-
+ Root : constant Entity_Id := Get_Enclosing_Object (N);
+ State_N : Perm_Kind;
begin
-- We ignore if yielding to synchronized
@@ -4256,200 +3353,153 @@ package body Sem_SPARK is
return;
end if;
- -- We ignore shallow unaliased. They are checked in flow analysis,
- -- allowing backward compatibility.
+ State_N := Get_Perm (N);
- if Current_Checking_Mode /= Super_Move
- and then not Has_Alias (N)
- and then Is_Shallow (Etype (N))
- then
- return;
- end if;
-
- declare
- Perm_N : constant Perm_Kind := Get_Perm (N);
+ case Current_Checking_Mode is
- begin
+ -- Check permission R, do nothing
- case Current_Checking_Mode is
- -- Check permission R, do nothing
+ when Read =>
- when Read =>
- if Perm_N not in Read_Perm then
- Perm_Error (N, Read_Only, Perm_N);
- return;
- end if;
+ -- This condition should be removed when removing the read
+ -- checking mode.
- -- If shallow type no need for RW, only R
+ return;
- when Move =>
- if Is_Shallow (Etype (N)) then
- if Perm_N not in Read_Perm then
- Perm_Error (N, Read_Only, Perm_N);
- return;
- end if;
- else
- -- Check permission RW if deep
+ when Move =>
- if Perm_N /= Read_Write then
- Perm_Error (N, Read_Write, Perm_N);
- return;
- end if;
+ -- The rhs object in an assignment statement (including copy in
+ -- and copy back) should be in the Unrestricted or Moved state.
+ -- Otherwise the move is not allowed.
+ -- This applies to both stand-alone and composite objects.
+ -- If the state of the source is Moved, then a warning message
+ -- is prompt to make the user aware of reading a nullified
+ -- object.
- declare
- -- Set permission to W to the path and any of its prefix
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (N, Move);
+ if State_N /= Unrestricted and State_N /= Moved then
+ Perm_Error (N, Unrestricted, State_N);
+ return;
+ end if;
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
+ -- In the AI, after moving a path nothing to do since the rhs
+ -- object was in the Unrestricted state and it shall be
+ -- refreshed to Unrestricted. The object should be nullified
+ -- however. To avoid moving again a name that has already been
+ -- moved, in this implementation we set the state of the moved
+ -- object to "Moved". This shall be used to prompt a warning
+ -- when manipulating a null pointer and also to implement
+ -- the no aliasing parameter restriction.
+
+ if State_N = Moved then
+ Error_Msg_N ("?the source or one of its extensions has"
+ & " already been moved", N);
+ end if;
- return;
- end if;
+ declare
+ -- Set state to Borrowed to the path and any of its prefixes
- -- Set permissions to
- -- No for any extension with more .all
- -- W for any deep extension with same number of .all
- -- RW for any shallow extension with same number of .all
+ Tree : constant Perm_Tree_Access :=
+ Set_Perm_Prefixes (N, Moved);
- Set_Perm_Extensions_Move (Tree, Etype (N));
- end;
- end if;
+ begin
+ if Tree = null then
- -- Check permission RW
+ -- We went through a function call, no permission to
+ -- modify.
- when Super_Move =>
- if Perm_N /= Read_Write then
- Perm_Error (N, Read_Write, Perm_N);
return;
end if;
- declare
- -- Set permission to No to the path and any of its prefix up
- -- to the first .all and then W.
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (N, Super_Move);
+ -- Set state to Borrowed on any strict extension of the path
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
-
- return;
- end if;
-
- -- Set permissions to No on any strict extension of the path
+ Set_Perm_Extensions (Tree, Moved);
+ end;
- Set_Perm_Extensions (Tree, No_Access);
- end;
+ when Assign =>
- -- Check permission W
+ -- The lhs object in an assignment statement (including copy in
+ -- and copy back) should be in the Unrestricted state.
+ -- Otherwise the move is not allowed.
+ -- This applies to both stand-alone and composite objects.
- when Assign =>
- if Perm_N not in Write_Perm then
- Perm_Error (N, Write_Only, Perm_N);
- return;
- end if;
+ if State_N /= Unrestricted and State_N /= Moved then
+ Perm_Error (N, Unrestricted, State_N);
+ return;
+ end if;
- -- If the tree has an array component, then the permissions do
- -- not get modified by the assignment.
+ -- After assigning to a path nothing to do since it was in the
+ -- Unrestricted state and it would be refreshed to
+ -- Unrestricted.
- if Has_Array_Component (N) then
- return;
- end if;
+ when Borrow =>
- -- Same if has function component
+ -- Borrowing is only allowed on Unrestricted objects.
- if Has_Function_Component (N) then -- Dead code?
- return;
- end if;
+ if State_N /= Unrestricted and State_N /= Moved then
+ Perm_Error (N, Unrestricted, State_N);
+ end if;
- declare
- -- Get the permission tree for the path
+ if State_N = Moved then
+ Error_Msg_N ("?the source or one of its extensions has"
+ & " already been moved", N);
+ end if;
- Tree : constant Perm_Tree_Access :=
- Get_Perm_Tree (N);
+ declare
+ -- Set state to Borrowed to the path and any of its prefixes
- Dummy : Perm_Tree_Access;
+ Tree : constant Perm_Tree_Access :=
+ Set_Perm_Prefixes (N, Borrowed);
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
+ begin
+ if Tree = null then
- return;
- end if;
+ -- We went through a function call, no permission to
+ -- modify.
- -- Set permission RW for it and all of its extensions
+ return;
+ end if;
- Tree.all.Tree.Permission := Read_Write;
+ -- Set state to Borrowed on any strict extension of the path
- Set_Perm_Extensions (Tree, Read_Write);
+ Set_Perm_Extensions (Tree, Borrowed);
+ end;
- -- Normalize the permission tree
+ when Observe =>
+ if State_N /= Unrestricted
+ and then State_N /= Observed
+ then
+ Perm_Error (N, Observed, State_N);
+ end if;
- Dummy := Set_Perm_Prefixes_Assign (N);
- end;
+ declare
+ -- Set permission to Observed on the path and any of its
+ -- prefixes if it is of a deep type. Actually, some operation
+ -- like reading from an object of access type is considered as
+ -- observe while it should not affect the permissions of
+ -- the considered tree.
- -- Check permission W
+ Tree : Perm_Tree_Access;
- when Borrow_Out =>
- if Perm_N not in Write_Perm then
- Perm_Error (N, Write_Only, Perm_N);
+ begin
+ if Is_Deep (Etype (N)) then
+ Tree := Set_Perm_Prefixes (N, Observed);
+ else
+ Tree := null;
end if;
- declare
- -- Set permission to No to the path and any of its prefixes
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (N);
-
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
-
- return;
- end if;
-
- -- Set permissions to No on any strict extension of the path
+ if Tree = null then
- Set_Perm_Extensions (Tree, No_Access);
- end;
+ -- We went through a function call, no permission to
+ -- modify.
- when Observe =>
- if Perm_N not in Read_Perm then
- Perm_Error (N, Read_Only, Perm_N);
- end if;
-
- if Is_By_Copy_Type (Etype (N)) then
return;
end if;
- declare
- -- Set permission to No on the path and any of its prefixes
-
- Tree : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (N);
-
- begin
- if Tree = null then
- -- We went through a function call, no permission to
- -- modify.
+ -- Set permissions to No on any strict extension of the path
- return;
- end if;
-
- -- Set permissions to No on any strict extension of the path
-
- Set_Perm_Extensions (Tree, Read_Only);
- end;
- end case;
- end;
+ Set_Perm_Extensions (Tree, Observed);
+ end;
+ end case;
end Process_Path;
-------------------------
@@ -4457,7 +3507,6 @@ package body Sem_SPARK is
-------------------------
procedure Return_Declarations (L : List_Id) is
-
procedure Return_Declaration (Decl : Node_Id);
-- Check correct permissions for every declared object
@@ -4468,6 +3517,7 @@ package body Sem_SPARK is
procedure Return_Declaration (Decl : Node_Id) is
begin
if Nkind (Decl) = N_Object_Declaration then
+
-- Check RW for object declared, unless the object has never been
-- initialized.
@@ -4477,15 +3527,6 @@ package body Sem_SPARK is
return;
end if;
- -- We ignore shallow unaliased. They are checked in flow analysis,
- -- allowing backward compatibility.
-
- if not Has_Alias (Defining_Identifier (Decl))
- and then Is_Shallow (Etype (Defining_Identifier (Decl)))
- then
- return;
- end if;
-
declare
Elem : constant Perm_Tree_Access :=
Get (Current_Perm_Env,
@@ -4493,22 +3534,23 @@ package body Sem_SPARK is
begin
if Elem = null then
+
-- Here we are on a declaration. Hence it should have been
-- added in the environment when analyzing this node with
-- mode Read. Hence it is not possible to find a null
-- pointer here.
-- Hash_Table_Error
+
raise Program_Error;
end if;
- if Permission (Elem) /= Read_Write then
- Perm_Error (Decl, Read_Write, Permission (Elem));
+ if Permission (Elem) /= Unrestricted then
+ Perm_Error (Decl, Unrestricted, Permission (Elem));
end if;
end;
end if;
end Return_Declaration;
-
-- Local Variables
N : Node_Id;
@@ -4528,7 +3570,6 @@ package body Sem_SPARK is
--------------------
procedure Return_Globals (Subp : Entity_Id) is
-
procedure Return_Globals_From_List
(First_Item : Node_Id;
Kind : Formal_Kind);
@@ -4557,7 +3598,7 @@ package body Sem_SPARK is
if Ekind (E) = E_Abstract_State then
null;
else
- Return_Parameter_Or_Global (E, Kind, Subp, Global_Var => True);
+ Return_The_Global (E, Kind, Subp);
end if;
Next_Global (Item);
end loop;
@@ -4572,7 +3613,9 @@ package body Sem_SPARK is
begin
case Global_Mode is
- when Name_Input | Name_Proof_In =>
+ when Name_Input
+ | Name_Proof_In
+ =>
Kind := E_In_Parameter;
when Name_Output =>
Kind := E_Out_Parameter;
@@ -4602,71 +3645,54 @@ package body Sem_SPARK is
-- Return_Parameter_Or_Global --
--------------------------------
- procedure Return_Parameter_Or_Global
- (Id : Entity_Id;
- Mode : Formal_Kind;
- Subp : Entity_Id;
- Global_Var : Boolean)
+ procedure Return_The_Global
+ (Id : Entity_Id;
+ Mode : Formal_Kind;
+ Subp : Entity_Id)
is
Elem : constant Perm_Tree_Access := Get (Current_Perm_Env, Id);
pragma Assert (Elem /= null);
begin
- -- Shallow unaliased parameters and globals cannot introduce pointer
- -- aliasing.
-
- if not Has_Alias (Id) and then Is_Shallow (Etype (Id)) then
- null;
-
-- Observed IN parameters and globals need not return a permission to
-- the caller.
- elsif Mode = E_In_Parameter
- and then (not Is_Borrowed_In (Id) or else Global_Var)
+ if Mode = E_In_Parameter
+
+ -- Check this for read-only globals.
+
then
- null;
+ if Permission (Elem) /= Unrestricted
+ and then Permission (Elem) /= Observed
+ then
+ Perm_Error_Subprogram_End
+ (E => Id,
+ Subp => Subp,
+ Perm => Observed,
+ Found_Perm => Permission (Elem));
+ end if;
- -- All other parameters and globals should return with mode RW to the
- -- caller.
+ -- All globals of mode out or in/out should return with mode
+ -- Unrestricted.
else
- if Permission (Elem) /= Read_Write then
+ if Permission (Elem) /= Unrestricted then
Perm_Error_Subprogram_End
(E => Id,
Subp => Subp,
- Perm => Read_Write,
+ Perm => Unrestricted,
Found_Perm => Permission (Elem));
end if;
end if;
- end Return_Parameter_Or_Global;
-
- -----------------------
- -- Return_Parameters --
- -----------------------
-
- procedure Return_Parameters (Subp : Entity_Id) is
- Formal : Entity_Id;
-
- begin
- Formal := First_Formal (Subp);
- while Present (Formal) loop
- Return_Parameter_Or_Global (Formal, Ekind (Formal), Subp, False);
- Next_Formal (Formal);
- end loop;
- end Return_Parameters;
+ end Return_The_Global;
-------------------------
-- Set_Perm_Extensions --
-------------------------
- procedure Set_Perm_Extensions
- (T : Perm_Tree_Access;
- P : Perm_Kind)
- is
+ procedure Set_Perm_Extensions (T : Perm_Tree_Access; P : Perm_Kind) is
procedure Free_Perm_Tree_Children (T : Perm_Tree_Access);
-
- procedure Free_Perm_Tree_Children (T : Perm_Tree_Access)
- is
+ procedure Free_Perm_Tree_Children (T : Perm_Tree_Access) is
begin
case Kind (T) is
when Entire_Object =>
@@ -4709,316 +3735,59 @@ package body Sem_SPARK is
end Set_Perm_Extensions;
------------------------------
- -- Set_Perm_Extensions_Move --
+ -- Set_Perm_Prefixes --
------------------------------
- procedure Set_Perm_Extensions_Move
- (T : Perm_Tree_Access;
- E : Entity_Id)
+ function Set_Perm_Prefixes
+ (N : Node_Id;
+ New_Perm : Perm_Kind)
+ return Perm_Tree_Access
is
begin
- if not Is_Node_Deep (T) then
- -- We are a shallow extension with same number of .all
-
- Set_Perm_Extensions (T, Read_Write);
- return;
- end if;
-
- -- We are a deep extension here (or the moved deep path)
-
- T.all.Tree.Permission := Write_Only;
-
- case T.all.Tree.Kind is
- -- Unroll the tree depending on the type
-
- when Entire_Object =>
- case Ekind (E) is
- when Scalar_Kind
- | E_String_Literal_Subtype
- =>
- Set_Perm_Extensions (T, No_Access);
-
- -- No need to unroll here, directly put sons to No_Access
-
- when Access_Kind =>
- if Ekind (E) in Access_Subprogram_Kind then
- null;
- else
- Set_Perm_Extensions (T, No_Access);
- end if;
-
- -- No unrolling done, too complicated
-
- when E_Class_Wide_Subtype
- | E_Class_Wide_Type
- | E_Incomplete_Type
- | E_Incomplete_Subtype
- | E_Exception_Type
- | E_Task_Type
- | E_Task_Subtype
- =>
- Set_Perm_Extensions (T, No_Access);
-
- -- Expand the tree. Replace the node with Array component.
-
- when E_Array_Type
- | E_Array_Subtype =>
- declare
- Son : Perm_Tree_Access;
-
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (T),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- Set_Perm_Extensions_Move (Son, Component_Type (E));
-
- -- We change the current node from Entire_Object to
- -- Reference with Write_Only and the previous son.
-
- pragma Assert (Is_Node_Deep (T));
-
- T.all.Tree := (Kind => Array_Component,
- Is_Node_Deep => Is_Node_Deep (T),
- Permission => Write_Only,
- Get_Elem => Son);
- end;
-
- -- Unroll, and set permission extensions with component type
-
- when E_Record_Type
- | E_Record_Subtype
- | E_Record_Type_With_Private
- | E_Record_Subtype_With_Private
- | E_Protected_Type
- | E_Protected_Subtype
- =>
- declare
- -- Expand the tree. Replace the node with
- -- Record_Component.
-
- Elem : Node_Id;
-
- Son : Perm_Tree_Access;
-
- begin
- -- We change the current node from Entire_Object to
- -- Record_Component with same permission and an empty
- -- hash table as component list.
-
- pragma Assert (Is_Node_Deep (T));
-
- T.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (T),
- Permission => Write_Only,
- Component => Perm_Tree_Maps.Nil,
- Other_Components =>
- new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => True,
- Permission => Read_Write,
- Children_Permission => Read_Write)
- )
- );
-
- -- We fill the hash table with all sons of the record,
- -- with basic Entire_Objects nodes.
- Elem := First_Component_Or_Discriminant (E);
- while Present (Elem) loop
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- Set_Perm_Extensions_Move (Son, Etype (Elem));
-
- Perm_Tree_Maps.Set
- (T.all.Tree.Component, Elem, Son);
-
- Next_Component_Or_Discriminant (Elem);
- end loop;
- end;
-
- when E_Private_Type
- | E_Private_Subtype
- | E_Limited_Private_Type
- | E_Limited_Private_Subtype
- =>
- Set_Perm_Extensions_Move (T, Underlying_Type (E));
-
- when others =>
- raise Program_Error;
- end case;
-
- when Reference =>
- -- Now the son does not have the same number of .all
- Set_Perm_Extensions (T, No_Access);
-
- when Array_Component =>
- Set_Perm_Extensions_Move (Get_Elem (T), Component_Type (E));
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- It : Node_Id;
-
- begin
- It := First_Component_Or_Discriminant (E);
- while It /= Empty loop
- Comp := Perm_Tree_Maps.Get (Component (T), It);
- pragma Assert (Comp /= null);
- Set_Perm_Extensions_Move (Comp, It);
- It := Next_Component_Or_Discriminant (E);
- end loop;
-
- Set_Perm_Extensions (Other_Components (T), No_Access);
- end;
- end case;
- end Set_Perm_Extensions_Move;
-
- ------------------------------
- -- Set_Perm_Prefixes_Assign --
- ------------------------------
-
- function Set_Perm_Prefixes_Assign (N : Node_Id) return Perm_Tree_Access is
- C : constant Perm_Tree_Access := Get_Perm_Tree (N);
-
- begin
- pragma Assert (Current_Checking_Mode = Assign);
-
- -- The function should not be called if has_function_component
-
- pragma Assert (C /= null);
-
- case Kind (C) is
- when Entire_Object =>
- pragma Assert (Children_Permission (C) = Read_Write);
-
- -- Maroua: Children could have read_only perm. Why Read_Write?
-
- C.all.Tree.Permission := Read_Write;
-
- when Reference =>
- pragma Assert (Get_All (C) /= null);
-
- C.all.Tree.Permission :=
- Lub (Permission (C), Permission (Get_All (C)));
-
- when Array_Component =>
- pragma Assert (C.all.Tree.Get_Elem /= null);
-
- -- Given that it is not possible to know which element has been
- -- assigned, then the permissions do not get changed in case of
- -- Array_Component.
-
- null;
-
- when Record_Component =>
- declare
- Comp : Perm_Tree_Access;
- Perm : Perm_Kind := Read_Write;
-
- begin
- -- We take the Glb of all the descendants, and then update the
- -- permission of the node with it.
-
- Comp := Perm_Tree_Maps.Get_First (Component (C));
- while Comp /= null loop
- Perm := Glb (Perm, Permission (Comp));
- Comp := Perm_Tree_Maps.Get_Next (Component (C));
- end loop;
-
- Perm := Glb (Perm, Permission (Other_Components (C)));
-
- C.all.Tree.Permission := Lub (Permission (C), Perm);
- end;
- end case;
case Nkind (N) is
- -- Base identifier. End recursion here.
-
when N_Identifier
| N_Expanded_Name
| N_Defining_Identifier
=>
- return null;
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Set_Perm_Prefixes_Assign (Expression (N));
-
- when N_Parameter_Specification =>
- raise Program_Error;
-
- -- Continue recursion on prefix
-
- when N_Selected_Component =>
- return Set_Perm_Prefixes_Assign (Prefix (N));
-
- -- Continue recursion on prefix
-
- when N_Indexed_Component
- | N_Slice
- =>
- return Set_Perm_Prefixes_Assign (Prefix (N));
-
- -- Continue recursion on prefix
-
- when N_Explicit_Dereference =>
- return Set_Perm_Prefixes_Assign (Prefix (N));
-
- when N_Function_Call =>
- raise Program_Error;
-
- when others =>
- raise Program_Error;
-
- end case;
- end Set_Perm_Prefixes_Assign;
-
- ----------------------------------
- -- Set_Perm_Prefixes_Borrow_Out --
- ----------------------------------
-
- function Set_Perm_Prefixes_Borrow_Out
- (N : Node_Id)
- return Perm_Tree_Access
- is
- begin
- pragma Assert (Current_Checking_Mode = Borrow_Out);
-
- case Nkind (N) is
- -- Base identifier. Set permission to No.
+ if Nkind (N) = N_Defining_Identifier
+ and then New_Perm = Borrowed
+ then
+ raise Program_Error;
+ end if;
- when N_Identifier
- | N_Expanded_Name
- =>
declare
- P : constant Node_Id := Entity (N);
+ P : Node_Id;
+ C : Perm_Tree_Access;
- C : constant Perm_Tree_Access :=
- Get (Current_Perm_Env, Unique_Entity (P));
+ begin
+ if Nkind (N) = N_Defining_Identifier then
+ P := N;
+ else
+ P := Entity (N);
+ end if;
+ C := Get (Current_Perm_Env, Unique_Entity (P));
pragma Assert (C /= null);
- begin
-- Setting the initialization map to True, so that this
-- variable cannot be ignored anymore when looking at end
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
+ if New_Perm = Observed
+ and then C = null
+ then
- C.all.Tree.Permission := No_Access;
+ -- No null possible here, there are no parents for the path.
+ -- This means we are using a global variable without adding
+ -- it in environment with a global aspect.
+
+ Illegal_Global_Usage (N);
+ end if;
+
+ C.all.Tree.Permission := New_Perm;
return C;
end;
@@ -5026,11 +3795,9 @@ package body Sem_SPARK is
| N_Unchecked_Type_Conversion
| N_Qualified_Expression
=>
- return Set_Perm_Prefixes_Borrow_Out (Expression (N));
+ return Set_Perm_Prefixes (Expression (N), New_Perm);
- when N_Parameter_Specification
- | N_Defining_Identifier
- =>
+ when N_Parameter_Specification =>
raise Program_Error;
-- We set the permission tree of its prefix, and then we extract
@@ -5041,19 +3808,16 @@ package body Sem_SPARK is
when N_Selected_Component =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (Prefix (N));
+ Set_Perm_Prefixes (Prefix (N), New_Perm);
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be No
-
- pragma Assert (Permission (C) = No_Access);
-
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Record_Component);
@@ -5075,11 +3839,10 @@ package body Sem_SPARK is
end if;
pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission := No_Access;
-
+ Selected_C.all.Tree.Permission := New_Perm;
return Selected_C;
end;
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with
@@ -5094,9 +3857,8 @@ package body Sem_SPARK is
-- We create the unrolled nodes, that will all have same
-- permission than parent.
- Son : Perm_Tree_Access;
-
- ChildrenPerm : constant Perm_Kind :=
+ Son : Perm_Tree_Access;
+ Children_Perm : constant Perm_Kind :=
Children_Permission (C);
begin
@@ -5114,12 +3876,13 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => True,
- Permission => ChildrenPerm,
- Children_Permission => ChildrenPerm)
+ Permission => Children_Perm,
+ Children_Permission => Children_Perm)
));
-- We fill the hash table with all sons of the record,
-- with basic Entire_Objects nodes.
+
Elem := First_Component_Or_Discriminant
(Etype (Prefix (N)));
@@ -5128,23 +3891,19 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => ChildrenPerm,
- Children_Permission => ChildrenPerm));
-
- Perm_Tree_Maps.Set
- (C.all.Tree.Component, Elem, Son);
+ Permission => Children_Perm,
+ Children_Permission => Children_Perm));
+ Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
Next_Component_Or_Discriminant (Elem);
end loop;
-
- -- Now we set the right field to No_Access, and then we
+ -- Now we set the right field to Borrowed, and then we
-- return the tree to the sons, so that the recursion can
-- continue.
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
Selected_C : Perm_Tree_Access :=
Perm_Tree_Maps.Get
(Component (C), Selected_Component);
@@ -5155,9 +3914,7 @@ package body Sem_SPARK is
end if;
pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission := No_Access;
-
+ Selected_C.all.Tree.Permission := New_Perm;
return Selected_C;
end;
end;
@@ -5176,33 +3933,28 @@ package body Sem_SPARK is
=>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (Prefix (N));
+ Set_Perm_Prefixes (Prefix (N), New_Perm);
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be either W
- -- (because the recursive call sets <= Write_Only) or No
- -- (if another path has been moved with 'Access).
-
- pragma Assert (Permission (C) = No_Access);
-
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Array_Component);
if Kind (C) = Array_Component then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
pragma Assert (Get_Elem (C) /= null);
-
- C.all.Tree.Get_Elem.all.Tree.Permission := No_Access;
-
+ C.all.Tree.Get_Elem.all.Tree.Permission := New_Perm;
return Get_Elem (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace node with Array_Component.
@@ -5214,18 +3966,21 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => No_Access,
+ Permission => New_Perm,
Children_Permission => Children_Permission (C)));
+ -- Children_Permission => Children_Permission (C)
+ -- this line should be checked maybe New_Perm
+ -- instead of Children_Permission (C)
+
-- We change the current node from Entire_Object
-- to Array_Component with same permission and the
-- previously defined son.
C.all.Tree := (Kind => Array_Component,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => No_Access,
+ Permission => New_Perm,
Get_Elem => Son);
-
return Get_Elem (C);
end;
else
@@ -5241,30 +3996,28 @@ package body Sem_SPARK is
when N_Explicit_Dereference =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Borrow_Out (Prefix (N));
+ Set_Perm_Prefixes (Prefix (N), New_Perm);
begin
if C = null then
+
-- We went through a function call. Do nothing.
return null;
end if;
- -- The permission of the returned node should be No
-
- pragma Assert (Permission (C) = No_Access);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Reference);
if Kind (C) = Reference then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
pragma Assert (Get_All (C) /= null);
-
- C.all.Tree.Get_All.all.Tree.Permission := No_Access;
-
+ C.all.Tree.Get_All.all.Tree.Permission := New_Perm;
return Get_All (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with Reference.
@@ -5276,21 +4029,20 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => No_Access,
+ Permission => New_Perm,
Children_Permission => Children_Permission (C)));
-- We change the current node from Entire_Object to
- -- Reference with No_Access and the previous son.
+ -- Reference with Borrowed and the previous son.
pragma Assert (Is_Node_Deep (C));
-
C.all.Tree := (Kind => Reference,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => No_Access,
+ Permission => New_Perm,
Get_All => Son);
-
return Get_All (C);
end;
+
else
raise Program_Error;
end if;
@@ -5302,59 +4054,34 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
end case;
- end Set_Perm_Prefixes_Borrow_Out;
+ end Set_Perm_Prefixes;
- ----------------------------
- -- Set_Perm_Prefixes_Move --
- ----------------------------
+ ------------------------------
+ -- Set_Perm_Prefixes_Borrow --
+ ------------------------------
- function Set_Perm_Prefixes_Move
- (N : Node_Id; Mode : Checking_Mode)
- return Perm_Tree_Access
+ function Set_Perm_Prefixes_Borrow (N : Node_Id) return Perm_Tree_Access
is
begin
+ pragma Assert (Current_Checking_Mode = Borrow);
case Nkind (N) is
- -- Base identifier. Set permission to W or No depending on Mode.
-
when N_Identifier
| N_Expanded_Name
=>
declare
P : constant Node_Id := Entity (N);
C : constant Perm_Tree_Access :=
- Get (Current_Perm_Env, Unique_Entity (P));
+ Get (Current_Perm_Env, Unique_Entity (P));
+ pragma Assert (C /= null);
begin
- -- The base tree can be RW (first move from this base path) or
- -- W (already some extensions values moved), or even No_Access
- -- (extensions moved with 'Access). But it cannot be Read_Only
- -- (we get an error).
-
- if Permission (C) = Read_Only then
- raise Unrecoverable_Error;
- end if;
-
-- Setting the initialization map to True, so that this
-- variable cannot be ignored anymore when looking at end
-- of elaboration of package.
Set (Current_Initialization_Map, Unique_Entity (P), True);
-
- if C = null then
- -- No null possible here, there are no parents for the path.
- -- This means we are using a global variable without adding
- -- it in environment with a global aspect.
-
- Illegal_Global_Usage (N);
- end if;
-
- if Mode = Super_Move then
- C.all.Tree.Permission := No_Access;
- else
- C.all.Tree.Permission := Glb (Write_Only, Permission (C));
- end if;
-
+ C.all.Tree.Permission := Borrowed;
return C;
end;
@@ -5362,7 +4089,7 @@ package body Sem_SPARK is
| N_Unchecked_Type_Conversion
| N_Qualified_Expression
=>
- return Set_Perm_Prefixes_Move (Expression (N), Mode);
+ return Set_Perm_Prefixes_Borrow (Expression (N));
when N_Parameter_Specification
| N_Defining_Identifier
@@ -5370,79 +4097,51 @@ package body Sem_SPARK is
raise Program_Error;
-- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer our subtree and assign an adequate
+ -- our subtree from the returned pointer and assign an adequate
-- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
+ -- in one step.
when N_Selected_Component =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (Prefix (N), Mode);
+ Set_Perm_Prefixes_Borrow (Prefix (N));
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be either W
- -- (because the recursive call sets <= Write_Only) or No
- -- (if another path has been moved with 'Access).
-
- pragma Assert (Permission (C) = No_Access
- or else Permission (C) = Write_Only);
-
- if Mode = Super_Move then
- -- The permission of the returned node should be No (thanks
- -- to the recursion).
-
- pragma Assert (Permission (C) = No_Access);
- null;
- end if;
+ -- The permission of the returned node should be No
+ pragma Assert (Permission (C) = Borrowed);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Record_Component);
if Kind (C) = Record_Component then
+
-- The tree is unfolded. We just modify the permission and
-- return the record subtree.
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
Selected_C : Perm_Tree_Access :=
Perm_Tree_Maps.Get
(Component (C), Selected_Component);
begin
if Selected_C = null then
- -- If the hash table returns no element, then we fall
- -- into the part of Other_Components.
- pragma Assert (Is_Tagged_Type (Etype (Prefix (N))));
-
Selected_C := Other_Components (C);
end if;
pragma Assert (Selected_C /= null);
-
- -- The Selected_C can have permissions:
- -- RW : first move in this path
- -- W : Already other moves in this path
- -- No : Already other moves with 'Access
-
- pragma Assert (Permission (Selected_C) /= Read_Only);
- if Mode = Super_Move then
- Selected_C.all.Tree.Permission := No_Access;
- else
- Selected_C.all.Tree.Permission :=
- Glb (Write_Only, Permission (Selected_C));
-
- end if;
-
+ Selected_C.all.Tree.Permission := Borrowed;
return Selected_C;
end;
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with
@@ -5454,17 +4153,12 @@ package body Sem_SPARK is
Hashtbl : Perm_Tree_Maps.Instance;
- -- We are in Move or Super_Move mode, hence we can assume
- -- that the Children_permission is RW, given that there
- -- are no other paths that could have been moved.
-
- pragma Assert (Children_Permission (C) = Read_Write);
-
- -- We create the unrolled nodes, that will all have RW
- -- permission given that we are in move mode. We will
- -- then set the right node to W.
+ -- We create the unrolled nodes, that will all have same
+ -- permission than parent.
Son : Perm_Tree_Access;
+ ChildrenPerm : constant Perm_Kind :=
+ Children_Permission (C);
begin
-- We change the current node from Entire_Object to
@@ -5472,21 +4166,22 @@ package body Sem_SPARK is
-- hash table as component list.
C.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Component => Hashtbl,
+ (Kind => Record_Component,
+ Is_Node_Deep => Is_Node_Deep (C),
+ Permission => Permission (C),
+ Component => Hashtbl,
Other_Components =>
new Perm_Tree_Wrapper'
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => True,
- Permission => Read_Write,
- Children_Permission => Read_Write)
+ Permission => ChildrenPerm,
+ Children_Permission => ChildrenPerm)
));
-- We fill the hash table with all sons of the record,
-- with basic Entire_Objects nodes.
+
Elem := First_Component_Or_Discriminant
(Etype (Prefix (N)));
@@ -5495,26 +4190,21 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- Perm_Tree_Maps.Set
- (C.all.Tree.Component, Elem, Son);
-
+ Permission => ChildrenPerm,
+ Children_Permission => ChildrenPerm));
+ Perm_Tree_Maps.Set (C.all.Tree.Component, Elem, Son);
Next_Component_Or_Discriminant (Elem);
end loop;
- -- Now we set the right field to Write_Only or No_Access
- -- depending on mode, and then we return the tree to the
- -- sons, so that the recursion can continue.
+ -- Now we set the right field to Borrowed, and then we
+ -- return the tree to the sons, so that the recursion can
+ -- continue.
declare
Selected_Component : constant Entity_Id :=
Entity (Selector_Name (N));
-
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
+ Selected_C : Perm_Tree_Access := Perm_Tree_Maps.Get
+ (Component (C), Selected_Component);
begin
if Selected_C = null then
@@ -5522,22 +4212,11 @@ package body Sem_SPARK is
end if;
pragma Assert (Selected_C /= null);
-
- -- Given that this is a newly created Select_C, we can
- -- safely assume that its permission is Read_Write.
-
- pragma Assert (Permission (Selected_C) =
- Read_Write);
-
- if Mode = Super_Move then
- Selected_C.all.Tree.Permission := No_Access;
- else
- Selected_C.all.Tree.Permission := Write_Only;
- end if;
-
+ Selected_C.all.Tree.Permission := Borrowed;
return Selected_C;
end;
end;
+
else
raise Program_Error;
end if;
@@ -5545,72 +4224,41 @@ package body Sem_SPARK is
-- We set the permission tree of its prefix, and then we extract
-- from the returned pointer the subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
+ -- permission to it, if unfolded. If folded, we unroll the tree in
+ -- one step.
when N_Indexed_Component
| N_Slice
=>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (Prefix (N), Mode);
+ Set_Perm_Prefixes_Borrow (Prefix (N));
begin
if C = null then
+
-- We went through a function call, do nothing
return null;
end if;
- -- The permission of the returned node should be either
- -- W (because the recursive call sets <= Write_Only)
- -- or No (if another path has been moved with 'Access)
-
- if Mode = Super_Move then
- pragma Assert (Permission (C) = No_Access);
- null;
- else
- pragma Assert (Permission (C) = Write_Only
- or else Permission (C) = No_Access);
- null;
- end if;
-
+ pragma Assert (Permission (C) = Borrowed);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Array_Component);
if Kind (C) = Array_Component then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
- if Get_Elem (C) = null then
- -- Hash_Table_Error
- raise Program_Error;
- end if;
-
- -- The Get_Elem can have permissions :
- -- RW : first move in this path
- -- W : Already other moves in this path
- -- No : Already other moves with 'Access
-
- pragma Assert (Permission (Get_Elem (C)) /= Read_Only);
-
- if Mode = Super_Move then
- C.all.Tree.Get_Elem.all.Tree.Permission := No_Access;
- else
- C.all.Tree.Get_Elem.all.Tree.Permission :=
- Glb (Write_Only, Permission (Get_Elem (C)));
- end if;
-
+ pragma Assert (Get_Elem (C) /= null);
+ C.all.Tree.Get_Elem.all.Tree.Permission := Borrowed;
return Get_Elem (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace node with Array_Component.
- -- We are in move mode, hence we can assume that the
- -- Children_permission is RW.
-
- pragma Assert (Children_Permission (C) = Read_Write);
-
Son : Perm_Tree_Access;
begin
@@ -5618,14 +4266,8 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- if Mode = Super_Move then
- Son.all.Tree.Permission := No_Access;
- else
- Son.all.Tree.Permission := Write_Only;
- end if;
+ Permission => Borrowed,
+ Children_Permission => Children_Permission (C)));
-- We change the current node from Entire_Object
-- to Array_Component with same permission and the
@@ -5633,11 +4275,11 @@ package body Sem_SPARK is
C.all.Tree := (Kind => Array_Component,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
+ Permission => Borrowed,
Get_Elem => Son);
-
return Get_Elem (C);
end;
+
else
raise Program_Error;
end if;
@@ -5651,415 +4293,56 @@ package body Sem_SPARK is
when N_Explicit_Dereference =>
declare
C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Move (Prefix (N), Move);
+ Set_Perm_Prefixes_Borrow (Prefix (N));
begin
if C = null then
- -- We went through a function call: do nothing
-
- return null;
- end if;
-
- -- The permission of the returned node should be only
- -- W (because the recursive call sets <= Write_Only)
- -- No is NOT POSSIBLE here
-
- pragma Assert (Permission (C) = Write_Only);
-
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Reference);
-
- if Kind (C) = Reference then
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
-
- if Get_All (C) = null then
- -- Hash_Table_Error
- raise Program_Error;
- end if;
-
- -- The Get_All can have permissions :
- -- RW : first move in this path
- -- W : Already other moves in this path
- -- No : Already other moves with 'Access
-
- pragma Assert (Permission (Get_All (C)) /= Read_Only);
-
- if Mode = Super_Move then
- C.all.Tree.Get_All.all.Tree.Permission := No_Access;
- else
- Get_All (C).all.Tree.Permission :=
- Glb (Write_Only, Permission (Get_All (C)));
- end if;
- return Get_All (C);
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with Reference.
-
- -- We are in Move or Super_Move mode, hence we can assume
- -- that the Children_permission is RW.
-
- pragma Assert (Children_Permission (C) = Read_Write);
-
- Son : Perm_Tree_Access;
-
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
-
- if Mode = Super_Move then
- Son.all.Tree.Permission := No_Access;
- else
- Son.all.Tree.Permission := Write_Only;
- end if;
-
- -- We change the current node from Entire_Object to
- -- Reference with Write_Only and the previous son.
-
- pragma Assert (Is_Node_Deep (C));
-
- C.all.Tree := (Kind => Reference,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Write_Only,
- -- Write_only is equal to C.Permission
- Get_All => Son);
-
- return Get_All (C);
- end;
- else
- raise Program_Error;
- end if;
- end;
-
- when N_Function_Call =>
- return null;
-
- when others =>
- raise Program_Error;
- end case;
-
- end Set_Perm_Prefixes_Move;
-
- -------------------------------
- -- Set_Perm_Prefixes_Observe --
- -------------------------------
-
- function Set_Perm_Prefixes_Observe
- (N : Node_Id)
- return Perm_Tree_Access
- is
- begin
- pragma Assert (Current_Checking_Mode = Observe);
-
- case Nkind (N) is
- -- Base identifier. Set permission to R.
-
- when N_Identifier
- | N_Expanded_Name
- | N_Defining_Identifier
- =>
- declare
- P : Node_Id;
- C : Perm_Tree_Access;
-
- begin
- if Nkind (N) = N_Defining_Identifier then
- P := N;
- else
- P := Entity (N);
- end if;
-
- C := Get (Current_Perm_Env, Unique_Entity (P));
- -- Setting the initialization map to True, so that this
- -- variable cannot be ignored anymore when looking at end
- -- of elaboration of package.
-
- Set (Current_Initialization_Map, Unique_Entity (P), True);
-
- if C = null then
- -- No null possible here, there are no parents for the path.
- -- This means we are using a global variable without adding
- -- it in environment with a global aspect.
-
- Illegal_Global_Usage (N);
- end if;
-
- C.all.Tree.Permission := Glb (Read_Only, Permission (C));
-
- return C;
- end;
-
- when N_Type_Conversion
- | N_Unchecked_Type_Conversion
- | N_Qualified_Expression
- =>
- return Set_Perm_Prefixes_Observe (Expression (N));
-
- when N_Parameter_Specification =>
- raise Program_Error;
-
- -- We set the permission tree of its prefix, and then we extract
- -- from the returned pointer our subtree and assign an adequate
- -- permission to it, if unfolded. If folded, we unroll the tree
- -- at one step.
-
- when N_Selected_Component =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (Prefix (N));
-
- begin
- if C = null then
- -- We went through a function call, do nothing
-
- return null;
- end if;
-
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Record_Component);
-
- if Kind (C) = Record_Component then
- -- The tree is unfolded. We just modify the permission and
- -- return the record subtree. We put the permission to the
- -- glb of read_only and its current permission, to consider
- -- the case of observing x.y while x.z has been moved. Then
- -- x should be No_Access.
-
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
-
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
-
- begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
- end if;
-
- pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission :=
- Glb (Read_Only, Permission (Selected_C));
-
- return Selected_C;
- end;
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace the node with
- -- Record_Component.
-
- Elem : Node_Id;
-
- -- Create an empty hash table
-
- Hashtbl : Perm_Tree_Maps.Instance;
-
- -- We create the unrolled nodes, that will all have RW
- -- permission given that we are in move mode. We will
- -- then set the right node to W.
-
- Son : Perm_Tree_Access;
-
- Child_Perm : constant Perm_Kind :=
- Children_Permission (C);
-
- begin
- -- We change the current node from Entire_Object to
- -- Record_Component with same permission and an empty
- -- hash table as component list.
- C.all.Tree :=
- (Kind => Record_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Permission (C),
- Component => Hashtbl,
- Other_Components =>
- new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => True,
- Permission => Child_Perm,
- Children_Permission => Child_Perm)
- ));
-
- -- We fill the hash table with all sons of the record,
- -- with basic Entire_Objects nodes.
- Elem := First_Component_Or_Discriminant
- (Etype (Prefix (N)));
-
- while Present (Elem) loop
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Deep (Etype (Elem)),
- Permission => Child_Perm,
- Children_Permission => Child_Perm));
-
- Perm_Tree_Maps.Set
- (C.all.Tree.Component, Elem, Son);
-
- Next_Component_Or_Discriminant (Elem);
- end loop;
-
- -- Now we set the right field to Read_Only. and then we
- -- return the tree to the sons, so that the recursion can
- -- continue.
-
- declare
- Selected_Component : constant Entity_Id :=
- Entity (Selector_Name (N));
-
- Selected_C : Perm_Tree_Access :=
- Perm_Tree_Maps.Get
- (Component (C), Selected_Component);
-
- begin
- if Selected_C = null then
- Selected_C := Other_Components (C);
- end if;
-
- pragma Assert (Selected_C /= null);
-
- Selected_C.all.Tree.Permission :=
- Glb (Read_Only, Child_Perm);
-
- return Selected_C;
- end;
- end;
- else
- raise Program_Error;
- end if;
- end;
-
- -- We set the permission tree of its prefix, and then we extract from
- -- the returned pointer the subtree and assign an adequate permission
- -- to it, if unfolded. If folded, we unroll the tree at one step.
-
- when N_Indexed_Component
- | N_Slice
- =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (Prefix (N));
-
- begin
- if C = null then
- -- We went through a function call, do nothing
+ -- We went through a function call. Do nothing.
return null;
end if;
- pragma Assert (Kind (C) = Entire_Object
- or else Kind (C) = Array_Component);
-
- if Kind (C) = Array_Component then
- -- The tree is unfolded. We just modify the permission and
- -- return the elem subtree.
-
- pragma Assert (Get_Elem (C) /= null);
-
- C.all.Tree.Get_Elem.all.Tree.Permission :=
- Glb (Read_Only, Permission (Get_Elem (C)));
-
- return Get_Elem (C);
- elsif Kind (C) = Entire_Object then
- declare
- -- Expand the tree. Replace node with Array_Component.
-
- Son : Perm_Tree_Access;
-
- Child_Perm : constant Perm_Kind :=
- Glb (Read_Only, Children_Permission (C));
-
- begin
- Son := new Perm_Tree_Wrapper'
- (Tree =>
- (Kind => Entire_Object,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Child_Perm,
- Children_Permission => Child_Perm));
-
- -- We change the current node from Entire_Object
- -- to Array_Component with same permission and the
- -- previously defined son.
-
- C.all.Tree := (Kind => Array_Component,
- Is_Node_Deep => Is_Node_Deep (C),
- Permission => Child_Perm,
- Get_Elem => Son);
-
- return Get_Elem (C);
- end;
-
- else
- raise Program_Error;
- end if;
- end;
-
- -- We set the permission tree of its prefix, and then we extract from
- -- the returned pointer the subtree and assign an adequate permission
- -- to it, if unfolded. If folded, we unroll the tree at one step.
-
- when N_Explicit_Dereference =>
- declare
- C : constant Perm_Tree_Access :=
- Set_Perm_Prefixes_Observe (Prefix (N));
-
- begin
- if C = null then
- -- We went through a function call, do nothing
-
- return null;
- end if;
+ -- The permission of the returned node should be No
+ pragma Assert (Permission (C) = Borrowed);
pragma Assert (Kind (C) = Entire_Object
or else Kind (C) = Reference);
if Kind (C) = Reference then
+
-- The tree is unfolded. We just modify the permission and
-- return the elem subtree.
pragma Assert (Get_All (C) /= null);
-
- C.all.Tree.Get_All.all.Tree.Permission :=
- Glb (Read_Only, Permission (Get_All (C)));
-
+ C.all.Tree.Get_All.all.Tree.Permission := Borrowed;
return Get_All (C);
+
elsif Kind (C) = Entire_Object then
declare
-- Expand the tree. Replace the node with Reference.
Son : Perm_Tree_Access;
- Child_Perm : constant Perm_Kind :=
- Glb (Read_Only, Children_Permission (C));
-
begin
Son := new Perm_Tree_Wrapper'
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (N)),
- Permission => Child_Perm,
- Children_Permission => Child_Perm));
+ Permission => Borrowed,
+ Children_Permission => Children_Permission (C)));
-- We change the current node from Entire_Object to
- -- Reference with Write_Only and the previous son.
+ -- Reference with Borrowed and the previous son.
pragma Assert (Is_Node_Deep (C));
-
C.all.Tree := (Kind => Reference,
Is_Node_Deep => Is_Node_Deep (C),
- Permission => Child_Perm,
+ Permission => Borrowed,
Get_All => Son);
-
return Get_All (C);
end;
+
else
raise Program_Error;
end if;
@@ -6070,16 +4353,14 @@ package body Sem_SPARK is
when others =>
raise Program_Error;
-
end case;
- end Set_Perm_Prefixes_Observe;
+ end Set_Perm_Prefixes_Borrow;
-------------------
-- Setup_Globals --
-------------------
procedure Setup_Globals (Subp : Entity_Id) is
-
procedure Setup_Globals_From_List
(First_Item : Node_Id;
Kind : Formal_Kind);
@@ -6123,12 +4404,17 @@ package body Sem_SPARK is
begin
case Global_Mode is
- when Name_Input | Name_Proof_In =>
+ when Name_Input
+ | Name_Proof_In
+ =>
Kind := E_In_Parameter;
+
when Name_Output =>
Kind := E_Out_Parameter;
+
when Name_In_Out =>
Kind := E_In_Out_Parameter;
+
when others =>
raise Program_Error;
end case;
@@ -6165,36 +4451,57 @@ package body Sem_SPARK is
(Tree =>
(Kind => Entire_Object,
Is_Node_Deep => Is_Deep (Etype (Id)),
- Permission => Read_Write,
- Children_Permission => Read_Write));
+ Permission => Unrestricted,
+ Children_Permission => Unrestricted));
case Mode is
- when E_In_Parameter =>
- -- Borrowed IN: RW for everybody
+ -- All out and in out parameters are considered to be unrestricted.
+ -- They are whether borrowed or moved. Ada Rules would restrict
+ -- these permissions further. For example an in parameter cannot
+ -- be written.
- if Is_Borrowed_In (Id) and not Global_Var then
- Elem.all.Tree.Permission := Read_Write;
- Elem.all.Tree.Children_Permission := Read_Write;
+ -- In the following we deal with in parameters that can be observed.
+ -- We only consider the observing cases.
- -- Observed IN: R for everybody
+ when E_In_Parameter =>
- else
- Elem.all.Tree.Permission := Read_Only;
- Elem.all.Tree.Children_Permission := Read_Only;
- end if;
+ -- Handling global variables as in parameters here
+ -- Remove the following condition once decided how globals
+ -- should be considered.
+
+ if not Global_Var then
+ if (Is_Access_Type (Etype (Id))
+ and then Is_Access_Constant (Etype (Id))
+ and then Is_Anonymous_Access_Type (Etype (Id)))
+ or else
+ (not Is_Access_Type (Etype (Id))
+ and then Is_Deep (Etype (Id))
+ and then not Is_Anonymous_Access_Type (Etype (Id)))
+ then
+ Elem.all.Tree.Permission := Observed;
+ Elem.all.Tree.Children_Permission := Observed;
- -- OUT: borrow, but callee has W only
+ else
+ Elem.all.Tree.Permission := Unrestricted;
+ Elem.all.Tree.Children_Permission := Unrestricted;
+ end if;
- when E_Out_Parameter =>
- Elem.all.Tree.Permission := Write_Only;
- Elem.all.Tree.Children_Permission := Write_Only;
+ else
+ Elem.all.Tree.Permission := Observed;
+ Elem.all.Tree.Children_Permission := Observed;
+ end if;
- -- IN OUT: borrow and callee has RW
+ -- When out or in/out formal or global parameters, we set them to
+ -- the Unrestricted state. "We want to be able to assume that all
+ -- relevant writable globals are unrestricted when a subprogram
+ -- starts executing". Formal parameters of mode out or in/out
+ -- are whether Borrowers or the targets of a move operation:
+ -- they start theirs lives in the subprogram as Unrestricted.
- when E_In_Out_Parameter =>
- Elem.all.Tree.Permission := Read_Write;
- Elem.all.Tree.Children_Permission := Read_Write;
+ when others =>
+ Elem.all.Tree.Permission := Unrestricted;
+ Elem.all.Tree.Children_Permission := Unrestricted;
end case;
Set (Current_Perm_Env, Id, Elem);
@@ -6204,9 +4511,7 @@ package body Sem_SPARK is
-- Setup_Parameters --
----------------------
- procedure Setup_Parameters (Subp : Entity_Id) is
- Formal : Entity_Id;
-
+ procedure Setup_Parameters (Subp : Entity_Id) is Formal : Entity_Id;
begin
Formal := First_Formal (Subp);
while Present (Formal) loop
@@ -6216,4 +4521,85 @@ package body Sem_SPARK is
end loop;
end Setup_Parameters;
+ -------------------------------
+ -- Has_Ownership_Aspect_True --
+ -------------------------------
+
+ function Has_Ownership_Aspect_True
+ (N : Entity_Id;
+ Msg : String)
+ return Boolean
+ is
+ begin
+ case Ekind (Etype (N)) is
+ when Access_Kind =>
+ if Ekind (Etype (N)) = E_General_Access_Type then
+ Error_Msg_NE (Msg & " & not allowed " &
+ "(Named General Access type)", N, N);
+ return False;
+
+ else
+ return True;
+ end if;
+
+ when E_Array_Type
+ | E_Array_Subtype
+ =>
+ declare
+ Com_Ty : constant Node_Id := Component_Type (Etype (N));
+ Ret : Boolean := Has_Ownership_Aspect_True (Com_Ty, "");
+
+ begin
+ if Nkind (Parent (N)) = N_Full_Type_Declaration and
+ Is_Anonymous_Access_Type (Com_Ty)
+ then
+ Ret := False;
+ end if;
+
+ if not Ret then
+ Error_Msg_NE (Msg & " & not allowed "
+ & "(Components of Named General Access type or"
+ & " Anonymous type)", N, N);
+ end if;
+ return Ret;
+ end;
+
+ -- ??? What about hidden components
+
+ when E_Record_Type
+ | E_Record_Subtype
+ =>
+ declare
+ Elmt : Entity_Id;
+ Elmt_T_Perm : Boolean := True;
+ Elmt_Perm, Elmt_Anonym : Boolean;
+
+ begin
+ Elmt := First_Component_Or_Discriminant (Etype (N));
+ while Present (Elmt) loop
+ Elmt_Perm := Has_Ownership_Aspect_True (Elmt,
+ "type of component");
+ Elmt_Anonym := Is_Anonymous_Access_Type (Etype (Elmt));
+ if Elmt_Anonym then
+ Error_Msg_NE
+ ("type of component & not allowed"
+ & " (Components of Anonymous type)", Elmt, Elmt);
+ end if;
+ Elmt_T_Perm := Elmt_T_Perm and Elmt_Perm and not Elmt_Anonym;
+ Next_Component_Or_Discriminant (Elmt);
+ end loop;
+ if not Elmt_T_Perm then
+ Error_Msg_NE
+ (Msg & " & not allowed (One or "
+ & "more components have Ownership Aspect False)",
+ N, N);
+ end if;
+ return Elmt_T_Perm;
+ end;
+
+ when others =>
+ return True;
+ end case;
+
+ end Has_Ownership_Aspect_True;
end Sem_SPARK;
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index bfa2b4f..2b31cf7 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -20997,7 +20997,7 @@ package body Sem_Util is
Sloc_Value : Source_Ptr;
Related_Id : Entity_Id;
Suffix : Character;
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Prefix : Character := ' ') return Entity_Id
is
N : constant Entity_Id :=
@@ -24039,6 +24039,14 @@ package body Sem_Util is
and then Outer = Protected_Body_Subprogram (Curr)
then
return True;
+
+ -- Outside of its scope, a synchronized type may just be private
+
+ elsif Is_Private_Type (Curr)
+ and then Present (Full_View (Curr))
+ and then Is_Concurrent_Type (Full_View (Curr))
+ then
+ return Scope_Within (Full_View (Curr), Outer);
end if;
end loop;
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index aec3644..74d670d 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -2326,7 +2326,7 @@ package Sem_Util is
Sloc_Value : Source_Ptr;
Related_Id : Entity_Id;
Suffix : Character;
- Suffix_Index : Nat := 0;
+ Suffix_Index : Int := 0;
Prefix : Character := ' ') return Entity_Id;
-- This function creates an N_Defining_Identifier node for an internal
-- created entity, such as an implicit type or subtype, or a record
diff --git a/gcc/ada/set_targ.adb b/gcc/ada/set_targ.adb
index 0340ee6..4c717c5 100755
--- a/gcc/ada/set_targ.adb
+++ b/gcc/ada/set_targ.adb
@@ -917,6 +917,9 @@ begin
Get_Back_End_Config_File;
begin
if Back_End_Config_File /= null then
+ pragma Gnat_Annotate
+ (CodePeer, Intentional, "test always false",
+ "some variant body will return non null");
Read_Target_Dependent_Values (Back_End_Config_File.all);
-- Otherwise we get all values from the back end directly
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index ae29661..1359c94 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -4674,7 +4674,7 @@ package Sinfo is
--------------------------
-- 4.5.7 If Expression --
- ----------------------------
+ --------------------------
-- IF_EXPRESSION ::=
-- if CONDITION then DEPENDENT_EXPRESSION
diff --git a/gcc/ada/sprint.adb b/gcc/ada/sprint.adb
index f19629c..ab7eecb 100644
--- a/gcc/ada/sprint.adb
+++ b/gcc/ada/sprint.adb
@@ -3540,15 +3540,14 @@ package body Sprint is
-- where the aspects are printed inside the package specification.
if Has_Aspects (Node)
- and then not Nkind_In (Node, N_Package_Declaration,
- N_Generic_Package_Declaration)
+ and then not Nkind_In (Node, N_Generic_Package_Declaration,
+ N_Package_Declaration)
+ and then not Is_Empty_List (Aspect_Specifications (Node))
then
Sprint_Aspect_Specifications (Node, Semicolon => True);
end if;
- if Nkind (Node) in N_Subexpr
- and then Do_Range_Check (Node)
- then
+ if Nkind (Node) in N_Subexpr and then Do_Range_Check (Node) then
Write_Str ("}");
end if;
diff --git a/gcc/ada/terminals.c b/gcc/ada/terminals.c
index 7025f57..bd2cdd0 100644
--- a/gcc/ada/terminals.c
+++ b/gcc/ada/terminals.c
@@ -1107,14 +1107,6 @@ __gnat_setup_winsize (void *desc, int rows, int columns)
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-
-/* On some system termio is either absent or including it will disable termios
- (HP-UX) */
-#if !defined (__hpux__) && !defined (BSD) && !defined (__APPLE__) \
- && !defined (__rtems__) && !defined (__QNXNTO__)
-# include <termio.h>
-#endif
-
#include <sys/ioctl.h>
#include <termios.h>
#include <fcntl.h>
@@ -1130,7 +1122,6 @@ __gnat_setup_winsize (void *desc, int rows, int columns)
# include <sys/signal.h>
#endif
#if defined (__hpux__)
-# include <sys/termio.h>
# include <sys/stropts.h>
#endif
diff --git a/gcc/ada/vxlink-bind.adb b/gcc/ada/vxlink-bind.adb
new file mode 100644
index 0000000..9f45694
--- /dev/null
+++ b/gcc/ada/vxlink-bind.adb
@@ -0,0 +1,390 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . B I N D --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Text_IO; use Ada.Text_IO;
+with Ada.IO_Exceptions;
+with Ada.Strings.Fixed;
+
+with GNAT.Regpat; use GNAT.Regpat;
+
+package body VxLink.Bind is
+
+ function Split_Lines (S : String) return Strings_List.Vector;
+
+ function Split (S : String; C : Character) return Strings_List.Vector;
+
+ function Parse_Nm_Output (S : String) return Symbol_Sets.Set;
+
+ procedure Emit_Module_Dtor
+ (FP : File_Type);
+
+ procedure Emit_CDtor
+ (FP : File_Type;
+ Var : String;
+ Set : Symbol_Sets.Set);
+
+ -----------------
+ -- Split_Lines --
+ -----------------
+
+ function Split_Lines (S : String) return Strings_List.Vector
+ is
+ Last : Natural := S'First;
+ Ret : Strings_List.Vector;
+ begin
+ for J in S'Range loop
+ if S (J) = ASCII.CR
+ and then J < S'Last
+ and then S (J + 1) = ASCII.LF
+ then
+ Ret.Append (S (Last .. J - 1));
+ Last := J + 2;
+ elsif S (J) = ASCII.LF then
+ Ret.Append (S (Last .. J - 1));
+ Last := J + 1;
+ end if;
+ end loop;
+
+ if Last <= S'Last then
+ Ret.Append (S (Last .. S'Last));
+ end if;
+
+ return Ret;
+ end Split_Lines;
+
+ -----------
+ -- Split --
+ -----------
+
+ function Split (S : String; C : Character) return Strings_List.Vector
+ is
+ Last : Natural := S'First;
+ Ret : Strings_List.Vector;
+ begin
+ for J in S'Range loop
+ if S (J) = C then
+ if J > Last then
+ Ret.Append (S (Last .. J - 1));
+ end if;
+
+ Last := J + 1;
+ end if;
+ end loop;
+
+ if Last <= S'Last then
+ Ret.Append (S (Last .. S'Last));
+ end if;
+
+ return Ret;
+ end Split;
+
+ ---------------------
+ -- Parse_Nm_Output --
+ ---------------------
+
+ function Parse_Nm_Output (S : String) return Symbol_Sets.Set
+ is
+ Nm_Regexp : constant Pattern_Matcher :=
+ Compile ("^[0-9A-Za-z]* ([a-zA-Z]) (.*)$");
+ type CDTor_Type is
+ (CTOR_Diab,
+ CTOR_Gcc,
+ DTOR_Diab,
+ DTOR_Gcc);
+ subtype CTOR_Type is CDTor_Type range CTOR_Diab .. CTOR_Gcc;
+ CTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?STI__*([0-9]+)_");
+ CTOR_GCC_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?GLOBAL_.I._*([0-9]+)_");
+ DTOR_DIAB_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?STD__*([0-9]+)_");
+ DTOR_GCC_Regexp : aliased constant Pattern_Matcher :=
+ Compile ("^__?GLOBAL_.D._*([0-9]+)_");
+ type Regexp_Access is access constant Pattern_Matcher;
+ CDTor_Regexps : constant array (CDTor_Type) of Regexp_Access :=
+ (CTOR_Diab => CTOR_DIAB_Regexp'Access,
+ CTOR_Gcc => CTOR_GCC_Regexp'Access,
+ DTOR_Diab => DTOR_DIAB_Regexp'Access,
+ DTOR_Gcc => DTOR_GCC_Regexp'Access);
+ Result : Symbol_Sets.Set;
+
+ begin
+ for Line of Split_Lines (S) loop
+ declare
+ Sym : Symbol;
+ Nm_Grps : Match_Array (0 .. 2);
+ Ctor_Grps : Match_Array (0 .. 1);
+ begin
+ Match (Nm_Regexp, Line, Nm_Grps);
+
+ if Nm_Grps (0) /= No_Match then
+ declare
+ Sym_Type : constant Character :=
+ Line (Nm_Grps (1).First);
+ Sym_Name : constant String :=
+ Line (Nm_Grps (2).First .. Nm_Grps (2).Last);
+ begin
+ Sym :=
+ (Name => To_Unbounded_String (Sym_Name),
+ Cat => Sym_Type,
+ Internal => False,
+ Kind => Sym_Other,
+ Priority => -1);
+
+ for J in CDTor_Regexps'Range loop
+ Match (CDTor_Regexps (J).all, Sym_Name, Ctor_Grps);
+
+ if Ctor_Grps (0) /= No_Match then
+ if J in CTOR_Type then
+ Sym.Kind := Sym_Ctor;
+ else
+ Sym.Kind := Sym_Dtor;
+ end if;
+
+ Sym.Priority := Integer'Value
+ (Line (Ctor_Grps (1).First .. Ctor_Grps (1).Last));
+
+ exit;
+ end if;
+ end loop;
+
+ Result.Include (Sym);
+ end;
+ end if;
+ end;
+ end loop;
+
+ return Result;
+ end Parse_Nm_Output;
+
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize
+ (Binder : out VxLink_Binder;
+ Object_File : String)
+ is
+ Args : Arguments_List;
+ Module_Dtor_Not_Needed : Boolean := False;
+ Module_Dtor_Needed : Boolean := False;
+
+ begin
+ Args.Append (Nm);
+ Args.Append (Object_File);
+
+ declare
+ Output : constant String := Run (Args);
+ Symbols : Symbol_Sets.Set;
+ begin
+ if Is_Error_State then
+ return;
+ end if;
+
+ Symbols := Parse_Nm_Output (Output);
+
+ for Sym of Symbols loop
+ if Sym.Kind = Sym_Ctor then
+ Binder.Constructors.Insert (Sym);
+ elsif Sym.Kind = Sym_Dtor then
+ Binder.Destructors.Insert (Sym);
+ elsif Match ("_?__.*_atexit$", To_String (Sym.Name)) then
+ if Sym.Cat = 'T' then
+ Module_Dtor_Not_Needed := True;
+ elsif Sym.Cat = 'U' then
+ Module_Dtor_Needed := True;
+ end if;
+ end if;
+ end loop;
+
+ Binder.Module_Dtor_Needed :=
+ not Module_Dtor_Not_Needed and then Module_Dtor_Needed;
+ end;
+ end Initialize;
+
+ --------------------
+ -- Parse_Tag_File --
+ --------------------
+
+ procedure Parse_Tag_File
+ (Binder : in out VxLink_Binder;
+ File : String)
+ is
+ FP : Ada.Text_IO.File_Type;
+
+ begin
+ Open
+ (FP,
+ Mode => In_File,
+ Name => File);
+ loop
+ declare
+ Line : constant String :=
+ Ada.Strings.Fixed.Trim
+ (Get_Line (FP), Ada.Strings.Both);
+ Tokens : Strings_List.Vector;
+
+ begin
+ if Line'Length = 0 then
+ -- Skip empty lines
+ null;
+
+ elsif Line (Line'First) = '#' then
+ -- Skip comment
+ null;
+
+ else
+ Tokens := Split (Line, ' ');
+ if Tokens.First_Element = "section" then
+ -- Sections are not used for tags, only when building
+ -- kernels. So skip for now
+ null;
+ else
+ Binder.Tags_List.Append (Line);
+ end if;
+ end if;
+ end;
+ end loop;
+
+ exception
+ when Ada.IO_Exceptions.End_Error =>
+ Close (FP);
+ when others =>
+ Log_Error ("Cannot open file " & File &
+ ". DKM tags won't be generated");
+ end Parse_Tag_File;
+
+ ----------------------
+ -- Emit_Module_Dtor --
+ ----------------------
+
+ procedure Emit_Module_Dtor
+ (FP : File_Type)
+ is
+ Dtor_Name : constant String := "_GLOBAL__D_65536_0_cxa_finalize";
+ begin
+ Put_Line (FP, "extern void __cxa_finalize(void *);");
+ Put_Line (FP, "static void " & Dtor_Name & "()");
+ Put_Line (FP, "{");
+ Put_Line (FP, " __cxa_finalize(&__dso_handle);");
+ Put_Line (FP, "}");
+ Put_Line (FP, "");
+ end Emit_Module_Dtor;
+
+ ----------------
+ -- Emit_CDtor --
+ ----------------
+
+ procedure Emit_CDtor
+ (FP : File_Type;
+ Var : String;
+ Set : Symbol_Sets.Set)
+ is
+ begin
+ for Sym of Set loop
+ if not Sym.Internal then
+ Put_Line (FP, "extern void " & To_String (Sym.Name) & "();");
+ end if;
+ end loop;
+
+ New_Line (FP);
+
+ Put_Line (FP, "extern void (*" & Var & "[])();");
+ Put_Line (FP, "void (*" & Var & "[])() =");
+ Put_Line (FP, " {");
+ for Sym of Set loop
+ Put_Line (FP, " " & To_String (Sym.Name) & ",");
+ end loop;
+ Put_Line (FP, " 0};");
+ New_Line (FP);
+ end Emit_CDtor;
+
+ ---------------
+ -- Emit_CTDT --
+ ---------------
+
+ procedure Emit_CTDT
+ (Binder : in out VxLink_Binder;
+ Namespace : String)
+ is
+ FP : Ada.Text_IO.File_Type;
+ CDtor_File : constant String := Namespace & "-cdtor.c";
+ begin
+ Binder.CTDT_File := To_Unbounded_String (CDtor_File);
+ Create
+ (File => FP,
+ Name => CDtor_File);
+ Put_Line (FP, "#if defined(_HAVE_TOOL_XTORS)");
+ Put_Line (FP, "#include <vxWorks.h>");
+ if Binder.Module_Dtor_Needed then
+ Put_Line (FP, "#define _WRS_NEED_CALL_CXA_FINALIZE");
+ end if;
+ Put_Line (FP, "#include TOOL_HEADER (toolXtors.h)");
+ Put_Line (FP, "#else");
+ Put_Line (FP, "");
+
+ if Binder.Module_Dtor_Needed then
+ Emit_Module_Dtor (FP);
+ end if;
+
+ Emit_CDtor (FP, "_ctors", Binder.Constructors);
+ Emit_CDtor (FP, "_dtors", Binder.Destructors);
+
+ Put_Line (FP, "#endif");
+
+ if not Binder.Tags_List.Is_Empty then
+ New_Line (FP);
+ Put_Line (FP, "/* build variables */");
+ Put_Line (FP, "__asm("" .section \"".wrs_build_vars\"",\""a\"""");");
+ for Tag of Binder.Tags_List loop
+ Put_Line (FP, "__asm("" .ascii \""" & Tag & "\"""");");
+ Put_Line (FP, "__asm("" .byte 0"");");
+ end loop;
+ Put_Line (FP, "__asm("" .ascii \""end\"""");");
+ Put_Line (FP, "__asm("" .byte 0"");");
+ end if;
+
+ Close (FP);
+
+ exception
+ when others =>
+ Close (FP);
+ Set_Error_State ("Internal error");
+ raise;
+ end Emit_CTDT;
+
+ ---------------
+ -- CTDT_File --
+ ---------------
+
+ function CTDT_File (Binder : VxLink_Binder) return String
+ is
+ begin
+ return To_String (Binder.CTDT_File);
+ end CTDT_File;
+
+end VxLink.Bind;
diff --git a/gcc/ada/vxlink-bind.ads b/gcc/ada/vxlink-bind.ads
new file mode 100644
index 0000000..7e6a1b0
--- /dev/null
+++ b/gcc/ada/vxlink-bind.ads
@@ -0,0 +1,87 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . B I N D --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+private with Ada.Containers.Ordered_Sets;
+private with Ada.Strings.Unbounded;
+
+package VxLink.Bind is
+
+ type VxLink_Binder is private;
+
+ procedure Initialize
+ (Binder : out VxLink_Binder;
+ Object_File : String);
+
+ procedure Parse_Tag_File
+ (Binder : in out VxLink_Binder;
+ File : String);
+
+ procedure Emit_CTDT
+ (Binder : in out VxLink_Binder;
+ Namespace : String);
+
+ function CTDT_File (Binder : VxLink_Binder) return String;
+
+private
+
+ use Ada.Strings.Unbounded;
+
+ type Symbol_Kind is (Sym_Ctor, Sym_Dtor, Sym_Other);
+
+ type Symbol is record
+ Name : Unbounded_String;
+ Cat : Character;
+ Internal : Boolean;
+ Kind : Symbol_Kind;
+ Priority : Integer;
+ end record;
+
+ function "=" (S1, S2 : Symbol) return Boolean
+ is (S1.Name = S2.Name and then S1.Cat = S2.Cat);
+
+ function "<" (S1, S2 : Symbol) return Boolean
+ is (if S1.Priority /= S2.Priority
+ then S1.Priority < S2.Priority
+ elsif S1.Name /= S2.Name
+ then S1.Name < S2.Name
+ else S1.Cat < S2.Cat);
+
+ package Symbol_Sets is new Ada.Containers.Ordered_Sets
+ (Symbol,
+ "<" => "<",
+ "=" => "=");
+
+ type VxLink_Binder is record
+ CTDT_File : Unbounded_String;
+ Constructors : Symbol_Sets.Set;
+ Destructors : Symbol_Sets.Set;
+ Module_Dtor_Needed : Boolean;
+ EH_Frame_Needed : Boolean;
+ Tags_List : Strings_List.Vector;
+ end record;
+
+end VxLink.Bind;
diff --git a/gcc/ada/vxlink-link.adb b/gcc/ada/vxlink-link.adb
new file mode 100644
index 0000000..5211074
--- /dev/null
+++ b/gcc/ada/vxlink-link.adb
@@ -0,0 +1,194 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . L I N K --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Command_Line; use Ada.Command_Line;
+with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+
+package body VxLink.Link is
+
+ Gcc : constant String := VxLink.Gcc;
+
+ ----------------
+ -- Initialize --
+ ----------------
+
+ procedure Initialize
+ (Linker : out VxLink_Linker)
+ is
+ Leading : Boolean := True;
+ Next_Is_Object : Boolean := False;
+
+ begin
+ for J in 1 .. Ada.Command_Line.Argument_Count loop
+ declare
+ Arg : String renames Argument (J);
+ begin
+ if Next_Is_Object then
+ Next_Is_Object := False;
+ Linker.Dest_Object := To_Unbounded_String (Arg);
+ Leading := False;
+
+ elsif Argument (J) = "-o" then
+ Next_Is_Object := True;
+
+ elsif Argument (J) = "-noauto-register" then
+ -- Filter out this argument, and do not generate _ctors/_dtors
+ Linker.Add_CDtors := False;
+ elsif Arg = "-v" and then not Is_Verbose then
+ -- first -v means VxLink should be verbose, two -v passes -v to
+ -- the linker.
+ Set_Verbose (True);
+ else
+ if Arg = "-nostdlib" or Arg = "-nostartfiles" then
+ Linker.Add_CDtors := False;
+ end if;
+
+ if Leading then
+ Linker.Args_Leading.Append (Arg);
+ else
+ Linker.Args_Trailing.Append (Arg);
+ end if;
+ end if;
+ end;
+ end loop;
+
+ if Linker.Dest_Object = Null_Unbounded_String then
+ Set_Error_State ("no output object is defined");
+ elsif Linker.Add_CDtors then
+ -- We'll need to create intermediate artefacts, so we'll use the
+ -- destination object as base namespace just in case we have
+ -- several link operations in the same directory
+ declare
+ Obj : constant String :=
+ Base_Name (To_String (Linker.Dest_Object));
+
+ begin
+ for J in reverse Obj'Range loop
+ if Obj (J) = '.' then
+ Linker.Dest_Base :=
+ To_Unbounded_String (Obj (Obj'First .. J - 1));
+ exit;
+ end if;
+ end loop;
+
+ Linker.Partial_Obj := Linker.Dest_Base & "-partial.o";
+ end;
+ end if;
+ end Initialize;
+
+ -----------------
+ -- Needs_CDtor --
+ -----------------
+
+ function Needs_CDtor (Linker : VxLink_Linker) return Boolean is
+ begin
+ return Linker.Add_CDtors;
+ end Needs_CDtor;
+
+ --------------------
+ -- Partial_Object --
+ --------------------
+
+ function Partial_Object (Linker : VxLink_Linker) return String is
+ begin
+ return To_String (Linker.Partial_Obj);
+ end Partial_Object;
+
+ ---------------
+ -- Namespace --
+ ---------------
+
+ function Namespace (Linker : VxLink_Linker) return String is
+ begin
+ return To_String (Linker.Dest_Base);
+ end Namespace;
+
+ ---------------------
+ -- Do_Initial_Link --
+ ---------------------
+
+ procedure Do_Initial_Link (Linker : VxLink_Linker)
+ is
+ Args : Arguments_List;
+ Gxx_Path : constant String := Gxx;
+ begin
+ if Is_Error_State then
+ return;
+ end if;
+
+ if Gxx_Path'Length /= 0 then
+ Args.Append (Gxx);
+ else
+ Args.Append (Gcc);
+ end if;
+ Args.Append (Linker.Args_Leading);
+ Args.Append ("-o");
+
+ if Linker.Add_CDtors then
+ Args.Append (To_String (Linker.Partial_Obj));
+ else
+ Args.Append (To_String (Linker.Dest_Object));
+ end if;
+
+ Args.Append (Linker.Args_Trailing);
+
+ if not Linker.Add_CDtors then
+ Args.Append ("-nostartfiles");
+ end if;
+
+ Run (Args);
+ end Do_Initial_Link;
+
+ -------------------
+ -- Do_Final_Link --
+ -------------------
+
+ procedure Do_Final_Link
+ (Linker : VxLink_Linker;
+ Ctdt_Obj : String)
+ is
+ Args : Arguments_List;
+ begin
+ if not Linker.Add_CDtors then
+ return;
+ end if;
+
+ if Is_Error_State then
+ return;
+ end if;
+
+ Args.Append (Gcc);
+ Args.Append ("-nostdlib");
+ Args.Append (Ctdt_Obj);
+ Args.Append (To_String (Linker.Partial_Obj));
+ Args.Append ("-o");
+ Args.Append (To_String (Linker.Dest_Object));
+
+ Run (Args);
+ end Do_Final_Link;
+
+end VxLink.Link;
diff --git a/gcc/ada/vxlink-link.ads b/gcc/ada/vxlink-link.ads
new file mode 100644
index 0000000..4c46f48
--- /dev/null
+++ b/gcc/ada/vxlink-link.ads
@@ -0,0 +1,63 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . L I N K --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+private with Ada.Strings.Unbounded;
+
+package VxLink.Link is
+
+ type VxLink_Linker is private;
+
+ procedure Initialize
+ (Linker : out VxLink_Linker);
+
+ function Needs_CDtor (Linker : VxLink_Linker) return Boolean;
+
+ function Partial_Object (Linker : VxLink_Linker) return String;
+
+ function Namespace (Linker : VxLink_Linker) return String;
+
+ procedure Do_Initial_Link
+ (Linker : VxLink_Linker);
+
+ procedure Do_Final_Link
+ (Linker : VxLink_Linker;
+ Ctdt_Obj : String);
+
+private
+
+ use Ada.Strings.Unbounded;
+
+ type VxLink_Linker is record
+ Args_Leading : Arguments_List;
+ Args_Trailing : Arguments_List;
+ Add_CDtors : Boolean := True;
+ Dest_Object : Unbounded_String;
+ Dest_Base : Unbounded_String;
+ Partial_Obj : Unbounded_String;
+ end record;
+
+end VxLink.Link;
diff --git a/gcc/ada/vxlink-main.adb b/gcc/ada/vxlink-main.adb
new file mode 100644
index 0000000..04a22c3
--- /dev/null
+++ b/gcc/ada/vxlink-main.adb
@@ -0,0 +1,81 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K . M A I N --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- VxLink is a helper tool used as a wrapper around g++/gcc to build VxWorks
+-- DKM (Downloadable Kernel Modules).
+-- Such DKM is a partially linked object that contains entry points for
+-- constructors and destructors. This tool thus uses g++ to generate an
+-- intermediate partially linked object, retrieves the list of constructors
+-- and destructors in it and produces a C file that lists those ctors/dtors
+-- in a way that is understood be VxWorks kernel. It then links this file
+-- with the intermediate object to produce a valid DKM.
+
+pragma Ada_2012;
+
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+
+with VxLink.Link; use VxLink.Link;
+with VxLink.Bind; use VxLink.Bind;
+
+procedure VxLink.Main is
+ Linker : VxLink_Linker;
+ Binder : VxLink_Binder;
+ VSB_Dir : String_Access := Getenv ("VSB_DIR");
+begin
+ Initialize (Linker);
+
+ if Is_Error_State then
+ return;
+ end if;
+
+ Do_Initial_Link (Linker);
+
+ if Is_Error_State then
+ return;
+ end if;
+
+ if not Needs_CDtor (Linker) then
+ -- Initial link is enough, let's return
+ return;
+ end if;
+
+ if VSB_Dir /= null and then VSB_Dir'Length > 0 then
+ declare
+ DKM_Tag_File : constant String :=
+ Normalize_Pathname
+ ("krnl/tags/dkm.tags", VSB_Dir.all);
+ begin
+ if Is_Regular_File (DKM_Tag_File) then
+ Parse_Tag_File (Binder, DKM_Tag_File);
+ end if;
+ end;
+ end if;
+
+ Initialize (Binder, Object_File => Partial_Object (Linker));
+ Emit_CTDT (Binder, Namespace => Namespace (Linker));
+
+ Do_Final_Link (Linker, CTDT_File (Binder));
+ Free (VSB_Dir);
+end VxLink.Main;
diff --git a/gcc/ada/vxlink.adb b/gcc/ada/vxlink.adb
new file mode 100644
index 0000000..400ad22
--- /dev/null
+++ b/gcc/ada/vxlink.adb
@@ -0,0 +1,288 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K --
+-- --
+-- B o d y --
+-- --
+-- Copyright (C) 2018, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+pragma Ada_2012;
+
+with Ada.Command_Line;
+with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
+with Ada.Text_IO;
+
+with GNAT.Directory_Operations; use GNAT.Directory_Operations;
+with GNAT.Expect; use GNAT.Expect;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
+
+package body VxLink is
+
+ Target_Triplet : Unbounded_String := Null_Unbounded_String;
+ Verbose : Boolean := False;
+ Error_State : Boolean := False;
+
+ function Triplet return String;
+
+ function Which (Exe : String) return String;
+
+ -------------
+ -- Triplet --
+ -------------
+
+ function Triplet return String is
+ begin
+ if Target_Triplet = Null_Unbounded_String then
+ declare
+ Exe : constant String := File_Name (Ada.Command_Line.Command_Name);
+ begin
+ for J in reverse Exe'Range loop
+ if Exe (J) = '-' then
+ Target_Triplet := To_Unbounded_String (Exe (Exe'First .. J));
+ exit;
+ end if;
+ end loop;
+ end;
+ end if;
+
+ return To_String (Target_Triplet);
+ end Triplet;
+
+ -----------
+ -- Which --
+ -----------
+
+ function Which (Exe : String) return String
+ is
+ Suffix : GNAT.OS_Lib.String_Access := Get_Executable_Suffix;
+ Basename : constant String := Exe & Suffix.all;
+ Path : GNAT.OS_Lib.String_Access := Getenv ("PATH");
+ Last : Natural := Path'First;
+
+ begin
+ Free (Suffix);
+
+ for J in Path'Range loop
+ if Path (J) = Path_Separator then
+ declare
+ Full : constant String := Normalize_Pathname
+ (Name => Basename,
+ Directory => Path (Last .. J - 1),
+ Resolve_Links => False,
+ Case_Sensitive => True);
+ begin
+ if Is_Executable_File (Full) then
+ Free (Path);
+
+ return Full;
+ end if;
+ end;
+
+ Last := J + 1;
+ end if;
+ end loop;
+
+ Free (Path);
+
+ return "";
+ end Which;
+
+ -----------------
+ -- Set_Verbose --
+ -----------------
+
+ procedure Set_Verbose (Value : Boolean)
+ is
+ begin
+ Verbose := Value;
+ end Set_Verbose;
+
+ ----------------
+ -- Is_Verbose --
+ ----------------
+
+ function Is_Verbose return Boolean
+ is
+ begin
+ return Verbose;
+ end Is_Verbose;
+
+ ---------------------
+ -- Set_Error_State --
+ ---------------------
+
+ procedure Set_Error_State (Message : String)
+ is
+ begin
+ Log_Error ("Error: " & Message);
+ Error_State := True;
+ Ada.Command_Line.Set_Exit_Status (1);
+ end Set_Error_State;
+
+ --------------------
+ -- Is_Error_State --
+ --------------------
+
+ function Is_Error_State return Boolean
+ is
+ begin
+ return Error_State;
+ end Is_Error_State;
+
+ --------------
+ -- Log_Info --
+ --------------
+
+ procedure Log_Info (S : String)
+ is
+ begin
+ if Verbose then
+ Ada.Text_IO.Put_Line (S);
+ end if;
+ end Log_Info;
+
+ ---------------
+ -- Log_Error --
+ ---------------
+
+ procedure Log_Error (S : String)
+ is
+ begin
+ Ada.Text_IO.Put_Line (Ada.Text_IO.Standard_Error, S);
+ end Log_Error;
+
+ ---------
+ -- Run --
+ ---------
+
+ procedure Run (Arguments : Arguments_List)
+ is
+ Output : constant String := Run (Arguments);
+ begin
+ if not Is_Error_State then
+ -- In case of erroneous execution, the function version of run will
+ -- have already displayed the output
+ Ada.Text_IO.Put (Output);
+ end if;
+ end Run;
+
+ ---------
+ -- Run --
+ ---------
+
+ function Run (Arguments : Arguments_List) return String
+ is
+ Args : GNAT.OS_Lib.Argument_List_Access :=
+ new GNAT.OS_Lib.Argument_List
+ (1 .. Natural (Arguments.Length) - 1);
+ Base : constant String := Base_Name (Arguments.First_Element);
+ Status : aliased Integer := 0;
+ Debug_Line : Unbounded_String;
+ Add_Quotes : Boolean;
+
+ begin
+ if Verbose then
+ Append (Debug_Line, Base);
+ end if;
+
+ for J in Arguments.First_Index + 1 .. Arguments.Last_Index loop
+ declare
+ Arg : String renames Arguments.Element (J);
+ begin
+ Args (J - 1) := new String'(Arg);
+
+ if Verbose then
+ Add_Quotes := False;
+
+ for K in Arg'Range loop
+ if Arg (K) = ' ' then
+ Add_Quotes := True;
+ exit;
+ end if;
+ end loop;
+
+ Append (Debug_Line, ' ');
+
+ if Add_Quotes then
+ Append (Debug_Line, '"' & Arg & '"');
+ else
+ Append (Debug_Line, Arg);
+ end if;
+ end if;
+ end;
+ end loop;
+
+ if Verbose then
+ Ada.Text_IO.Put_Line (To_String (Debug_Line));
+ end if;
+
+ declare
+ Ret : constant String :=
+ Get_Command_Output
+ (Command => Arguments.First_Element,
+ Arguments => Args.all,
+ Input => "",
+ Status => Status'Access,
+ Err_To_Out => True);
+ begin
+ GNAT.OS_Lib.Free (Args);
+
+ if Status /= 0 then
+ Ada.Text_IO.Put_Line (Ret);
+ Set_Error_State
+ (Base_Name (Arguments.First_Element) &
+ " returned" & Status'Image);
+ end if;
+
+ return Ret;
+ end;
+ end Run;
+
+ ---------
+ -- Gcc --
+ ---------
+
+ function Gcc return String
+ is
+ begin
+ return Which (Triplet & "gcc");
+ end Gcc;
+
+ ---------
+ -- Gxx --
+ ---------
+
+ function Gxx return String
+ is
+ begin
+ return Which (Triplet & "g++");
+ end Gxx;
+
+ --------
+ -- Nm --
+ --------
+
+ function Nm return String
+ is
+ begin
+ return Which (Triplet & "nm");
+ end Nm;
+
+end VxLink;
diff --git a/gcc/ada/vxlink.ads b/gcc/ada/vxlink.ads
new file mode 100644
index 0000000..37ae5d7
--- /dev/null
+++ b/gcc/ada/vxlink.ads
@@ -0,0 +1,68 @@
+------------------------------------------------------------------------------
+-- --
+-- GNAT COMPILER COMPONENTS --
+-- --
+-- V X L I N K --
+-- --
+-- S p e c --
+-- --
+-- Copyright (C) 2018, AdaCore --
+-- --
+-- 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. --
+-- --
+------------------------------------------------------------------------------
+
+-- See vxlink-main.adb for a description of the tool.
+--
+-- This package contains only common utility functions used by the other
+-- child packages.
+
+pragma Ada_2012;
+
+with Ada.Containers.Indefinite_Vectors;
+
+package VxLink is
+
+ package Strings_List is new Ada.Containers.Indefinite_Vectors
+ (Positive, String);
+
+ subtype Arguments_List is Strings_List.Vector;
+
+ procedure Set_Verbose (Value : Boolean);
+ function Is_Verbose return Boolean;
+
+ procedure Set_Error_State (Message : String);
+ function Is_Error_State return Boolean;
+
+ procedure Log_Info (S : String);
+ procedure Log_Error (S : String);
+
+ procedure Run (Arguments : Arguments_List);
+
+ function Run (Arguments : Arguments_List) return String;
+
+ function Gcc return String;
+ -- Current toolchain's gcc command
+
+ function Gxx return String;
+ -- Current toolchain's g++ command
+
+ function Nm return String;
+ -- Current toolchain's nm command
+
+ function Ends_With (Str, Suffix : String) return Boolean
+ is (Str'Length >= Suffix'Length
+ and then Str (Str'Last - Suffix'Length + 1 .. Str'Last) = Suffix);
+
+end VxLink;