FreeBSD/contrib/gcc/cp/class.c
/* Return the dynamic type of INSTANCE, if known.
   Used to determine whether the virtual function table is needed
   or not.

   *NONNULL is set iff INSTANCE can be known to be nonnull, regardless
   of our knowledge of its type.  *NONNULL should be initialized
   before this function is called.  */
Return the dynamic type of INSTANCE, if known.
Used to determine whether the virtual function table is needed
or not.

NONNULL is set iff INSTANCE can be known to be nonnull, regardless
of our knowledge of its type.  *NONNULL should be initialized
before this function is called.
Return the dynamic type of INSTANCE if known . Used to determine whether the virtual function table is needed or not . NONNULL is set iff INSTANCE can be known to be nonnull regardless of our knowledge of its type . * NONNULL should be initialized before this function is called .
static tree
fixed_type_or_null (tree instance, int* nonnull, int* cdtorp)
{
  switch (TREE_CODE (instance))
    {
    case INDIRECT_REF:
      if (POINTER_TYPE_P (TREE_TYPE (instance)))
	return NULL_TREE;
      else
	return fixed_type_or_null (TREE_OPERAND (instance, 0),
				   nonnull, cdtorp);
    case CALL_EXPR:
      if (TREE_HAS_CONSTRUCTOR (instance))
	{
	  if (nonnull)
	    *nonnull = 1;
	  return TREE_TYPE (instance);
	}
      return NULL_TREE;
    case SAVE_EXPR:
      if (TREE_HAS_CONSTRUCTOR (instance))
	{
	  if (nonnull)
	    *nonnull = 1;
	  return TREE_TYPE (instance);
	}
      return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
    case PLUS_EXPR:
    case MINUS_EXPR:
      if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
	return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
      if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
	return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
      return NULL_TREE;
    case NOP_EXPR:
    case CONVERT_EXPR:
      return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
    case ADDR_EXPR:
      instance = TREE_OPERAND (instance, 0);
      if (nonnull)
	{
	  tree t = get_base_address (instance);
	  if (t && DECL_P (t))
	    *nonnull = 1;
	}
      return fixed_type_or_null (instance, nonnull, cdtorp);
    case COMPONENT_REF:
      if (DECL_FIELD_IS_BASE (TREE_OPERAND (instance, 1)))
	return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull, cdtorp);
      return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull, cdtorp);
    case VAR_DECL:
    case FIELD_DECL:
      if (TREE_CODE (TREE_TYPE (instance)) == ARRAY_TYPE
	  && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (instance))))
	{
	  if (nonnull)
	    *nonnull = 1;
	  return TREE_TYPE (TREE_TYPE (instance));
	}
    case TARGET_EXPR:
    case PARM_DECL:
    case RESULT_DECL:
      if (IS_AGGR_TYPE (TREE_TYPE (instance)))
	{
	  if (nonnull)
	    *nonnull = 1;
	  return TREE_TYPE (instance);
	}
      else if (instance == current_class_ptr)
	{
	  if (nonnull)
	    *nonnull = 1;
	  if (DECL_LANG_SPECIFIC (current_function_decl)
	      && (DECL_CONSTRUCTOR_P (current_function_decl)
		  || DECL_DESTRUCTOR_P (current_function_decl)))
	    {
	      if (cdtorp)
		*cdtorp = 1;
	      return TREE_TYPE (TREE_TYPE (instance));
	    }
	}
      else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
	{
	  static htab_t ht;
	  if (!ht)
	    ht = htab_create (37, 
			      htab_hash_pointer,
			      htab_eq_pointer,
			      NULL);
	  if (nonnull)
	    *nonnull = 1;
	  if (TREE_CODE (instance) == VAR_DECL
	      && DECL_INITIAL (instance)
	      && !htab_find (ht, instance))
	    {
	      tree type;
	      void **slot;
	      slot = htab_find_slot (ht, instance, INSERT);
	      *slot = instance;
	      type = fixed_type_or_null (DECL_INITIAL (instance),
					 nonnull, cdtorp);
	      htab_remove_elt (ht, instance);
	      return type;
	    }
	}
      return NULL_TREE;
    default:
      return NULL_TREE;
    }
}
static tree fixed_type_or_null ( tree instance , int * nonnull , int * cdtorp ) { switch ( TREE_CODE ( instance ) ) { case INDIRECT_REF : if ( POINTER_TYPE_P ( TREE_TYPE ( instance ) ) ) return NULL_TREE ; else return fixed_type_or_null ( TREE_OPERAND ( instance , 0 ) , nonnull , cdtorp ) ; case CALL_EXPR : if ( TREE_HAS_CONSTRUCTOR ( instance ) ) { if ( nonnull ) * nonnull = 1 ; return TREE_TYPE ( instance ) ; } return NULL_TREE ; case SAVE_EXPR : if ( TREE_HAS_CONSTRUCTOR ( instance ) ) { if ( nonnull ) * nonnull = 1 ; return TREE_TYPE ( instance ) ; } return fixed_type_or_null ( TREE_OPERAND ( instance , 0 ) , nonnull , cdtorp ) ; case PLUS_EXPR : case MINUS_EXPR : if ( TREE_CODE ( TREE_OPERAND ( instance , 0 ) ) == ADDR_EXPR ) return fixed_type_or_null ( TREE_OPERAND ( instance , 0 ) , nonnull , cdtorp ) ; if ( TREE_CODE ( TREE_OPERAND ( instance , 1 ) ) == INTEGER_CST ) return fixed_type_or_null ( TREE_OPERAND ( instance , 0 ) , nonnull , cdtorp ) ; return NULL_TREE ; case NOP_EXPR : case CONVERT_EXPR : return fixed_type_or_null ( TREE_OPERAND ( instance , 0 ) , nonnull , cdtorp ) ; case ADDR_EXPR : instance = TREE_OPERAND ( instance , 0 ) ; if ( nonnull ) { tree t = get_base_address ( instance ) ; if ( t && DECL_P ( t ) ) * nonnull = 1 ; } return fixed_type_or_null ( instance , nonnull , cdtorp ) ; case COMPONENT_REF : if ( DECL_FIELD_IS_BASE ( TREE_OPERAND ( instance , 1 ) ) ) return fixed_type_or_null ( TREE_OPERAND ( instance , 0 ) , nonnull , cdtorp ) ; return fixed_type_or_null ( TREE_OPERAND ( instance , 1 ) , nonnull , cdtorp ) ; case VAR_DECL : case FIELD_DECL : if ( TREE_CODE ( TREE_TYPE ( instance ) ) == ARRAY_TYPE && IS_AGGR_TYPE ( TREE_TYPE ( TREE_TYPE ( instance ) ) ) ) { if ( nonnull ) * nonnull = 1 ; return TREE_TYPE ( TREE_TYPE ( instance ) ) ; } case TARGET_EXPR : case PARM_DECL : case RESULT_DECL : if ( IS_AGGR_TYPE ( TREE_TYPE ( instance ) ) ) { if ( nonnull ) * nonnull = 1 ; return TREE_TYPE ( instance ) ; } else if ( instance == current_class_ptr ) { if ( nonnull ) * nonnull = 1 ; if ( DECL_LANG_SPECIFIC ( current_function_decl ) && ( DECL_CONSTRUCTOR_P ( current_function_decl ) || DECL_DESTRUCTOR_P ( current_function_decl ) ) ) { if ( cdtorp ) * cdtorp = 1 ; return TREE_TYPE ( TREE_TYPE ( instance ) ) ; } } else if ( TREE_CODE ( TREE_TYPE ( instance ) ) == REFERENCE_TYPE ) { static htab_t ht ; if ( ! ht ) ht = htab_create ( 37 , htab_hash_pointer , htab_eq_pointer , NULL ) ; if ( nonnull ) * nonnull = 1 ; if ( TREE_CODE ( instance ) == VAR_DECL && DECL_INITIAL ( instance ) && ! htab_find ( ht , instance ) ) { tree type ; void * * slot ; slot = htab_find_slot ( ht , instance , INSERT ) ; * slot = instance ; type = fixed_type_or_null ( DECL_INITIAL ( instance ) , nonnull , cdtorp ) ; htab_remove_elt ( ht , instance ) ; return type ; } } return NULL_TREE ; default : return NULL_TREE ; } }
Return the dynamic type of INSTANCE, if known.
Return the dynamic type of INSTANCE if known .
/* This is a call to a constructor, hence it's never zero.  */ /* This is a call to a constructor, hence it's never zero.  */ /* Propagate nonnull.  */ /* Just because we see an ADDR_EXPR doesn't mean we're dealing
	     with a real object -- given &p->f, p can still be null.  */ /* ??? Probably should check DECL_WEAK here.  */ /* If this component is really a base class reference, then the field
	 itself isn't definitive.  */ /* fall through...  */ /* if we're in a ctor or dtor, we know our type.  */ /* We only need one hash table because it is always left empty.  */ /*htab_del=*/ /* Reference variables should be references to objects.  */ /* Enter the INSTANCE in a table to prevent recursion; a
	     variable's initializer may refer to the variable
	     itself.  */