This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

revised PATCH: CALL_EXPR representation changes, part 1/9 (tree.{h,c,def} changes)


2007-02-14  Sandra Loosemore  <sandra@codesourcery.com>
	    Brooks Moses  <brooks.moses@codesourcery.com>
	    Lee Millward  <lee.millward@codesourcery.com>

	* tree.h (enum tree_code_class): Add tcc_vl_exp.
	(VL_EXP_CLASS_P): New.
	(TREE_OPERAND_CHECK): Use TREE_OPERAND_LENGTH instead of
	TREE_CODE_LENGTH.
	(TREE_OPERAND_CHECK_CODE): Likewise.
	(GIMPLE_STMT_OPERAND_CHECK): Likewise.
	(TREE_RTL_OPERAND_CHECK): Likewise.
	(tree_operand_check_failed): Make second parameter the whole tree
	instead of its code.  Fixed callers.
	(VL_EXP_CHECK): New.
	(TREE_OPERAND_LENGTH): New.
	(VL_EXP_OPERAND_LENGTH): New.
	(CALL_EXPR_FN): New.
	(CALL_EXPR_STATIC_CHAIN): New.
	(CALL_EXPR_ARGS): New.
	(CALL_EXPR_ARG): New.
	(call_expr_nargs): New.
	(CALL_EXPR_ARGP): New.
	(build_nt_call_list): Declare.
	(build_vl_exp_stat): Declare.
	(build_vl_exp): New.
	(build_call_list): Declare.
	(build_call_nary): Declare.
	(build_call_valist): Declare.
	(build_call_array): Declare.
	(call_expr_arg): Declare.
	(call_expr_argp): Declare.
	(call_expr_arglist): Declare.
	(fold_build_call_list): Declare.
	(fold_build_call_list_initializer): Declare.
	(fold_call_expr): Declare to replace fold_builtin.
	(fold_builtin_fputs): Update to agree with modified definition.
	(fold_builtin_strcpy): Likewise.
	(fold_builtin_strncpy): Likewise.
	(fold_builtin_memory_chk): Likewise.
	(fold_builtin_stxcpy_chk): Likewise.
	(fold_builtin_strncpy_chk): Likewise.
	(fold_builtin_next_arg): Likewise.
	(fold_build_call_expr): Declare.
	(fold_builtin_call_list): Declare.
	(fold_builtin_call_valist): Declare.
	(build_call_expr): Declare.
	(validate_arglist): Update to agree with modified definition.
	(tree_operand_length): New.
	(call_expr_arg_iterator): New.
	(init_call_expr_arg_iterator): New.
	(next_call_expr_arg): New.
	(first_call_expr_arg): New.
	(more_call_expr_args_p): New.
	(FOR_EACH_CALL_EXPR_ARG): New.

	* tree.c (tree_code_class_string): Add entry for tcc_vl_exp.
	(tree_code_size): Update documentation.  Use sizeof (tree) rather
	than sizeof (char *).
	(tree_size): Likewise.  Add case for tcc_vl_exp.
	(tree_node_structure): Add case for tcc_vl_exp.
	(contains_placeholder_p): Likewise.
	(substitute_in_expr): Likewise.
	(substitute_placeholder_in_expr): Likewise.
	(stabilize_reference_1): Likewise.
	(build3_stat): Remove logic for CALL_EXPRs.  Replace with assertion
	to diagnose breakage of this interface for constructing CALL_EXPRs.
	(build_nt): Add similar assertion here.
	(build_nt_call_list): New.
	(simple_cst_equal) <CALL_EXPR>: Rewrite to use new accessors.
	(iterative_hash_expr): Use TREE_OPERAND_LENGTH instead of
	TREE_CODE_LENGTH.
	(get_callee_fndecl): Use new CALL_EXPR accessors.
	(tree_operand_check_failed): Change parameters to pass entire node
	instead of its code, so that we can call TREE_OPERAND_LENGTH on it.
	(process_call_operands): New.
	(build_vl_exp_stat): New.
	(build_call_list): New.
	(build_call_nary): New.
	(build_call_valist): New.
	(build_call_array): New.
	(walk_tree): Use TREE_OPERAND_LENGTH instead of TREE_CODE_LENGTH.
	(call_expr_arglist): New.

	* tree.def (CALL_EXPR): Change representation of CALL_EXPRs to use
	tcc_vl_exp instead of a fixed-size tcc_expression.

	* doc/c-tree.texi (CALL_EXPR): Document new representation and
	accessors for CALL_EXPRs.
	(AGGR_INIT_EXPR): Likewise.
Index: gcc/tree.h
===================================================================
*** gcc/tree.h	(revision 121818)
--- gcc/tree.h	(working copy)
*************** enum tree_code_class {
*** 64,69 ****
--- 64,71 ----
    tcc_binary,      /* A binary arithmetic expression.  */
    tcc_statement,   /* A statement expression, which have side effects
  		      but usually no interesting value.  */
+   tcc_vl_exp,      /* A function call or other expression with a
+ 		      variable-length operand vector.  */
    tcc_expression,  /* Any other expression.  */
    tcc_gimple_stmt  /* A GIMPLE statement.  */
  };
*************** extern const enum tree_code_class tree_c
*** 149,154 ****
--- 151,162 ----
  #define STATEMENT_CLASS_P(CODE)\
  	(TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_statement)
  
+ /* Nonzero if CODE represents a function call-like expression with a
+    variable-length operand vector.  */
+ 
+ #define VL_EXP_CLASS_P(CODE)\
+ 	(TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_vl_exp)
+ 
  /* Nonzero if CODE represents any other expression.  */
  
  #define EXPRESSION_CLASS_P(CODE)\
*************** enum tree_node_structure_enum {
*** 779,786 ****
      const int __i = (I);						\
      if (GIMPLE_TUPLE_P (__t))						\
        gcc_unreachable ();						\
!     if (__i < 0 || __i >= TREE_CODE_LENGTH (TREE_CODE (__t)))		\
!       tree_operand_check_failed (__i, TREE_CODE (__t),			\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->exp.operands[__i]; }))
  
