Makefile.in (LIBGCOV): Add _gcov_fork...
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Fri, 23 Apr 2004 22:50:16 +0000 (00:50 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Fri, 23 Apr 2004 22:50:16 +0000 (22:50 +0000)
* Makefile.in (LIBGCOV): Add _gcov_fork, _gcov_execl, _gcov_execlp,
_gcov_execle, _gcov_execv, _gcov_execvp, _gcov_execve.
* builtin-types.def (BT_PID, BT_PTR_CONST_STRING, BT_FN_PID,
BT_FN_INT_CONST_STRING_PTR_CONST_STRING,
BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING): New.
* builtins.c (expand_builtin_fork_or_exec): New.
(expand_builtin): Call it.
* builtins.def (BUILT_IN_EXECL, BUILT_IN_EXECLP,BUILT_IN_EXECLE,
BUILT_IN_EXECV, BUILT_IN_EXECVP, BUILT_IN_EXECVE, BUILT_IN_FORK): New.
* c-common.c (PID_TYPE): New macro.
(c_common_nodes_and_builtins): Initialize pid_type_node.
* calls.c (special_function_p): Do not handle fork and exec.
(expand_call): Do not handle ECF_FORK_OR_EXEC.
* gcov-io.h (__gcov_fork, __gcov_execl, __gcov_execlp, __gcov_execle,
__gcov_execv, __gcov_execvp, __gcov_execve): Declare.
* libgcov.c (__gcov_fork, __gcov_execl, __gcov_execlp, __gcov_execle,
__gcov_execv, __gcov_execvp, __gcov_execve): New.
* tree.h (enum tree_index): Add TI_PID_TYPE.
(pid_type_node): New macro.
(ECF_FORK_OR_EXEC): Removed.

From-SVN: r81118

gcc/ChangeLog
gcc/Makefile.in
gcc/builtin-types.def
gcc/builtins.c
gcc/builtins.def
gcc/c-common.c
gcc/calls.c
gcc/gcov-io.h
gcc/libgcov.c
gcc/tree.h

index 9c99787..e910151 100644 (file)
@@ -1,3 +1,26 @@
+2004-03-23  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
+
+       * Makefile.in (LIBGCOV): Add _gcov_fork, _gcov_execl, _gcov_execlp,
+       _gcov_execle, _gcov_execv, _gcov_execvp, _gcov_execve.
+       * builtin-types.def (BT_PID, BT_PTR_CONST_STRING, BT_FN_PID,
+       BT_FN_INT_CONST_STRING_PTR_CONST_STRING,
+       BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING): New.
+       * builtins.c (expand_builtin_fork_or_exec): New.
+       (expand_builtin): Call it.
+       * builtins.def (BUILT_IN_EXECL, BUILT_IN_EXECLP,BUILT_IN_EXECLE,
+       BUILT_IN_EXECV, BUILT_IN_EXECVP, BUILT_IN_EXECVE, BUILT_IN_FORK): New.
+       * c-common.c (PID_TYPE): New macro.
+       (c_common_nodes_and_builtins): Initialize pid_type_node.
+       * calls.c (special_function_p): Do not handle fork and exec.
+       (expand_call): Do not handle ECF_FORK_OR_EXEC.
+       * gcov-io.h (__gcov_fork, __gcov_execl, __gcov_execlp, __gcov_execle,
+       __gcov_execv, __gcov_execvp, __gcov_execve): Declare.
+       * libgcov.c (__gcov_fork, __gcov_execl, __gcov_execlp, __gcov_execle,
+       __gcov_execv, __gcov_execvp, __gcov_execve): New.
+       * tree.h (enum tree_index): Add TI_PID_TYPE.
+       (pid_type_node): New macro.
+       (ECF_FORK_OR_EXEC): Removed.
+
 2004-04-23  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR optimization/13985
index 43a2e33..4b718d5 100644 (file)
@@ -905,7 +905,9 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \
 LIB2FUNCS_ST = _eprintf __gcc_bcmp
 
 # Defined in libgcov.c, included only in gcov library
-LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta
+LIBGCOV = _gcov _gcov_merge_add _gcov_merge_single _gcov_merge_delta \
+    _gcov_fork _gcov_execl _gcov_execlp _gcov_execle \
+    _gcov_execv _gcov_execvp _gcov_execve
 
 FPBIT_FUNCS = _pack_sf _unpack_sf _addsub_sf _mul_sf _div_sf \
     _fpcmp_parts_sf _compare_sf _eq_sf _ne_sf _gt_sf _ge_sf \
index 81fdeb1..c6cf5d3 100644 (file)
@@ -80,6 +80,7 @@ DEF_PRIMITIVE_TYPE (BT_INT_PTR, integer_ptr_type_node)
 DEF_PRIMITIVE_TYPE (BT_FLOAT_PTR, float_ptr_type_node)
 DEF_PRIMITIVE_TYPE (BT_DOUBLE_PTR, double_ptr_type_node)
 DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE_PTR, long_double_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_PID, pid_type_node)
 DEF_PRIMITIVE_TYPE (BT_SIZE, size_type_node)
 DEF_PRIMITIVE_TYPE (BT_SSIZE, signed_size_type_node)
 DEF_PRIMITIVE_TYPE (BT_WINT, wint_type_node)
