[Prev][Next][Index]

Updates to True Type Code




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;
     }
}