--- 787,794 ----
      const int __i = (I);						\
      if (GIMPLE_TUPLE_P (__t))						\
        gcc_unreachable ();						\
!     if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))			\
!       tree_operand_check_failed (__i, __t,				\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->exp.operands[__i]; }))
  
*************** enum tree_node_structure_enum {
*** 789,796 ****
      const int __i = (I);						\
      if (TREE_CODE (__t) != CODE)					\
        tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0);\
!     if (__i < 0 || __i >= TREE_CODE_LENGTH (CODE))			\
!       tree_operand_check_failed (__i, (CODE),				\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->exp.operands[__i]; }))
  
--- 797,804 ----
      const int __i = (I);						\
      if (TREE_CODE (__t) != CODE)					\
        tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0);\
!     if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))			\
!       tree_operand_check_failed (__i, __t,				\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->exp.operands[__i]; }))
  
*************** enum tree_node_structure_enum {
*** 798,805 ****
  #define GIMPLE_STMT_OPERAND_CHECK(T, I) __extension__			\
  (*({const tree __t = GIMPLE_STMT_CHECK (T);				\
      const int __i = (I);						\
!     if (__i < 0 || __i >= TREE_CODE_LENGTH (TREE_CODE (__t)))		\
!       tree_operand_check_failed (__i, TREE_CODE (__t),			\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->gstmt.operands[__i]; }))
  
--- 806,813 ----
  #define GIMPLE_STMT_OPERAND_CHECK(T, I) __extension__			\
  (*({const tree __t = GIMPLE_STMT_CHECK (T);				\
      const int __i = (I);						\
!     if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))			\
!       tree_operand_check_failed (__i, __t,				\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->gstmt.operands[__i]; }))
  
*************** enum tree_node_structure_enum {
*** 809,816 ****
      const int __i = (I);						\
      if (TREE_CODE (__t) != (CODE))					\
        tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0); \
!     if (__i < 0 || __i >= TREE_CODE_LENGTH ((CODE)))			\
!       tree_operand_check_failed (__i, (CODE),				\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->exp.operands[__i]; }))
  
--- 817,824 ----
      const int __i = (I);						\
      if (TREE_CODE (__t) != (CODE))					\
        tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0); \
!     if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))			\
!       tree_operand_check_failed (__i, __t,				\
  				 __FILE__, __LINE__, __FUNCTION__);	\
      &__t->exp.operands[__i]; }))
  