@@ -89,8 +90,11 @@ DEF_PRIMITIVE_TYPE (BT_CONST_STRING, const_string_type_node)
 DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node)
 DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node)
 
+DEF_POINTER_TYPE (BT_PTR_CONST_STRING, BT_CONST_STRING)
+
 DEF_FUNCTION_TYPE_0 (BT_FN_VOID, BT_VOID)
 DEF_FUNCTION_TYPE_0 (BT_FN_PTR, BT_PTR)
+DEF_FUNCTION_TYPE_0 (BT_FN_PID, BT_PID)
 DEF_FUNCTION_TYPE_0 (BT_FN_UNSIGNED, BT_UNSIGNED)
 DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT, BT_FLOAT)
 DEF_FUNCTION_TYPE_0 (BT_FN_DOUBLE, BT_DOUBLE)
@@ -223,6 +227,8 @@ DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
                     BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE)
 DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, 
                     BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_PTR_CONST_STRING,
+                    BT_INT, BT_CONST_STRING, BT_PTR_CONST_STRING)
 
 DEF_FUNCTION_TYPE_3 (BT_FN_STRING_STRING_CONST_STRING_SIZE,
                     BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE)
@@ -264,6 +270,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_DOUBLE_DOUBLEPTR_DOUBLEPTR,
                     BT_VOID, BT_DOUBLE, BT_DOUBLE_PTR, BT_DOUBLE_PTR)
 DEF_FUNCTION_TYPE_3 (BT_FN_VOID_LONGDOUBLE_LONGDOUBLEPTR_LONGDOUBLEPTR,
                     BT_VOID, BT_LONGDOUBLE, BT_LONGDOUBLE_PTR, BT_LONGDOUBLE_PTR)
+DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING,
+                    BT_INT, BT_CONST_STRING, BT_PTR_CONST_STRING, BT_PTR_CONST_STRING)
 
 DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR,
                     BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_PTR)
index c7627c0..7c6cae1 100644 (file)
@@ -5081,6 +5081,69 @@ expand_builtin_signbit (tree exp, rtx target)
     }
   return temp;
 }
