FreeBSD/contrib/gcc/c-common.c
/* Build the result of __builtin_offsetof.  EXPR is a nested sequence of
   component references, with STOP_REF, or alternatively an INDIRECT_REF of
   NULL, at the bottom; much like the traditional rendering of offsetof as a
   macro.  Returns the folded and properly cast result.  */
Build the result of __builtin_offsetof.  EXPR is a nested sequence of
component references, with STOP_REF, or alternatively an INDIRECT_REF of
NULL, at the bottom; much like the traditional rendering of offsetof as a
macro.  Returns the folded and properly cast result.
Build the result of __builtin_offsetof . EXPR is a nested sequence of component references with STOP_REF or alternatively an INDIRECT_REF of NULL at the bottom ; much like the traditional rendering of offsetof as a macro . Returns the folded and properly cast result .
static tree
fold_offsetof_1 (tree expr, tree stop_ref)
{
  enum tree_code code = PLUS_EXPR;
  tree base, off, t;
  if (expr == stop_ref && TREE_CODE (expr) != ERROR_MARK)
    return size_zero_node;
  switch (TREE_CODE (expr))
    {
    case ERROR_MARK:
      return expr;
    case VAR_DECL:
      error ("cannot apply %<offsetof%> to static data member %qD", expr);
      return error_mark_node;
    case CALL_EXPR:
      error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
      return error_mark_node;
    case INTEGER_CST:
      gcc_assert (integer_zerop (expr));
      return size_zero_node;
    case NOP_EXPR:
    case INDIRECT_REF:
      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
      gcc_assert (base == error_mark_node || base == size_zero_node);
      return base;
    case COMPONENT_REF:
      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
      if (base == error_mark_node)
	return base;
      t = TREE_OPERAND (expr, 1);
      if (DECL_C_BIT_FIELD (t))
	{
	  error ("attempt to take address of bit-field structure "
		 "member %qD", t);
	  return error_mark_node;
	}
      off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
			size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1)
				  / BITS_PER_UNIT));
      break;
    case ARRAY_REF:
      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
      if (base == error_mark_node)
	return base;
      t = TREE_OPERAND (expr, 1);
      if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
	{
	  code = MINUS_EXPR;
	  t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
	}
      t = convert (sizetype, t);
      off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
      break;
    case COMPOUND_EXPR:
      t = TREE_OPERAND (expr, 1);
      gcc_assert (TREE_CODE (t) == VAR_DECL);
      return fold_offsetof_1 (t, stop_ref);
    default:
      gcc_unreachable ();
    }
  return size_binop (code, base, off);
}
static tree fold_offsetof_1 ( tree expr , tree stop_ref ) { enum tree_code code = PLUS_EXPR ; tree base , off , t ; if ( expr == stop_ref && TREE_CODE ( expr ) != ERROR_MARK ) return size_zero_node ; switch ( TREE_CODE ( expr ) ) { case ERROR_MARK : return expr ; case VAR_DECL : error ( " " , expr ) ; return error_mark_node ; case CALL_EXPR : error ( " " ) ; return error_mark_node ; case INTEGER_CST : gcc_assert ( integer_zerop ( expr ) ) ; return size_zero_node ; case NOP_EXPR : case INDIRECT_REF : base = fold_offsetof_1 ( TREE_OPERAND ( expr , 0 ) , stop_ref ) ; gcc_assert ( base == error_mark_node || base == size_zero_node ) ; return base ; case COMPONENT_REF : base = fold_offsetof_1 ( TREE_OPERAND ( expr , 0 ) , stop_ref ) ; if ( base == error_mark_node ) return base ; t = TREE_OPERAND ( expr , 1 ) ; if ( DECL_C_BIT_FIELD ( t ) ) { error ( " " " " , t ) ; return error_mark_node ; } off = size_binop ( PLUS_EXPR , DECL_FIELD_OFFSET ( t ) , size_int ( tree_low_cst ( DECL_FIELD_BIT_OFFSET ( t ) , 1 ) / BITS_PER_UNIT ) ) ; break ; case ARRAY_REF : base = fold_offsetof_1 ( TREE_OPERAND ( expr , 0 ) , stop_ref ) ; if ( base == error_mark_node ) return base ; t = TREE_OPERAND ( expr , 1 ) ; if ( TREE_CODE ( t ) == INTEGER_CST && tree_int_cst_sgn ( t ) < 0 ) { code = MINUS_EXPR ; t = fold_build1 ( NEGATE_EXPR , TREE_TYPE ( t ) , t ) ; } t = convert ( sizetype , t ) ; off = size_binop ( MULT_EXPR , TYPE_SIZE_UNIT ( TREE_TYPE ( expr ) ) , t ) ; break ; case COMPOUND_EXPR : t = TREE_OPERAND ( expr , 1 ) ; gcc_assert ( TREE_CODE ( t ) == VAR_DECL ) ; return fold_offsetof_1 ( t , stop_ref ) ; default : gcc_unreachable ( ) ; } return size_binop ( code , base , off ) ; }
Build the result of __builtin_offsetof.
Build the result of __builtin_offsetof .
/* Handle static members of volatile structs.  */