*************** extern void tree_vec_elt_check_failed (i
*** 864,870 ****
  extern void phi_node_elt_check_failed (int, int, const char *,
  				       int, const char *)
      ATTRIBUTE_NORETURN;
! extern void tree_operand_check_failed (int, enum tree_code,
  				       const char *, int, const char *)
      ATTRIBUTE_NORETURN;
  extern void omp_clause_check_failed (const tree, const char *, int,
--- 872,878 ----
  extern void phi_node_elt_check_failed (int, int, const char *,
  				       int, const char *)
      ATTRIBUTE_NORETURN;
! extern void tree_operand_check_failed (int, tree,
  				       const char *, int, const char *)
      ATTRIBUTE_NORETURN;
  extern void omp_clause_check_failed (const tree, const char *, int,
*************** extern void omp_clause_range_check_faile
*** 924,929 ****
--- 932,938 ----
  #define DECL_NON_COMMON_CHECK(T) CONTAINS_STRUCT_CHECK (T, TS_DECL_NON_COMMON)
  #define CST_CHECK(T)		TREE_CLASS_CHECK (T, tcc_constant)
  #define STMT_CHECK(T)		TREE_CLASS_CHECK (T, tcc_statement)
+ #define VL_EXP_CHECK(T)		TREE_CLASS_CHECK (T, tcc_vl_exp)
  #define FUNC_OR_METHOD_CHECK(T)	TREE_CHECK2 (T, FUNCTION_TYPE, METHOD_TYPE)
  #define PTR_OR_REF_CHECK(T)	TREE_CHECK2 (T, POINTER_TYPE, REFERENCE_TYPE)
  
*************** struct tree_constructor GTY(())
*** 1497,1504 ****
--- 1506,1522 ----
  				 && integer_zerop (TREE_OPERAND (NODE, 0)))
  
  /* In ordinary expression nodes.  */
+ #define TREE_OPERAND_LENGTH(NODE) tree_operand_length (NODE)
  #define TREE_OPERAND(NODE, I) TREE_OPERAND_CHECK (NODE, I)
  
+ /* In a tcc_vl_exp node, operand 0 is an INT_CST node holding the operand
+    length.  Its value includes the length operand itself; that is,
+    the minimum valid length is 1.
+    Note that we have to bypass the use of TREE_OPERAND to access
+    that field to avoid infinite recursion in expanding the macros.  */
+ #define VL_EXP_OPERAND_LENGTH(NODE) \
+   ((int)TREE_INT_CST_LOW (VL_EXP_CHECK (NODE)->exp.operands[0]))
+ 
  /* In gimple statements.  */
  #define GIMPLE_STMT_OPERAND(NODE, I) GIMPLE_STMT_OPERAND_CHECK (NODE, I)
  #define GIMPLE_STMT_LOCUS(NODE) (GIMPLE_STMT_CHECK (NODE)->gstmt.locus)
*************** struct tree_constructor GTY(())
*** 1613,1618 ****
--- 1631,1653 ----
  #define ASSERT_EXPR_VAR(NODE)	TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 0)
  #define ASSERT_EXPR_COND(NODE)	TREE_OPERAND (ASSERT_EXPR_CHECK (NODE), 1)
  
+ /* CALL_EXPR accessors.
+  */
+ #define CALL_EXPR_FN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 1)
+ #define CALL_EXPR_STATIC_CHAIN(NODE) TREE_OPERAND (CALL_EXPR_CHECK (NODE), 2)
+ #define CALL_EXPR_ARGS(NODE) call_expr_arglist (NODE)
+ #define CALL_EXPR_ARG(NODE, I) TREE_OPERAND (CALL_EXPR_CHECK (NODE), (I) + 3)
+ #define call_expr_nargs(NODE) (VL_EXP_OPERAND_LENGTH(NODE) - 3)
+ 
+ /* CALL_EXPR_ARGP returns a pointer to the argument vector for NODE.
+    We can't use &CALL_EXPR_ARG (NODE, 0) because that will complain if
+    the argument count is zero when checking is enabled.  Instead, do
+    the pointer arithmetic to advance past the 3 fixed operands in a
+    CALL_EXPR.  That produces a valid pointer to just past the end of the
+    operand array, even if it's not valid to dereference it.  */
+ #define CALL_EXPR_ARGP(NODE) \
+   (&(TREE_OPERAND (CALL_EXPR_CHECK (NODE), 0)) + 3)
+ 
  /* OpenMP directive and clause accessors.  */
  
  #define OMP_BODY(NODE) \
*************** extern tree maybe_get_identifier (const 
*** 3620,3625 ****
--- 3655,3661 ----
  /* Construct various types of nodes.  */
  
  extern tree build_nt (enum tree_code, ...);
+ extern tree build_nt_call_list (tree, tree);
  
  extern tree build0_stat (enum tree_code, tree MEM_STAT_DECL);
  #define build0(c,t) build0_stat (c,t MEM_STAT_INFO)
*************** extern void annotate_with_locus (tree, l
*** 3670,3675 ****
--- 3706,3719 ----
  extern tree build_empty_stmt (void);
  extern tree build_omp_clause (enum omp_clause_code);
  
+ extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
+ #define build_vl_exp(c,n) build_vl_exp_stat (c,n MEM_STAT_INFO)
+ 
+ extern tree build_call_list (tree, tree, tree);
+ extern tree build_call_nary (tree, tree, int, ...);
+ extern tree build_call_valist (tree, tree, int, va_list);
+ extern tree build_call_array (tree, tree, int, tree*);
+ 
  /* Construct various nodes representing data types.  */
  
  extern tree make_signed_type (int);
*************** extern tree upper_bound_in_type (tree, t
*** 4266,4271 ****
--- 4310,4318 ----
  extern tree lower_bound_in_type (tree, tree);
  extern int operand_equal_for_phi_arg_p (tree, tree);
  extern bool empty_body_p (tree);
+ extern tree call_expr_arg (tree, int);
+ extern tree *call_expr_argp (tree, int);
+ extern tree call_expr_arglist (tree);
  
  /* In stmt.c */
  
*************** extern tree fold_build3_stat (enum tree_
*** 4307,4312 ****
--- 4354,4361 ----
  extern tree fold_build1_initializer (enum tree_code, tree, tree);
  extern tree fold_build2_initializer (enum tree_code, tree, tree, tree);
  extern tree fold_build3_initializer (enum tree_code, tree, tree, tree, tree);
+ extern tree fold_build_call_list (tree, tree, tree);
+ extern tree fold_build_call_list_initializer (tree, tree, tree);
  extern tree fold_convert (tree, tree);
  extern tree fold_single_bit_test (enum tree_code, tree, tree, tree);
  extern tree fold_ignored_result (tree);
*************** extern enum tree_code invert_tree_compar
*** 4386,4411 ****
  extern bool tree_expr_nonzero_p (tree);
  
  /* In builtins.c */
! extern tree fold_builtin (tree, tree, bool);
! extern tree fold_builtin_fputs (tree, bool, bool, tree);
! extern tree fold_builtin_strcpy (tree, tree, tree);
! extern tree fold_builtin_strncpy (tree, tree, tree);
! extern tree fold_builtin_memory_chk (tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_stxcpy_chk (tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_strncpy_chk (tree, tree);
  extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function);
! extern bool fold_builtin_next_arg (tree);
  extern enum built_in_function builtin_mathfn_code (tree);
  extern tree build_function_call_expr (tree, tree);
  extern tree mathfn_built_in (tree, enum built_in_function fn);
  extern tree strip_float_extensions (tree);
  extern tree c_strlen (tree, int);
  extern tree std_gimplify_va_arg_expr (tree, tree, tree *, tree *);
  extern tree build_va_arg_indirect_ref (tree);
  extern tree build_string_literal (int, const char *);
! extern int validate_arglist (tree, ...);
  extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  extern int get_pointer_alignment (tree, unsigned int);
  
--- 4435,4464 ----
  extern bool tree_expr_nonzero_p (tree);
  
  /* In builtins.c */
! extern tree fold_call_expr (tree, bool);
! extern tree fold_builtin_fputs (tree, tree, bool, bool, tree);
! extern tree fold_builtin_strcpy (tree, tree, tree, tree);
! extern tree fold_builtin_strncpy (tree, tree, tree, tree, tree);
! extern tree fold_builtin_memory_chk (tree, tree, tree, tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_stxcpy_chk (tree, tree, tree, tree, tree, bool,
  				     enum built_in_function);
! extern tree fold_builtin_strncpy_chk (tree, tree, tree, tree, tree);
  extern tree fold_builtin_snprintf_chk (tree, tree, enum built_in_function);
! extern bool fold_builtin_next_arg (tree, bool);
  extern enum built_in_function builtin_mathfn_code (tree);
  extern tree build_function_call_expr (tree, tree);
+ extern tree fold_build_call_expr (tree, tree, tree, tree);
+ extern tree fold_builtin_call_list (tree, tree, tree);
+ extern tree fold_builtin_call_valist (tree, tree, int, va_list);
+ extern tree build_call_expr (tree, int, ...);
  extern tree mathfn_built_in (tree, enum built_in_function fn);
  extern tree strip_float_extensions (tree);
  extern tree c_strlen (tree, int);
  extern tree std_gimplify_va_arg_expr (tree, tree, tree *, tree *);
  extern tree build_va_arg_indirect_ref (tree);
  extern tree build_string_literal (int, const char *);
! extern bool validate_arglist (tree, ...);
  extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
  extern int get_pointer_alignment (tree, unsigned int);
  
*************** extern unsigned HOST_WIDE_INT highest_po
*** 4759,4762 ****
--- 4812,4888 ----
  
  void init_inline_once (void);
  
+ /* Compute the number of operands in an expression node NODE.  For 
+    tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
+    otherwise it is looked up from the node's code.  */
+ static inline int
+ tree_operand_length (tree node)
+ {
+   if (VL_EXP_CLASS_P (node))
+     return VL_EXP_OPERAND_LENGTH (node);
+   else
+     return TREE_CODE_LENGTH (TREE_CODE (node));
+ }
+ 
+ /* Abstract iterators for CALL_EXPRs.  These static inline definitions
+    have to go towards the end of tree.h so that union tree_node is fully
+    defined by this point.  */
+ 
+ /* Structure containing iterator state.  */
+ typedef struct call_expr_arg_iterator_d GTY (())
+ {
+   tree t;	/* the call_expr */
+   int n;	/* argument count */
+   int i;	/* next argument index */
+ } call_expr_arg_iterator;
+ 
+ /* Initialize the abstract argument list iterator object ITER with the
+    arguments from CALL_EXPR node EXP.  */
+ static inline void
+ init_call_expr_arg_iterator (tree exp, call_expr_arg_iterator *iter)
+ {
+   iter->t = exp;
+   iter->n = call_expr_nargs (exp);
+   iter->i = 0;
+ }
+ 
+ /* Return the next argument from abstract argument list iterator object ITER,
+    and advance its state.  Return NULL_TREE if there are no more arguments.  */
+ static inline tree
+ next_call_expr_arg (call_expr_arg_iterator *iter)
+ {
+   tree result;
+   if (iter->i >= iter->n)
+     return NULL_TREE;
+   result = CALL_EXPR_ARG (iter->t, iter->i);
+   iter->i++;
+   return result;
+ }
+ 
+ /* Initialize the abstract argument list iterator object ITER, then advance
+    past and return the first argument.  Useful in for expressions, e.g.
+      for (arg = first_call_expr_arg (exp, &iter); arg;
+           arg = next_call_expr_arg (&iter))   */
+ static inline tree
+ first_call_expr_arg (tree exp, call_expr_arg_iterator *iter)
+ {
+   init_call_expr_arg_iterator (exp, iter);
+   return next_call_expr_arg (iter);
+ }
+ 
+ /* Test whether there are more arguments in abstract argument list iterator
+    ITER, without changing its state.  */
+ static inline bool
+ more_call_expr_args_p (const call_expr_arg_iterator *iter)
+ {
+   return (iter->i < iter->n);
+ }
+ 
+ 
+ /* Iterate through each argument ARG of CALL_EXPR CALL, using variable ITER
+    (of type call_expr_arg_iterator) to hold the iteration state.  */
+ #define FOR_EACH_CALL_EXPR_ARG(arg, iter, call)			\
+   for ((arg) = first_call_expr_arg ((call), &(iter)); (arg);	\
+        (arg) = next_call_expr_arg (&(iter)))
+ 
  #endif  /* GCC_TREE_H  */
Index: gcc/tree.c
===================================================================
*** gcc/tree.c	(revision 121818)
--- gcc/tree.c	(working copy)
*************** const char *const tree_code_class_string
*** 66,71 ****
--- 66,72 ----
    "unary",
    "binary",
    "statement",
+   "call",
    "expression",
  };
  
*************** decl_assembler_name_equal (tree decl, tr
*** 337,344 ****
  }
  
  /* Compute the number of bytes occupied by a tree with code CODE.
!    This function cannot be used for TREE_VEC, PHI_NODE, or STRING_CST
!    codes, which are of variable length.  */
  size_t
  tree_code_size (enum tree_code code)
  {
--- 338,345 ----
  }
  
  /* Compute the number of bytes occupied by a tree with code CODE.
!    This function cannot be used for nodes that have variable sizes,
!    including TREE_VEC, PHI_NODE, STRING_CST, and CALL_EXPR.  */
  size_t
  tree_code_size (enum tree_code code)
  {
*************** tree_code_size (enum tree_code code)
*** 386,392 ****
      case tcc_unary:       /* a unary arithmetic expression */
      case tcc_binary:      /* a binary arithmetic expression */
        return (sizeof (struct tree_exp)
! 	      + (TREE_CODE_LENGTH (code) - 1) * sizeof (char *));
  
      case tcc_gimple_stmt:
        return (sizeof (struct gimple_stmt)
--- 387,393 ----
      case tcc_unary:       /* a unary arithmetic expression */
      case tcc_binary:      /* a binary arithmetic expression */
        return (sizeof (struct tree_exp)
! 	      + (TREE_CODE_LENGTH (code) - 1) * sizeof (tree));
  
      case tcc_gimple_stmt:
        return (sizeof (struct gimple_stmt)
*************** tree_code_size (enum tree_code code)
*** 434,440 ****
  }
  
  /* Compute the number of bytes occupied by NODE.  This routine only
!    looks at TREE_CODE, except for PHI_NODE and TREE_VEC nodes.  */
  size_t
  tree_size (tree node)
  {
--- 435,441 ----
  }
  
  /* Compute the number of bytes occupied by NODE.  This routine only
!    looks at TREE_CODE, except for those nodes that have variable sizes.  */
  size_t
  tree_size (tree node)
  {
*************** tree_size (tree node)
*** 451,457 ****
  
      case TREE_VEC:
        return (sizeof (struct tree_vec)
! 	      + (TREE_VEC_LENGTH (node) - 1) * sizeof(char *));
  
      case STRING_CST:
        return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1;
--- 452,458 ----
  
      case TREE_VEC:
        return (sizeof (struct tree_vec)
! 	      + (TREE_VEC_LENGTH (node) - 1) * sizeof (tree));
  
      case STRING_CST:
        return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1;
*************** tree_size (tree node)
*** 462,468 ****
  	        * sizeof (tree));
  
      default:
!       return tree_code_size (code);
      }
  }
  
--- 463,473 ----
  	        * sizeof (tree));
  
      default:
!       if (TREE_CODE_CLASS (code) == tcc_vl_exp)
! 	return (sizeof (struct tree_exp)
! 		+ (VL_EXP_OPERAND_LENGTH (node) - 1) * sizeof (tree));
!       else
! 	return tree_code_size (code);
      }
  }
  
*************** tree_node_structure (tree t)
*** 2166,2171 ****
--- 2171,2177 ----
      case tcc_binary:
      case tcc_expression:
      case tcc_statement:
+     case tcc_vl_exp:
        return TS_EXP;
      case tcc_gimple_stmt:
        return TS_GIMPLE_STATEMENT;
*************** contains_placeholder_p (tree exp)
*** 2247,2255 ****
  		  || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
  		  || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
  
- 	case CALL_EXPR:
- 	  return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
- 
  	default:
  	  break;
  	}
--- 2253,2258 ----
*************** contains_placeholder_p (tree exp)
*** 2265,2270 ****
--- 2268,2289 ----
  	  return 0;
  	}
  
+     case tcc_vl_exp:
+       switch (code)
+ 	{
+ 	case CALL_EXPR:
+ 	  {
+ 	    tree arg;
+ 	    call_expr_arg_iterator iter;
+ 	    FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
+ 	      if (CONTAINS_PLACEHOLDER_P (arg))
+ 		return 1;
+ 	    return 0;
+ 	  }
+ 	default:
+ 	  return 0;
+ 	}
+ 
      default:
        return 0;
      }
*************** substitute_in_expr (tree exp, tree f, tr
*** 2472,2477 ****
--- 2491,2517 ----
  	  }
  	break;
  
+       case tcc_vl_exp:
+ 	{
+ 	  tree copy = NULL_TREE;
+ 	  int i;
+ 	  int n = TREE_OPERAND_LENGTH (exp);
+ 	  for (i = 1; i < n; i++)
+ 	    {
+ 	      tree op = TREE_OPERAND (exp, i);
+ 	      tree newop = SUBSTITUTE_IN_EXPR (op, f, r);
+ 	      if (newop != op)
+ 		{
+ 		  copy = copy_node (exp);
+ 		  TREE_OPERAND (copy, i) = newop;
+ 		}
+ 	    }
+ 	  if (copy)
+ 	    new = fold (copy);
+ 	  else
+ 	    return exp;
+ 	}
+ 
        default:
  	gcc_unreachable ();
        }
