[Prev][Next][Index]
Updates to True Type Code
- To: sage-users@cica.indiana.edu
- Subject: Updates to True Type Code
- Date: Sat, 07 Jan 1995 18:54:33 -0600
- From: Andrew Mauer <mauer@mcs.anl.gov>
The following message contains the latest version of my TrueType code.
There are a few bug fixes and enhancements. To install it, replace the
existing code in Sage++/libSage++.C (search for maskDescriptors --
that starts it) with the appended code.
Direct any questions to me (mauer@mcs.anl.gov). The next release of
Sage++ will have these changes folded in; if you do not use
maskDescriptors or getTrueType, you can safely discard this message.
/Andrew/
/* This code by Andrew Mauer (ajm) */
/*
maskDescriptors:
This routine strips many descriptive type traits which you are probably
not interested in cloning for variable declarations, etc.
Returns the getTrueType of the base type being described IF there
are no descriptors which are not masked out. The following masks
can be specified as an optional second argument:
MASK_NO_DESCRIPTORS: Do not mask out anything.
MASK_MOST_DESCRIPTORS: Only leave in: signed, unsigned, short, long,
const, volatile.
MASK_ALL_DESCRIPTORS: Mask out everything.
If you build your own mask, you should make sure that the traits
you want to set out have their bits UN-set, and the rest should have
their bits set. The complementation (~) operator is a good one to use.
See libSage++.h, where the MASK_*_DESCRIPTORS variables are defined.
*/
/* Thanks a lot for the stupid $@!@$ #ifdef USER in libSage++.h */
class SgDerivedType;
SgDescriptType *isSgDescriptType(SgType *pt);
SgPointerType *isSgPointerType(SgType *pt);
SgArrayType *isSgArrayType(SgType *pt);
SgDerivedType *isSgDerivedType(SgType *pt);
SgType *SgType::maskDescriptors (int mask /* = MASK_MOST_DESCRIPTORS */)
{
if ( ! isSgDescriptType(this))
return this;
int current_bits_set = isSgDescriptType(this)->modifierFlag();
if ( (current_bits_set & mask ) == 0 )
{
return this->baseType()->getTrueType(mask,0);
}
else if ( current_bits_set != (current_bits_set & mask) )
{
/* Mask has changed bits set. Need to build the new type
with the unwanted bits masked off. */
SgDescriptType *t_new = isSgDescriptType(&this->copy());
t_new->setModifierFlag( current_bits_set & mask );
return t_new;
}
else
{
return this;
}
}
/* This code by Andrew Mauer (ajm) */
/*
getTrueType:
Since Sage stores dereferenced pointers as PTR(-1) -> PTR(1) -> BASE_TYPE,
we may need to follow the chain of dereferencing to find the type
which we expect.
This code currently assumes that:
o If you follow the dereferencing pointer (PTR(-1)), you find another
pointer type, an array type, or a typedef to one of those.
We do NOT assume that the following situation cannot occur:
PTR(-1) -> PTR(-1) -> PTR(1) -> PTR(1) -> PTR(-1) -> PTR(1)
This means there may be more pointers to follow after we come to
an initial "equilibrium".
ALGORITHM:
T_POINTER:
[WARNING: No consideration is given to pointers with attributes
(ls_flags) set. For instance, a const pointer is treated the same
as any other pointer.]
1. Return the same type we got if it is not a pointer type or
the pointer is not a dereferencing pointer type.
2. Repeat { get next pointer , add its indirection to current total }
until the current total is 0. We have reached an equilibrium, so
the next type will not necessarily be a pointer type.
3. Check the next type for further indirection with another call
to getTrueType.
T_DESCRIPT:
Returns the result of maskDescriptors called with the given type and mask.
T_ARRAY:
If the array has zero dimensions, we pass over it. This type arose
for me in the following situation:
double x[2];
x[1] = 0;
T_DERIVED_TYPE:
If we have been told to follow typedefs, get the type of the
symbol from which this type is derived from, and continue digging.
Otherwise return this type.
HITCHES:
Some programs may dereference a T_ARRAY as a pointer, so we need
to be prepared to deal with that.
A typedef to a pointer (typedef double **new_type) can result in
needing to follow "through" a typedef (resolving it while
current_indirection is negative).
*/
SgType *SgType::getTrueType (int mask /* = MASK_MOST_DESCRIPTORS */, int follow_typedefs /* = 0 */)
{
switch (this->variant())
{
case T_POINTER:
{
SgType *next;
SgType *current;
int current_indirection;
current = this;
current_indirection =
isSgPointerType(current)->indirection();
if (current_indirection > 0)
return this;
/* if current_indirection == 0, we have a useless pointer,
so just return a truetype of its base */
while (current_indirection < 0)
{
// Get next type
next = current->baseType();
recycle:
if ( isSgPointerType (next) )
{
// add indirection to current
current_indirection +=
isSgPointerType(next)->indirection();
}
else if ( isSgArrayType (next) )
{
/* One level of indirection for each dimension. */
current_indirection +=
isSgArrayType(next)->dimension();
}
else if ( isSgDerivedType (next) )
{
/* If we have "typedef double **NEW_TYPE" and
write: NEW_TYPE x;
**x = 10.0;
Then the "**x" will result in a type dereferencing
through a typedef.
*/
/* In this case, I think we should go past the
typdef regardless of the value of
FOLLOW_TYPEDEFS. We'll also tear through any
descriptors we find, since the dereferencing
ought to move us past them.
True typing needs to be associative, for
this sub-calling method to work. */
next = next->getTrueType(MASK_ALL_DESCRIPTORS,
DO_FOLLOW_TYPEDEFS);
goto recycle;
}
else
{
/* Don't know what's going on. Fix me.
This includes the case of ptr not having
a base type, so next = NULL. */
abort();
}
current = next;
}
/* Don't use next because we might not execute the above while. */
return current->baseType()->getTrueType(mask, follow_typedefs);
}
break;
case T_DESCRIPT:
return this->maskDescriptors (mask);
break;
case T_DERIVED_TYPE:
{
if ( follow_typedefs )
{
SgDerivedType *derived_type = isSgDerivedType (this);
return (
(derived_type->typeName()->type())->getTrueType(mask, follow_typedefs)
);
}
else
{
return this;
}
break;
}
case T_ARRAY:
{
SgArrayType *the_array = isSgArrayType(this);
if (the_array->dimension() == 0)
{
/* use `this' and not `the_array' because SgArrayType
overrides the expected behaviour for baseType
(5 Nov 94) */
return this->baseType()->getTrueType(mask,
follow_typedefs);
}
else
{
return this;
}
}
default:
return this;
break;
}
}