The sort of an identifier depends on how it is declared.
If it is declared as a global variable, then its sort is given
by its declaration (see section 5.4 Declarators).
If it is a constant from a trait, then its sort is given in the trait.
If an identifier declared in a quantifier,
then the declaration explicitly gives its sort.
Otherwise, for identifiers declared as formal parameters,
the sort is determined from the declared type
(see section 2.7 Types and Sorts) as for global variables (see section 5.4 Declarators)
with the following important differences.
The first difference is that since parameters are passed by value,
the leading Obj
sort generator
(or ConstObj
generator, see below) is taken
off, unless the type is a reference type.
The reason for taking off the leading Obj
sort generator
is that non-reference parameters are passed by value in C++.
(In this we follow LCL, see [Guttag-Horning93].)
Second, the use of array types for formal parameters (at the top level)
is equivalent to the use of a pointer type.
(This follows C++, but differs from LCL [Chalin95].)
Finally, the sorts of formal struct and union parameters
are the corresponding value sort, not the object sort.
Examples are given in the following table.
Declaration VarId Its Sort (when used as a formal parameter) ------------- ----- ----------------------------------------- int i i int int & ir ir Obj[int] int * ip ip Ptr[Obj[int]] int ai[] ai Ptr[Obj[int]] struct IPair { int fst, snd; }; IPair sip; sip Val[IPair] union FI { float f; int i; }; FI fi; fi Val[FI]
In the table above,
the sorts of ir
and i
differ, unlike the case
for global variables.
The sort of *ip
is Obj[int]
,
which is also the sort of: ai[0]
, ip[0]
, and *ai
.
The sort of ai
is the same as the sort of ip
,
because of the C++ equivalence between array parameters
and pointer parameters.
Another way to think of this is that
when an array is passed in C++,
the address of the element with index 0 is passed
as a pointer value.
(Although in C++ there is no type distinction between an array name
and a pointer value,
so that myArray
and &myArray[0]
are equivalent in almost all contexts;
in the Larch/C++ model these two expressions have different sorts,
and thus one should think of the C++ function call
f(myArray)
as shorthand for f(&myArray[0])
.
In terms of the trait functions of the trait PrePointer
(see section 11.8 Pointer Types),
the abstract value passed is address_of(myArray,0)
.)
The sort of sip
is not IPair
, but Val[IPair]
,
because IPair
would be a tuple of objects instead of a tuple of values
(see section 11.10 Structure and Class Types).
The sort Val[IPair]
is a tuple with two fields,
fst
and snd
, both of sort
int
(not Obj[int]
, but int
values).
This models passing structures by value.
Hence the sort s of the terms sip.fst
and sip.snd
are both int
.
Similarly, the sort of fi
is not FI
, but Val[FI]
,
since pass by value implies the formal parameter's model should
be a union of values (not objects).
The sort Val[FI]
is a union with two tags:
f
and i
.
When defined,
the sort of fi.f
is float
,
and the sort of fi.i
is int
.
See section 11.11 Union Types for details on how the sort Val[FI]
is defined.
Except for reference parameters, the use of const
does not change the sorts of formal parameters.
It also does affect the C++ interface of a function,
unless one uses const
reference, pointer, or array parameters [ANSI95].
Hence its use is best avoided for formal parameters,
except, of course for const
reference, pointer, or array parameters.
The sort of a formal parameter that uses const
is derived from the sort of the corresponding global variable declaration
in a way that is analogous to how the sorts of formals without const
are derived.
That is, the main idea is that
the leading ConstObj
sort generator
is taken off
of the sort of the corresponding global variable declaration,
but this does not affect reference parameters.
For example, consider the following.
Declaration VarId Its sort (when used as a formal parameter) ------------------- ----- ----------------------------------------- const int ci ci int const int& rc rc ConstObj[int] int& const cr cr ConstObj[int] const int * pci pci Ptr[ConstObj[int]] int * const cip cip Ptr[Obj[int]] const int cai[] cpi Ptr[ConstObj[int]] struct IPair { int fst, snd; }; const pair csip; csip Val[IPair]
In the above, the sorts of the references are the same as they would be
when used as global variables.
The sort of pci
reflects its being a pointer to constant
integer objects.
Thus pci
, used as a formal parameter, is considered to name a value,
but *pci
is an lvalue--a constant integer object.
The sort Val[IPair]
is a tuple of two fields fst
and snd
,
both of sort int
.
See section 11.10 Structure and Class Types for details on this sort.
C++ considers the declarations int
and const int
different for formal parameters,
and thus for linking programs with functions so declared.
When possible, avoid the use of const
for such formals,
and only use it for references and pointers (and for pointers, only in
the form as shown in the declaration of pci
).
For C++ type names T
and S
,
the above discussion is summarized in the following table.
See section 11.10 Structure and Class Types for an explanation of how the sort Val[STS]
is defined.
Form of Decl. Sort of x (used as a formal parameter) ------------- -------------------------------------- T x T const T x T T & x Obj[T] const T & x ConstObj[T] T & const x ConstObj[T] T * x Ptr[Obj[T]] const T * x Ptr[ConstObj[T]] T * const x Ptr[Obj[T]] T x[] Ptr[Obj[T]] const T x[] Ptr[ConstObj[T]] struct STS { T t; S s }; STS x; Val[STS] const STs x; Val[STS]
When these types are composed, the sort becomes the composite
of the sorts given.
The only apparent exception is the interaction of const
and references.
The following are a few examples.
See section 11.10 Structure and Class Types discusses how the traits that define
Val[Str]
and Val[IntList]
would be defined.
Note that Val[IntList]
is a tuple of two fields.
The field val
has sort int
, and the field next
has sort Ptr[Obj[IntList]]
.
See section 5.4.8 Summary of Declarations to compare the following with the sorts
of the corresponding global variables.
Declaration Sort of x (used as a formal parameter) ------------- -------------------------------------- const int &const x; ConstObj[int] const int *const x; Ptr[ConstObj[int]] const int x[][4]; Ptr[Arr[ConstObj[int]]] int *x[]; Ptr[Obj[Ptr[Obj[int]]]] int **x; Ptr[Obj[Ptr[Obj[int]]]] int (*x)[10]; Ptr[Arr[Obj[int]]] int (*x[])[4]; Ptr[Obj[Ptr[Arr[Obj[int]]]]] int *const x[]; Ptr[ConstObj[Ptr[Obj[int]]]] int ***x; Ptr[Obj[Ptr[Obj[Ptr[Obj[int]]]]]] struct Str { char *s; int len; }; Str x; Val[Str] struct IntList { int val; IntList *next; }; IntList x; Val[IntList] const IntList x; Val[IntList]
Go to the first, previous, next, last section, table of contents.