*************** substitute_placeholder_in_expr (tree exp
*** 2503,2508 ****
--- 2543,2549 ----
  		  : (REFERENCE_CLASS_P (elt)
  		     || UNARY_CLASS_P (elt)
  		     || BINARY_CLASS_P (elt)
+ 		     || VL_EXP_CLASS_P (elt)
  		     || EXPRESSION_CLASS_P (elt))
  		  ? TREE_OPERAND (elt, 0) : 0))
  	if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
*************** substitute_placeholder_in_expr (tree exp
*** 2515,2520 ****
--- 2556,2562 ----
  		  : (REFERENCE_CLASS_P (elt)
  		     || UNARY_CLASS_P (elt)
  		     || BINARY_CLASS_P (elt)
+ 		     || VL_EXP_CLASS_P (elt)
  		     || EXPRESSION_CLASS_P (elt))
  		  ? TREE_OPERAND (elt, 0) : 0))
  	if (POINTER_TYPE_P (TREE_TYPE (elt))
*************** substitute_placeholder_in_expr (tree exp
*** 2602,2607 ****
--- 2644,2671 ----
  	  }
  	break;
  
+       case tcc_vl_exp:
+ 	{
+ 	  tree copy = NULL_TREE;
+ 	  int i;
+ 	  int n = TREE_OPERAND_LENGTH (exp);
+ 	  for (i = 1; i < n; i++)
+ 	    {
+ 	      tree op = TREE_OPERAND (exp, i);
+ 	      tree newop = SUBSTITUTE_PLACEHOLDER_IN_EXPR (op, obj);
+ 	      if (newop != op)
+ 		{
+ 		  if (!copy)
+ 		    copy = copy_node (exp);
+ 		  TREE_OPERAND (copy, i) = newop;
+ 		}
+ 	    }
+ 	  if (copy)
+ 	    return fold (copy);
+ 	  else
+ 	    return exp;
+ 	}
+ 
        default:
  	gcc_unreachable ();
        }
