From an ASIS application viewpoint we may view an ASIS
Context as a set of
Compilation_Units accessible through ASIS queries.
A common ASIS implementation technique is to base an implementation of an ASIS
Context on some persistent data structures created by the underlying Ada
compiler when compiling Ada compilation units maintained by this compiler.
The ASIS-for-GNAT implementation uses the GNAT compiler for this purpose. This
implementation choice has some ramifications discussed in this chapter.
5.1. ASIS Tree Creator¶
To create the persistent data structures needed for the ASIS-for-GNAT
implementation a special modification of the GNAT compiler is used.
This modification is based on GNSA (GNAT Semantic Analyzer) which is
basically a part of a normal compiler that does full semantic analysis of
the Ada sources but that cannot generate the code. This modification
asis-gcc and it is located in the
package an ASIS-for-GNAT user should install. It is recommended to add the
asis-gcc to your
PATH (moreover, this is required if
Context modes when tree files are created by the ASIS
queries on the fly).
asis-gcc is located in
.../asistools-standalone/libexec/asis-gnsa/bin/, the name of the
root package of
asistools-standalone installation may contain the
version information, the date of packaging and the name of the platform, e.g.
5.2. Interaction between ASIS and ASIS Tree Creator¶
Context can only contain compilable compilation units. If a
compilation error is produced by the tree creator for any reason (such as,
the source is not legal Ada, representation is not compatible with tree
creator’s architecture, there is a limitation in the creator preventing it from
processing a given construct, etc), then ASIS analysis will not continue.
Additionally, some compilation options and configuration pragmas can disrupt the analysis. For example, if a pragma Ignore_Pragma is in effect, any pragmas subject to this pragma in the source may not be fully analyzable by an ASIS application.
The known limitations of the tree creator are listed below.
If you need to create a tree for a source that contains representation clause that are not compatible with the architecture where your
asis-gccis used. The only possibility to compile this source for a tree is to use the GNAT
-gnatIoption. But the drawback of this solution is that the tree will not contain any information about all the representation clauses in the source, and your ASIS application will not see them.
If you compile your source with Assertion_Policy pragma that disables all or specific assertions (this may happen if you have such pragma(s) in your configuration file(s) and if you are using similar compilation scenarios to build your program and to create tree files with
asis-gcc ``), then all the semantic information for the code that is inside assertions (aspect definitions, pragmas Assert) is missing in the tree, and ASIS semantic queries will blow up or return wrong results when applying to the components of such code. To avoid this, you should add ``pragma Ignore_Pragma (Assertion_Policy)to configuration files used to create trees;
A dynamic predicate may fail to get analyzed if an overloaded name is declared in a package and is used in a dynamic predicate in the form of an expanded name (with package name as a prefix). Workaround: refer to the overloaded name in the dynamic predicate as a simple name.
Context and Tree Files¶
implementation is based on tree output files,
or, simply, tree files. When called with the special option
ASIS Tree Creator creates and outputs a tree file if no error was
detected during the compilation. The tree file is a kind of snapshot of
the compiler internal data structures (basically, of the Abstract Syntax Tree
(AST)) near the end of the successful compilation. ASIS then inputs tree
files and recreates in its internal data structures exactly the same picture
the compiler had at the end of the corresponding successful compilation.
An important consequence of the GNAT source-based compilation model is that the AST contains full information not only about the unit being compiled, but also about all the units upon which this unit depends semantically. Therefore, having read a tree file, ASIS can in general provide information about more than one unit. By processing a tree file, a tool can provide information about the unit for which this tree was created and about all the units upon which it depends semantically. However, to process several units, ASIS sometimes has to change the tree being processed (in particular, this occurs when an application switches between units which do not semantically depend on each other, for example, two package bodies). Therefore, in the course of an ASIS application, ASIS may read different tree files and it may read the same tree file more then once.
The name of a tree file is obtained from the name of the source file being
compiled by replacing its suffix with ‘
.adt’. For example, the tree
foo.adb is named
5.4. Creating Tree Files for Use by ASIS¶
Depending on the general organization of an ASIS application, either the application itself or a user of the application should to create a set of tree files that correctly reflect the set of the Ada components to be processed by the ASIS application, as well as to maintain the consistency of the trees and the related source files.
To create a tree file for a given source file, you need to compile the corresponding source file
by the ASIS Tree Creator with the
$ asis-gcc -c -gnatct foo.adb
foo.adt, provided that
foo.adb contains the source
of a legal Ada compilation unit. Actually, the
-gnatct is an
ASIS-specific combination of two compilation options,
-gnatt option generates a tree file,
-gnatc turns off AST expansion that are not needed for ASIS.
The following points are important to remember when generating and dealing with tree files:
ASIS-for-GNAT is distributed for a particular version of the ASIS Tree Creator.
All the trees to be processed by an ASIS application should be generated by this specific version of the ASIS Tree Creator.
A tree file is not created if an error has been detected during the compilation.
In contrast with object files, a tree file may be generated for any legal Ada compilation unit, including a library package declaration requiring a body or a subunit.
A set of tree files processed by an ASIS application may be inconsistent; for example, two tree files may have been created with different versions of the source of the same unit. This will lead to inconsistencies in the corresponding ASIS
Context. See Consistency Problems, for more details.
Do not move tree, object or source files among directories in the underlying file system! ASIS might assume an inconsistency between tree and source files when opening a
Context, or you may get wrong results when querying the source or object file for a given ASIS
When invoking asis-gcc to create tree files, make sure that all file and directory names containing relative path information start from
..\respectively in MS Windows). That is, to create a tree file for the source file
foo.adblocated in the inner directory named
inner, you should invoke asis-gcc (assuming an MS Windows platform) as:
$ asis-gcc -c -gnatct .\inner\foo.adb
but not as
$ asis-gcc -c -gnatct inner\foo.ads
Otherwise ASIS will not perform correctly.
When reading in a tree file, ASIS checks that this tree file was created with the
-gnatcoption, and it does not accept trees created without this option.
If called to create a tree, the ASIS Tree Creator does not destroy an
ALIfile if the
ALIfile already exists for the unit being compiled and if this
ALIfile is up-to-date. Moreover, GNAT may place some information from the existing
ALIfile into the tree file. If you would like to have both object and tree files for your program, first create the object files, and then the tree files.
There is only one extension for tree files, namely
.adt, whereas the standard GNAT name convention for the Ada source files uses different extensions for a spec (
.ads) and for a body (
.adb). This means that if you first generate a tree for a unit’s body:
$ asis-gcc -c -gnatct foo.adb
and then generate the tree for the corresponding spec:
$ asis-gcc -c -gnatct foo.ads
then the tree file
foo.adtwill be created twice: first for the body, and then for the spec. The tree for the spec will override the tree for the body, and the information about the body will be lost for ASIS. If you first create the tree for a spec, and then for a body, the second tree will also override the first one, but no information will be lost for ASIS, because the tree for a body contains full information about the corresponding spec. So, if you have to create a set of tree files for a set of sources, first create trees for specs and then for bodies:
$ asis-gcc -c -gnatct *.ads $ asis-gcc -c -gnatct *.adb
Reading tree files is a time-consuming operation. Try to minimize the number of tree files to be processed by your application, and try to avoid unnecessary tree swappings. (See How to Build Efficient ASIS Applications, for some tips).
It is possible to create tree files “on the fly”, as part of the processing of the ASIS queries that obtain units from a
Context. In this case there is no need to create tree files before running an ASIS application using the corresponding
Contextmode. Note that this possibility goes beyond the ASIS Standard, and there are some limitations imposed on some ASIS queries, but this functionality may be useful for ASIS tools that process only one
Compilation_Unitat a time. See the ASIS-for-GNAT Reference Manual for more details.
It is possible can create a set of tree files for all the sources from your project
by indicating the
--target=asis option for
gprbuild (provided that you
asis-gcc on your path). The following command:
$ gprbuild -c --target=asis -P prj.gpr --subdirs=asis -gnatct ...
creates the set of trees for the sources from
prj.gpr in the
subdirectory of the project objects directory.
Note that between opening and closing a
Context, an ASIS application should
not change its working directory; otherwise execution of the application is
5.4.1. Creating Trees for Data Decomposition Annex¶
Using the ASIS Data Decomposition Annex (DDA) does not require anything special to be done by an ASIS user, with one exception. The implementation of the ASIS DDA is based on some special annotations added by the compiler to the trees used by ASIS. An ASIS user should be aware of the fact that trees created for subunits do not have this special annotation.
Therefore ASIS DDA queries do
not work correctly on trees created for subunits (and these queries might not
work correctly if a set of tree files making up a
Context contains a tree
created for a subunit).
Thus, when working with the ASIS DDA, you should avoid creating separate trees for subunits. Actually, this is not a limitation: to create a tree for a subunit, you should also have the source of the parent body available. If in this situation you create the tree for the parent body, it will contain the full information (including DDA-specific annotation) for all the subunits that are present. From the other side, a tree created for a single subunit has to contain information about the parent body, so it has about the same size as the tree for the parent body.
The best way to create trees when using ASIS DDA is to use gnatmake: it will never create separate trees for subunits.
5.5. Different Ways to Define an ASIS
Context in ASIS-for-GNAT¶
that defines a
Context has the following spec:
procedure Associate (The_Context : in out Asis.Context; Name : in Wide_String; Parameters : in Wide_String := Default_Parameters);
Name does not have any special meaning, and the
properties of the
Context are set by ‘options’ specified
How to define a set of tree files making up the
How to deal with tree files when opening a
Contextand when processing ASIS queries (
How to process the source files during the consistency check when opening the
The search path for tree files making up the
The search path for source files used for calling ASIS Tree Creator to create a tree file “on the fly” (
The association parameters may (and in some cases must) also contain the
names of tree files or directories making up search paths for tree and/or
source files. Below is the overview of the
Context association parameters in
ASIS-for-GNAT; for full details refer to the ASIS-for-GNAT Reference Manual.
5.5.1. Defining a set of tree files making up a
The following options are available:
Contextcomprising a single tree file; this tree file name should be given explicitly in the
Contextcomprising a set of tree files; the names of the tree files making up the
Contextshould be given explicitly in the
Contextcomprising all the tree files in the tree search path given in the same
Parametersstring; if this option is set together with
-FMoption, ASIS can also create new tree files “on the fly” when processing queries yielding ASIS
The default option is
Note that for
Parameters string should contain the name of exactly
one tree file. Moreover, if during the opening of such a
Context this tree file could not be successfully read in because of any
Asis_Failed exception is raised.
5.5.2. Dealing with tree files when opening a
Context and processing ASIS queries¶
The following options are available:
Only pre-created trees are used, no tree file can be created by ASIS.
All the trees considered as making up a given
Contextare created “on the fly”, whether or not the corresponding tree file already exists; once created, a tree file may then be reused while the
Contextremains open. This option can be set only with
Mixed approach: if a needed tree does not exist, the attempt to create it “on the fly” is made. This option can only be set with
The default option is
Note that the
go beyond the scope of the
official ASIS standard. They may be useful for some ASIS applications with
specific requirements for defining and processing an ASIS
but in each case the ramifications of using such non-standard options
should be carefully considered. See the ASIS-for-GNAT Reference Manual
for a detailed description of these option.
5.5.3. Processing source files during the consistency check¶
When ASIS reads a tree fule as a part of opening a
checks, that the tree is consistent with the source files of the
Compilation_Units represented by this tree.
The following options are available to control this check:
Source files for all the
Compilation_Units belonging to the
Context(except the predefined
Standardpackage) have to be available, and all of them are taken into account for consistency checks when opening the
Only existing source files for all the
Compilation_Units belonging to the
Contextare taken into account for consistency checks when opening the
None of the source files from the underlying file system are taken into account when checking the consistency of the set of tree files making up a
Context(that is, no check is made).
The default option is
See Consistency Problems, concerning consistency issues in ASIS-for-GNAT.
5.5.4. Setting search paths¶
-gnatA options for defining
Context is similar to using the same optionsfor gcc.
-T option is used in the same way,
for tree files. For full details about the
options, refer to the ASIS-for-GNAT Reference Manual. Note that the
option is used only to locate existing tree files, and it has no effect for
Contexts. On the other hand, the
-I option is used only to
construct a set of arguments when ASIS calls ASIS Tree Creator to create a tree file “on
the fly”; it has no effect for
Contexts, and it cannot be used to
tell ASIS where it should look for source files for ASIS
5.6. Consistency Problems¶
There are two different kinds of consistency problems existing for
ASIS-for-GNAT, and both of them can show up when opening an ASIS
First, a tree file may have been created by another version of ASIS Tree Creator (see the README file about the coordination between the ASIS Tree Creator and ASIS-for-GNAT versions). This means that there is an ASIS-for-GNAT installation problem.
Second, the tree files may be inconsistent with the existing source files or with each other.
5.6.1. Inconsistent versions of ASIS and ASIS Tree Creator¶
When ASIS-for-GNAT reads a tree file created by the version of ASIS Tree Creator
for which a given version of ASIS-for-GNAT is not supposed to be used, ASIS
treats the situation as an ASIS-for-GNAT installation problem
with a corresponding exception message. In
Program_Error is not caught by any ASIS query, and it propagates
Note that the real cause may be an old tree file you have forgotten to
remove when reinstalling ASIS-for-GNAT. This is also considered an
ASIS uses the tree files created by ASIS Tree Creator installed on your machine, and the ASIS implementation includes some compiler components to define and to get access to the corresponding data structures. Therefore, the version of ASIS Tree Creator installed on your machine and the version of the GNAT compiler whose sources are used as a part of the ASIS implementation should be close enough to define the same data structures. We do not require these versions to be exactly the same, and, by default, when ASIS reads a tree file it only checks for significant differences. That is, it will accept tree files from previous versions of GNAT as long as it is possible for such files to be read. In theory, this check is not 100% safe; that is, a tree created by one version of ASIS Tree Creator might not be correctly processed by ASIS built with GNAT sources taken from another version. But in practice this situation is extremely unlikely.
An ASIS application may set a strong GNAT version check by providing the
-vs parameter for the ASIS
Initialize procedure, see
ASIS-for-GNAT Reference Manual
for more details. If the strong version check is set, then only a
tree created by exactly the same version of GNAT whose sources are used
as a part of the ASIS implementation can be successfully read in, and
Program_Error will be raised otherwise.
Be careful when using a
when others exception handler in your ASIS
application: do not use it just to catch non-ASIS exceptions and to ignore
them without any analysis.
5.6.2. Consistency of a set of tree and source files¶
When processing a set of more then one tree file making up the same
ASIS may face a consistency problem. A set of tree files is inconsistent if it
contains two trees representing the same compilation unit, and these trees
were created with different versions of the source of this unit. A tree file
is inconsistent with a source of a unit represented by this tree if the source
file currently available for the unit differs from the source used to create
the tree file.
When opening a
Context (via the
ASIS does the
following checks for all the tree files making up the
-SAoption is set for the
Context, ASIS checks that for every
Compilation_Unitrepresented by a tree, the source file is available and it is the same as the source file used to create the tree (a tree file contains references to all the source files used to create this tree file).
-SEoption is set for the
Context, then if for a
Compilation_Unitrepresented by a tree a source file is available, ASIS checks that this source is the same as the source used to create the tree. If for a
Compilation_Unitbelonging to a
Contexta source file is not available, ASIS checks that all the tree files containing this unit were created with the same version of the source of this unit.
-SNoption is set for the
Context, ASIS checks that all the trees were created from the same versions of the sources involved. It does not check if any of these sources is available or if this is the same version of the source that has been used to create the tree files.
If any of these checks fail, the
is raised as a result of
Context. If the
Context has been successfully opened,
you are guaranteed
that ASIS will process only consistent sets of tree and source files until the
Context is closed (provided that this set is not changed by some non-ASIS
5.7. Processing Several
Contexts at a Time¶
If your application processes more then one open
Context at a time, and if
at least one of the
Contexts is defined with an
be aware that all the tree files created by ASIS “on the fly” are
placed in the current directory. Therefore, to be on the safe side when
processing several opened
Contexts at a time, an ASIS application should
have at most one
Context defined with an
-FM option. If the
application has such a
Context, all the other
Contexts should not use
tree files located in the current directory.
5.8. Getting Representation Information with
Data Decomposition Annex Queries¶
Data Decomposition Annex allows to get information about the actual
type representation and to decompose data values using the ASIS type information and a
portable data stream, representing a data value of that type.
There are two ways to get the type representation information. By default ASIS
extracts this information from the tree files. In this mode all the queries from
Data Decomposition Annex can be used. The limitation of this approach is
that the representation information computed by the queries from the
Decomposition Annex always corresponds to the ASIS Tree Creator, but not to the
compiler you could be interested in.
If you need the representation information corresponding to a specific compiler, you
can use another way of getting it with the ASIS
Data Decomposition Annex.
You have to compile the Ada source of interest by this compiler with
option. This creates a JSON file with the type representation information. Note,
that in case of a package body this file creates information about types defined
in the body and in the corresponding package declaration. The name of this file is
the same as the name of the Ada source being compiled, and the suffix is
And then ASIS reads such JSON files to get the information needed for the
Data Decomposition Annex.
To use JSON files as the source of information for the
Data Decomposition Annex,
you need to provide
-gnatR parameter for the call to
Asis.Ada_Environments.Associate procedure. By default ASIS reads all the JSON files
from the current directory, if you want to read them from some other directory you
can indicate this directory with
-R option of the call to
Asis.Ada_Environments.Associate procedure. This approach has two limitations.
First, you cannot use queries from the
Data Decomposition Annex that have
portable data as a parameter. Second, for some types declared in the bodies (for
example - in the bodies of protected operations) a representation information is not