+
+/* Expand fork or exec calls.  TARGET is the desired target of the
+   call.  ARGLIST is the list of arguments of the call.  FN is the
+   identificator of the actual function.  IGNORE is nonzero if the
+   value is to be ignored.  */
+
+static rtx
+expand_builtin_fork_or_exec (tree fn, tree arglist, rtx target, int ignore)
+{
+  tree id, decl;
+  tree call;
+
+  /* If we are not profiling, just call the function.  */
+  if (!profile_arc_flag)
+    return NULL_RTX;
+
+  /* Otherwise call the wrapper.  This should be equivalent for the rest of
+     compiler, so the code does not diverge, and the wrapper may run the
+     code neccesary for keeping the profiling sane.  */
+
+  switch (DECL_FUNCTION_CODE (fn))
+    {
+    case BUILT_IN_FORK:
+      id = get_identifier ("__gcov_fork");
+      break;
+
+    case BUILT_IN_EXECL:
+      id = get_identifier ("__gcov_execl");
+      break;
+
+    case BUILT_IN_EXECV:
+      id = get_identifier ("__gcov_execv");
+      break;
+
+    case BUILT_IN_EXECLP:
+      id = get_identifier ("__gcov_execlp");
+      break;
+
+    case BUILT_IN_EXECLE:
+      id = get_identifier ("__gcov_execle");
+      break;
+
+    case BUILT_IN_EXECVP:
+      id = get_identifier ("__gcov_execvp");
+      break;
+
+    case BUILT_IN_EXECVE:
+      id = get_identifier ("__gcov_execve");
+      break;
+
+    default:
+      abort ();
+    }
+
+  decl = build_decl (FUNCTION_DECL, id, TREE_TYPE (fn));
+  DECL_EXTERNAL (decl) = 1;
+  TREE_PUBLIC (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  TREE_NOTHROW (decl) = 1;
+  call = build_function_call_expr (decl, arglist);
+
+  return expand_call (call, target, ignore);
+}
 \f
 /* Expand an expression EXP that calls a built-in function,
    with result going to TARGET if that's convenient
@@ -5653,6 +5716,17 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
       expand_builtin_prefetch (arglist);
       return const0_rtx;
 
+    case BUILT_IN_FORK:
+    case BUILT_IN_EXECL:
+    case BUILT_IN_EXECV:
+    case BUILT_IN_EXECLP:
+    case BUILT_IN_EXECLE:
+    case BUILT_IN_EXECVP:
+    case BUILT_IN_EXECVE:
+      target = expand_builtin_fork_or_exec (fndecl, arglist, target, ignore);
+      if (target)
+       return target;
+      break;
 
     default:   /* just do library call, if unknown builtin */
       if (!DECL_ASSEMBLER_NAME_SET_P (fndecl))
index 72f5f25..7220625 100644 (file)
@@ -555,10 +555,17 @@ DEF_GCC_BUILTIN        (BUILT_IN_DWARF_CFA, "dwarf_cfa", BT_FN_PTR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_DWARF_SP_COLUMN, "dwarf_sp_column", BT_FN_UNSIGNED, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_EH_RETURN, "eh_return", BT_FN_VOID_PTRMODE_PTR, ATTR_NORETURN_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_EH_RETURN_DATA_REGNO, "eh_return_data_regno", BT_FN_INT_INT, ATTR_NULL)
+DEF_LIB_BUILTIN        (BUILT_IN_EXECL, "execl", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_NOTHROW_LIST)
+DEF_LIB_BUILTIN        (BUILT_IN_EXECLP, "execlp", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_NOTHROW_LIST)
+DEF_LIB_BUILTIN        (BUILT_IN_EXECLE, "execle", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_NOTHROW_LIST)
+DEF_LIB_BUILTIN        (BUILT_IN_EXECV, "execv", BT_FN_INT_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
+DEF_LIB_BUILTIN        (BUILT_IN_EXECVP, "execvp", BT_FN_INT_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
+DEF_LIB_BUILTIN        (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
 DEF_LIB_BUILTIN        (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_WORD_PTR, ATTR_CONST_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_EXTRACT_RETURN_ADDR, "extract_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
+DEF_LIB_BUILTIN        (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UNSIGNED, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
index 9c86829..c4f0129 100644 (file)
@@ -55,6 +55,10 @@ cpp_reader *parse_in;                /* Declared in c-pragma.h.  */
 #define SIZE_TYPE "long unsigned int"
 #endif
 
+#ifndef PID_TYPE
+#define PID_TYPE "int"
+#endif
+
 #ifndef WCHAR_TYPE
 #define WCHAR_TYPE "int"
 #endif
@@ -3113,6 +3117,9 @@ c_common_nodes_and_builtins (void)
   signed_size_type_node = c_common_signed_type (size_type_node);
   set_sizetype (size_type_node);
 
+  pid_type_node =
+    TREE_TYPE (identifier_global_value (get_identifier (PID_TYPE)));
+
   build_common_tree_nodes_2 (flag_short_double);
 
   record_builtin_type (RID_FLOAT, NULL, float_type_node);
index 44d6360..091ea4e 100644 (file)
@@ -653,21 +653,8 @@ special_function_p (tree fndecl, int flags)
       else if (tname[0] == 'l' && tname[1] == 'o'
               && ! strcmp (tname, "longjmp"))
        flags |= ECF_LONGJMP;
-
-      else if ((tname[0] == 'f' && tname[1] == 'o'
-               && ! strcmp (tname, "fork"))
-              /* Linux specific: __clone.  check NAME to insist on the
-                 leading underscores, to avoid polluting the ISO / POSIX
-                 namespace.  */
-              || (name[0] == '_' && name[1] == '_'
-                  && ! strcmp (tname, "clone"))
-              || (tname[0] == 'e' && tname[1] == 'x' && tname[2] == 'e'
-                  && tname[3] == 'c' && (tname[4] == 'l' || tname[4] == 'v')
-                  && (tname[5] == '\0'
-                      || ((tname[5] == 'p' || tname[5] == 'e')
-                          && tname[6] == '\0'))))
-       flags |= ECF_FORK_OR_EXEC;
     }
+
   return flags;
 }
 
@@ -2626,18 +2613,6 @@ expand_call (tree exp, rtx target, int ignore)
       stack_pointer_delta = save_stack_pointer_delta;
     }
 
-  if (profile_arc_flag && (flags & ECF_FORK_OR_EXEC))
-    {
-      /* A fork duplicates the profile information, and an exec discards
-        it.  We can't rely on fork/exec to be paired.  So write out the
-        profile information we have gathered so far, and clear it.  */
-      /* ??? When Linux's __clone is called with CLONE_VM set, profiling
-        is subject to race conditions, just as with multithreaded
-        programs.  */
-
-      emit_library_call (gcov_flush_libfunc, LCT_ALWAYS_RETURN, VOIDmode, 0);
-    }
-
   /* Ensure current function's preferred stack boundary is at least
      what we need.  We don't have to increase alignment for recursive
      functions.  */
index e83c516..8e0da0e 100644 (file)
@@ -447,6 +447,16 @@ extern void __gcov_merge_single (gcov_type *, unsigned);
 /* The merge function to choose the most common difference between
    consecutive values.  */
 extern void __gcov_merge_delta (gcov_type *, unsigned);
+
+/* The wrappers around some library functions..  */
+extern pid_t __gcov_fork (void);
+extern int __gcov_execl (const char *, const char *, ...);
+extern int __gcov_execlp (const char *, const char *, ...);
+extern int __gcov_execle (const char *,  const char *, ...);
+extern int __gcov_execv (const char *, char *const []);
+extern int __gcov_execvp (const char *, char *const []);
+extern int __gcov_execve (const char *, char  *const [], char *const []);
+
 #endif /* IN_LIBGCOV */
 
 #if IN_LIBGCOV >= 0
index d334502..0731ed0 100644 (file)
@@ -580,4 +580,146 @@ __gcov_merge_delta (gcov_type *counters, unsigned n_counters)
 }
 #endif /* L_gcov_merge_delta */
 
+#ifdef L_gcov_fork
+/* A wrapper for the fork function.  Flushes the accumulated profiling data, so
+   that they are not counted twice.  */
+
+pid_t
+__gcov_fork (void)
+{
+  __gcov_flush ();
+  return fork ();
+}
+#endif
+
+#ifdef L_gcov_execl
+/* A wrapper for the execl function.  Flushes the accumulated profiling data, so
+   that they are not lost.  */
+
+int
+__gcov_execl (const char *path, const char *arg, ...)
+{
+  va_list ap, aq;
+  unsigned i, length;
+  char **args;
+
+  __gcov_flush ();
+
+  va_start (ap, arg);
+  va_copy (aq, ap);
+
+  length = 2;
+  while (va_arg (ap, char *))
+    length++;
+  va_end (ap);
+
+  args = alloca (length * sizeof (void *));
+  args[0] = (char *) arg;
+  for (i = 1; i < length; i++)
+    args[i] = va_arg (aq, char *);
+  va_end (aq);
+
+  return execv (path, args);
+}
+#endif
+
+#ifdef L_gcov_execlp
+/* A wrapper for the execlp function.  Flushes the accumulated profiling data, so
+   that they are not lost.  */
+
+int
+__gcov_execlp (const char *path, const char *arg, ...)
+{
+  va_list ap, aq;
+  unsigned i, length;
+  char **args;
+
+  __gcov_flush ();
+
+  va_start (ap, arg);
+  va_copy (aq, ap);
+
+  length = 2;
+  while (va_arg (ap, char *))
+    length++;
+  va_end (ap);
+
+  args = alloca (length * sizeof (void *));
+  args[0] = (char *) arg;
+  for (i = 1; i < length; i++)
+    args[i] = va_arg (aq, char *);
+  va_end (aq);
+
+  return execvp (path, args);
+}
+#endif
+
+#ifdef L_gcov_execle
+/* A wrapper for the execle function.  Flushes the accumulated profiling data, so
+   that they are not lost.  */
+
+int
+__gcov_execle (const char *path, const char *arg, ...)
+{
+  va_list ap, aq;
+  unsigned i, length;
+  char **args;
+  char **envp;
+
+  __gcov_flush ();
+
+  va_start (ap, arg);
+  va_copy (aq, ap);
+
+  length = 2;
+  while (va_arg (ap, char *))
+    length++;
+  va_end (ap);
+
+  args = alloca (length * sizeof (void *));
+  args[0] = (char *) arg;
+  for (i = 1; i < length; i++)
+    args[i] = va_arg (aq, char *);
+  envp = va_arg (aq, char **);
+  va_end (aq);
+
+  return execve (path, args, envp);
+}
+#endif
+
+#ifdef L_gcov_execv
+/* A wrapper for the execv function.  Flushes the accumulated profiling data, so
+   that they are not lost.  */
+
+int
+__gcov_execv (const char *path, char *const argv[])
+{
+  __gcov_flush ();
+  return execv (path, argv);
+}
+#endif
+
+#ifdef L_gcov_execvp
+/* A wrapper for the execvp function.  Flushes the accumulated profiling data, so
+   that they are not lost.  */
+
+int
+__gcov_execvp (const char *path, char *const argv[])
+{
+  __gcov_flush ();
+  return execvp (path, argv);
+}
+#endif
+
+#ifdef L_gcov_execve
+/* A wrapper for the execve function.  Flushes the accumulated profiling data, so
+   that they are not lost.  */
+
+int
+__gcov_execve (const char *path, char *const argv[], char *const envp[])
+{
+  __gcov_flush ();
+  return execve (path, argv, envp);
+}
+#endif
 #endif /* inhibit_libc */
index 52a17f0..085d5fe 100644 (file)
@@ -1992,6 +1992,7 @@ enum tree_index
   TI_PTR_TYPE,
   TI_CONST_PTR_TYPE,
   TI_SIZE_TYPE,
+  TI_PID_TYPE,
   TI_PTRDIFF_TYPE,
   TI_VA_LIST_TYPE,
   TI_BOOLEAN_TYPE,
@@ -2056,6 +2057,7 @@ extern GTY(()) tree global_trees[TI_MAX];
 #define const_ptr_type_node            global_trees[TI_CONST_PTR_TYPE]
 /* The C type `size_t'.  */
 #define size_type_node                  global_trees[TI_SIZE_TYPE]
+#define pid_type_node                   global_trees[TI_PID_TYPE]
 #define ptrdiff_type_node              global_trees[TI_PTRDIFF_TYPE]
 #define va_list_type_node              global_trees[TI_VA_LIST_TYPE]
 
@@ -3090,18 +3092,17 @@ extern rtx emit_line_note (location_t);
 #define ECF_LONGJMP            64
 /* Nonzero if this is a syscall that makes a new process in the image of
    the current one.  */
-#define ECF_FORK_OR_EXEC       128
-#define ECF_SIBCALL            256
+#define ECF_SIBCALL            128
 /* Nonzero if this is a call to "pure" function (like const function,
    but may read memory.  */
-#define ECF_PURE               512
+#define ECF_PURE               256
 /* Nonzero if this is a call to a function that returns with the stack
    pointer depressed.  */
-#define ECF_SP_DEPRESSED       1024
+#define ECF_SP_DEPRESSED       512
 /* Nonzero if this call is known to always return.  */
-#define ECF_ALWAYS_RETURN      2048
+#define ECF_ALWAYS_RETURN      1024
 /* Create libcall block around the call.  */
-#define ECF_LIBCALL_BLOCK      4096
+#define ECF_LIBCALL_BLOCK      2048
 
 extern int flags_from_decl_or_type (tree);
 extern int call_expr_flags (tree);