*************** stabilize_reference_1 (tree e)
*** 2727,2732 ****
--- 2791,2797 ----
      case tcc_statement:
      case tcc_expression:
      case tcc_reference:
+     case tcc_vl_exp:
        /* If the expression has side-effects, then encase it in a SAVE_EXPR
  	 so that it will only be evaluated once.  */
        /* The reference (r) and comparison (<) classes could be handled as
*************** build3_stat (enum tree_code code, tree t
*** 3074,3079 ****
--- 3139,3145 ----
    tree t;
  
    gcc_assert (TREE_CODE_LENGTH (code) == 3);
+   gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
  
    t = make_node_stat (code PASS_MEM_STAT);
    TREE_TYPE (t) = tt;
*************** build3_stat (enum tree_code code, tree t
*** 3084,3109 ****
    PROCESS_ARG(1);
    PROCESS_ARG(2);
  
-   if (code == CALL_EXPR && !side_effects)
-     {
-       tree node;
-       int i;
- 
-       /* Calls have side-effects, except those to const or
- 	 pure functions.  */
-       i = call_expr_flags (t);
-       if (!(i & (ECF_CONST | ECF_PURE)))
- 	side_effects = 1;
- 
-       /* And even those have side-effects if their arguments do.  */
-       else for (node = arg1; node; node = TREE_CHAIN (node))
- 	if (TREE_SIDE_EFFECTS (TREE_VALUE (node)))
- 	  {
- 	    side_effects = 1;
- 	    break;
- 	  }
-     }
- 
    TREE_SIDE_EFFECTS (t) = side_effects;
    TREE_THIS_VOLATILE (t)
      = (TREE_CODE_CLASS (code) == tcc_reference
--- 3150,3155 ----
*************** build_nt (enum tree_code code, ...)
*** 3209,3214 ****
--- 3255,3262 ----
    int i;
    va_list p;
  
+   gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);
+ 
    va_start (p, code);
  
    t = make_node (code);
*************** build_nt (enum tree_code code, ...)
*** 3220,3225 ****
--- 3268,3290 ----
    va_end (p);
    return t;
  }
+ 
+ /* Similar to build_nt, but for creating a CALL_EXPR object with
+    ARGLIST passed as a list.  */
+ 
+ tree
+ build_nt_call_list (tree fn, tree arglist)
+ {
+   tree t;
+   int i;
+ 
+   t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3);
+   CALL_EXPR_FN (t) = fn;
+   CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
+   for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++)
+     CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
+   return t;
+ }
  
  /* Create a DECL_... node of code CODE, name NAME and data type TYPE.
     We do NOT enter this node in any sort of symbol table.
*************** simple_cst_equal (tree t1, tree t2)
*** 4916,4926 ****
        return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
  
      case CALL_EXPR:
!       cmp = simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
        if (cmp <= 0)
  	return cmp;
!       return
! 	simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
  
      case TARGET_EXPR:
        /* Special case: if either target is an unallocated VAR_DECL,
--- 4981,5003 ----
        return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
  
      case CALL_EXPR:
!       cmp = simple_cst_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2));
        if (cmp <= 0)
  	return cmp;
!       if (call_expr_nargs (t1) != call_expr_nargs (t2))
! 	return 0;
!       {
! 	tree arg1, arg2;
! 	call_expr_arg_iterator iter1, iter2;
! 	for (arg1 = first_call_expr_arg (t1, &iter1),
! 	       arg2 = first_call_expr_arg (t2, &iter2);
! 	     arg1 && arg2;
! 	     arg1 = next_call_expr_arg (&iter1),
! 	       arg2 = next_call_expr_arg (&iter2))
! 	  if (simple_cst_equal (arg1, arg2) != 1)
! 	    return 0;
! 	return arg1 == arg2;
!       }
  
      case TARGET_EXPR:
        /* Special case: if either target is an unallocated VAR_DECL,
*************** iterative_hash_expr (tree t, hashval_t v
*** 5184,5190 ****
  	      val = iterative_hash_hashval_t (two, val);
  	    }
  	  else
! 	    for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; --i)
  	      val = iterative_hash_expr (TREE_OPERAND (t, i), val);
  	}
        return val;
--- 5261,5267 ----
  	      val = iterative_hash_hashval_t (two, val);
  	    }
  	  else
! 	    for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i)
  	      val = iterative_hash_expr (TREE_OPERAND (t, i), val);
  	}
        return val;
*************** get_callee_fndecl (tree call)
*** 6246,6252 ****
  
    /* The first operand to the CALL is the address of the function
       called.  */
!   addr = TREE_OPERAND (call, 0);
  
    STRIP_NOPS (addr);
  
--- 6323,6329 ----
  
    /* The first operand to the CALL is the address of the function
       called.  */
!   addr = CALL_EXPR_FN (call);
  
    STRIP_NOPS (addr);
  
*************** phi_node_elt_check_failed (int idx, int 
*** 6665,6679 ****
  }
  
  /* Similar to above, except that the check is for the bounds of the operand
!    vector of an expression node.  */
  
  void
! tree_operand_check_failed (int idx, enum tree_code code, const char *file,
  			   int line, const char *function)
  {
    internal_error
      ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d",
!      idx + 1, tree_code_name[code], TREE_CODE_LENGTH (code),
       function, trim_filename (file), line);
  }
  
--- 6742,6757 ----
  }
  
  /* Similar to above, except that the check is for the bounds of the operand
!    vector of an expression node EXP.  */
  
  void
! tree_operand_check_failed (int idx, tree exp, const char *file,
  			   int line, const char *function)
  {
+   int code = TREE_CODE (exp);
    internal_error
      ("tree check: accessed operand %d of %s with %d operands in %s, at %s:%d",
!      idx + 1, tree_code_name[code], TREE_OPERAND_LENGTH (exp),
       function, trim_filename (file), line);
  }
  
*************** build_omp_clause (enum omp_clause_code c
*** 7305,7310 ****
--- 7383,7531 ----
    return t;
  }
  
+ /* Set various status flags when building a CALL_EXPR object T.  */
+ 
+ static void
+ process_call_operands (tree t)
+ {
+   bool side_effects;
+ 
+   side_effects = TREE_SIDE_EFFECTS (t);
+   if (!side_effects)
+     {
+       int i, n;
+       n = TREE_OPERAND_LENGTH (t);
+       for (i = 1; i < n; i++)
+ 	{
+ 	  tree op = TREE_OPERAND (t, i);
+ 	  if (op && TREE_SIDE_EFFECTS (op))
+ 	    {
+ 	      side_effects = 1;
+ 	      break;
+ 	    }
+ 	}
+     }
+   if (!side_effects)
+     {
+       int i;
+ 
+       /* Calls have side-effects, except those to const or
+ 	 pure functions.  */
+       i = call_expr_flags (t);
+       if (!(i & (ECF_CONST | ECF_PURE)))
+ 	side_effects = 1;
+     }
+   TREE_SIDE_EFFECTS (t) = side_effects;
+ }
+ 
+ /* Build a tcc_vl_exp object with code CODE and room for LEN operands.  LEN
+    includes the implicit operand count in TREE_OPERAND 0, and so must be >= 1.
+    Except for the CODE and operand count field, other storage for the
+    object is initialized to zeros.  */
+ 
+ tree
+ build_vl_exp_stat (enum tree_code code, int len MEM_STAT_DECL)
+ {
+   tree t;
+   int length = (len - 1) * sizeof (tree) + sizeof (struct tree_exp);
+ 
+   gcc_assert (TREE_CODE_CLASS (code) == tcc_vl_exp);
+   gcc_assert (len >= 1);
+ 
+ #ifdef GATHER_STATISTICS
+   tree_node_counts[(int) e_kind]++;
+   tree_node_sizes[(int) e_kind] += length;
+ #endif
+ 
+   t = ggc_alloc_zone_pass_stat (length, &tree_zone);
+ 
+   memset (t, 0, length);
+ 
+   TREE_SET_CODE (t, code);
+ 
+   /* Can't use TREE_OPERAND to store the length because if checking is
+      enabled, it will try to check the length before we store it.  :-P  */
+   t->exp.operands[0] = build_int_cst (sizetype, len);
+ 
+   return t;
+ }
+ 
+ 
+ /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE
+    and FN and a null static chain slot.  ARGLIST is a TREE_LIST of the
+    arguments.  */
+ 
+ tree
+ build_call_list (tree return_type, tree fn, tree arglist)
+ {
+   tree t;
+   int i;
+ 
+   t = build_vl_exp (CALL_EXPR, list_length (arglist) + 3);
+   TREE_TYPE (t) = return_type;
+   CALL_EXPR_FN (t) = fn;
+   CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
+   for (i = 0; arglist; arglist = TREE_CHAIN (arglist), i++)
+     CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
+   process_call_operands (t);
+   return t;
+ }
+ 
+ /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
+    FN and a null static chain slot.  NARGS is the number of call arguments
+    which are specified as "..." arguments.  */
+ 
+ tree
+ build_call_nary (tree return_type, tree fn, int nargs, ...)
+ {
+   tree ret;
+   va_list args;
+   va_start (args, nargs);
+   ret = build_call_valist (return_type, fn, nargs, args);
+   va_end (args);
+   return ret;
+ }
+ 
+ /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
+    FN and a null static chain slot.  NARGS is the number of call arguments
+    which are specified as a va_list ARGS.  */
+ 
+ tree
+ build_call_valist (tree return_type, tree fn, int nargs, va_list args)
+ {
+   tree t;
+   int i;
+ 
+   t = build_vl_exp (CALL_EXPR, nargs + 3);
+   TREE_TYPE (t) = return_type;
+   CALL_EXPR_FN (t) = fn;
+   CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
+   for (i = 0; i < nargs; i++)
+     CALL_EXPR_ARG (t, i) = va_arg (args, tree);
+   process_call_operands (t);
+   return t;
+ }
+ 
+ /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
+    FN and a null static chain slot.  NARGS is the number of call arguments
+    which are specified as a tree array ARGS.  */
+ 
+ tree
+ build_call_array (tree return_type, tree fn, int nargs, tree *args)
+ {
+   tree t;
+   int i;
+ 
+   t = build_vl_exp (CALL_EXPR, nargs + 3);
+   TREE_TYPE (t) = return_type;
+   CALL_EXPR_FN (t) = fn;
+   CALL_EXPR_STATIC_CHAIN (t) = NULL_TREE;
+   for (i = 0; i < nargs; i++)
+     CALL_EXPR_ARG (t, i) = args[i];
+   process_call_operands (t);
+   return t;
+ }
+ 
  
  /* Returns true if it is possible to prove that the index of
     an array access REF (an ARRAY_REF expression) falls into the
*************** walk_tree (tree *tp, walk_tree_fn func, 
*** 7988,7994 ****
  	  int i, len;
  
  	  /* Walk over all the sub-trees of this operand.  */
! 	  len = TREE_CODE_LENGTH (code);
  
  	  /* Go through the subtrees.  We need to do this in forward order so
  	     that the scope of a FOR_EXPR is handled properly.  */
--- 8209,8215 ----
  	  int i, len;
  
  	  /* Walk over all the sub-trees of this operand.  */
! 	  len = TREE_OPERAND_LENGTH (*tp);
  
  	  /* Go through the subtrees.  We need to do this in forward order so
  	     that the scope of a FOR_EXPR is handled properly.  */
*************** generic_tree_type (tree node)
*** 8081,8084 ****
--- 8302,8320 ----
    return &TREE_TYPE (node);
  }
  
+ /* Build and return a TREE_LIST of arguments in the CALL_EXPR exp.
+    FIXME: don't use this function.  It exists for compatibility with
+    the old representation of CALL_EXPRs where a list was used to hold the
+    arguments.  Places that currently extract the arglist from a CALL_EXPR
+    ought to be rewritten to use the CALL_EXPR itself.  */
+ tree
+ call_expr_arglist (tree exp)
+ {
+   tree arglist = NULL_TREE;
+   int i;
+   for (i = call_expr_nargs (exp) - 1; i >= 0; i--)
+     arglist = tree_cons (NULL_TREE, CALL_EXPR_ARG (exp, i), arglist);
+   return arglist;
+ }
+ 
  #include "gt-tree.h"
Index: gcc/tree.def
===================================================================
*** gcc/tree.def	(revision 121818)
--- gcc/tree.def	(working copy)
*************** DEFTREECODE (VEC_COND_EXPR, "vec_cond_ex
*** 523,533 ****
     nodes for the function.  */
  DEFTREECODE (BIND_EXPR, "bind_expr", tcc_expression, 3)
  
! /* Function call.  Operand 0 is the function.
!    Operand 1 is the argument list, a list of expressions
!    made out of a chain of TREE_LIST nodes.
!    Operand 2 is the static chain argument, or NULL.  */
! DEFTREECODE (CALL_EXPR, "call_expr", tcc_expression, 3)
  
  /* Specify a value to compute along with its corresponding cleanup.
     Operand 0 is the cleanup expression.
--- 523,535 ----
     nodes for the function.  */
  DEFTREECODE (BIND_EXPR, "bind_expr", tcc_expression, 3)
  
! /* Function call.  CALL_EXPRs are represented by variably-sized expression
!    nodes.  There are at least three fixed operands.  Operand 0 is an
!    INTEGER_CST node containing the total operand count, the number of
!    arguments plus 3.  Operand 1 is the function, while operand 2 is
!    is static chain argument, or NULL.  The remaining operands are the
!    arguments to the call.  */
! DEFTREECODE (CALL_EXPR, "call_expr", tcc_vl_exp, 3)
  
  /* Specify a value to compute along with its corresponding cleanup.
     Operand 0 is the cleanup expression.
Index: gcc/doc/c-tree.texi
===================================================================
*** gcc/doc/c-tree.texi	(revision 121818)
--- gcc/doc/c-tree.texi	(working copy)
*************** argument does cause side-effects.
*** 2474,2492 ****
  
  @item CALL_EXPR
  These nodes are used to represent calls to functions, including
! non-static member functions.  The first operand is a pointer to the
  function to call; it is always an expression whose type is a
! @code{POINTER_TYPE}.  The second argument is a @code{TREE_LIST}.  The
! arguments to the call appear left-to-right in the list.  The
! @code{TREE_VALUE} of each list node contains the expression
! corresponding to that argument.  (The value of @code{TREE_PURPOSE} for
! these nodes is unspecified, and should be ignored.)  For non-static
  member functions, there will be an operand corresponding to the
  @code{this} pointer.  There will always be expressions corresponding to
  all of the arguments, even if the function is declared with default
  arguments and some arguments are not explicitly provided at the call
  sites.
  
  @item STMT_EXPR
  These nodes are used to represent GCC's statement-expression extension.
  The statement-expression extension allows code like this:
--- 2474,2512 ----
  
  @item CALL_EXPR
  These nodes are used to represent calls to functions, including
! non-static member functions.  @code{CALL_EXPR}s are implemented as
! expression nodes with a variable number of operands.  Rather than using
! @code{TREE_OPERAND} to extract them, it is preferable to use the
! specialized accessor macros and functions that operate specifically on
! @code{CALL_EXPR} nodes.
! 
! @code{CALL_EXPR_FN} returns a pointer to the
  function to call; it is always an expression whose type is a
! @code{POINTER_TYPE}.
! 
! The number of arguments to the call is returned by @code{call_expr_nargs},
! while the arguments themselves can be accessed with the @code{CALL_EXPR_ARG} 
! macro.  The arguments are zero-indexed and numbered left-to-right.  
! You can iterate over the arguments using @code{FOR_EACH_CALL_EXPR_ARG}, as in:
! 
! @smallexample
! tree call, arg;
! call_expr_arg_iterator iter;
! FOR_EACH_CALL_EXPR_ARG (arg, iter, call)
!   /* arg is bound to successive arguments of call.  */
!   ...;
! @end smallexample
! 
! For non-static
  member functions, there will be an operand corresponding to the
  @code{this} pointer.  There will always be expressions corresponding to
  all of the arguments, even if the function is declared with default
  arguments and some arguments are not explicitly provided at the call
  sites.
  
+ @code{CALL_EXPR}s also have a @code{CALL_EXPR_STATIC_CHAIN} operand that
+ is used to implement nested functions.  This operand is otherwise null.
+ 
  @item STMT_EXPR
  These nodes are used to represent GCC's statement-expression extension.
  The statement-expression extension allows code like this:
*************** cleanups.
*** 2613,2627 ****
  An @code{AGGR_INIT_EXPR} represents the initialization as the return
  value of a function call, or as the result of a constructor.  An
  @code{AGGR_INIT_EXPR} will only appear as a full-expression, or as the
! second operand of a @code{TARGET_EXPR}.  The first operand to the
! @code{AGGR_INIT_EXPR} is the address of a function to call, just as in
! a @code{CALL_EXPR}.  The second operand are the arguments to pass that
! function, as a @code{TREE_LIST}, again in a manner similar to that of
! a @code{CALL_EXPR}.
  
  If @code{AGGR_INIT_VIA_CTOR_P} holds of the @code{AGGR_INIT_EXPR}, then
! the initialization is via a constructor call.  The address of the third
! operand of the @code{AGGR_INIT_EXPR}, which is always a @code{VAR_DECL},
  is taken, and this value replaces the first argument in the argument
  list.
  
--- 2633,2646 ----
  An @code{AGGR_INIT_EXPR} represents the initialization as the return
  value of a function call, or as the result of a constructor.  An
  @code{AGGR_INIT_EXPR} will only appear as a full-expression, or as the
! second operand of a @code{TARGET_EXPR}.  @code{AGGR_INIT_EXPR}s have
! a representation similar to that of @code{CALL_EXPR}s.  You can use
! the @code{AGGR_INIT_EXPR_FN} and @code{AGGR_INIT_EXPR_ARG} macros to access
! the function to call and the arguments to pass.
  
  If @code{AGGR_INIT_VIA_CTOR_P} holds of the @code{AGGR_INIT_EXPR}, then
! the initialization is via a constructor call.  The address of the
! @code{AGGR_INIT_EXPR_SLOT} operand, which is always a @code{VAR_DECL},
  is taken, and this value replaces the first argument in the argument
  list.
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]