]> gcc.gnu.org Git - gcc.git/commitdiff
Lazy __FUNCTION__ generation.
authorNathan Sidwell <nathan@gcc.gnu.org>
Tue, 24 Apr 2001 08:22:06 +0000 (08:22 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 24 Apr 2001 08:22:06 +0000 (08:22 +0000)
gcc:
Lazy __FUNCTION__ generation.
* c-common.h (RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME,
RID_C99_FUNCTION_NAME): New _RIDs.
(CTI_FUNCTION_ID, CTI_PRETTY_FUNCTION_ID, CTI_FUNC_ID): Remove.
(CTI_FUNCTION_NAME_DECL, CTI_PRETTY_FUNCTION_NAME_DECL,
CTI_C99_FUNCTION_NAME_DECL, CTI_SAVED_FUNCTION_NAME_DECLS): New
global tree slots.
(function_id_node, pretty_function_id_node, func_id_node): Remove.
(c99_function_name_decl_node, function_name_decl_node,
pretty_function_name_decl_node, saved_function_name_decls):
Declare.
(struct language_function): Remove x_function_name_declared_p.
(make_fname_decl): Remove a parameter.
(declare_function_names): Remove prototype.
(start_fname_decls, finish_fname_decls): Prototype.
(fname_as_string): Likewise.
(fname_string, fname_decl): Likewise.
* c-common.c (make_fname_decl): Adjust.
(struct fname_var_t): New struct.
(fname_vars): New static array.
(declare_function_name): Remove.
(start_fname_decls, finish_fname_decls): New functions.
(fname_as_string): New function from remnants of
declare_function_name.
(fname_string, fname_decl): New functions.

* c-decl.c (c_function_name_declared_p): Remove.
(init_decl_processing): Don't generate __FUNCTION__ et al ids,
don't call declare_function_name. Call start_fname_decls.
(c_make_fname_decl): Adjust parameters. Generate the name. Don't
clobber the line number. Call finish_decl.
(start_function): Call start_fname_decls.
(finish_function): Call finish_fname_decls.
Remove c_function_name_declared_p.
(push_c_function_context): Don't push c_function_name_declared_p.
(pop_c_function_context): Don't pop c_function_name_declared_p.
(c_begin_compound_stmt): Don't check c_function_name_declared_p.
* c-parse.in (STRING_FUNC_NAME, VAR_FUNC_NAME): New tokens.
(program): Call finish_fname_decls for C.
(primary): Add VAR_FUNC_NAME.
(reswords): Add slots for __FUNCTION__ et al.
(rid_to_yy): Add mappings for __FUNCTION__ et al.
(yylexname): If it's a STRING_FUNC_NAME generate the function name
now. Don't look for VAR_DECLs containing __FUNCTION__ et al.
* c-semantics.c (prune_unused_decls): Remove.
(finish_stmt_tree): Don't call prune_unused_decls.
(genrtl_decl_stmt): Don't prune unused decls here.
cp:
Lazy __FUNCTION__ generation.
* cp-tree.def (FUNCTION_NAME): Remove.
* cp-tree.h (function_name_declared_p): Remove.
(cp_fname_init): Prototype.
* decl.c (init_decl_processing): Don't generate __FUNCTION__ et al ids,
don't call declare_function_name. Call start_fname_decls.
(cp_make_fname_decl): Adjust parameters. Generate the name. Don't
clobber the line number.
(cp_fname_init): New function.
(start_function): Call start_fname_decls.
(finish_function): Call finish_fname_decls.
* lex.c (reswords): Add slots for __FUNCTION__ et al.
(rid_to_yy): Add mappings for __FUNCTION__ et al.
* optimize.c (maybe_clone_body): Remove function_name_declared_p.
* parse.y (VAR_FUNC_NAME): New token.
(primary): Add VAR_FUNC_NAME.
* pt.c (tsubst_decl): Adjust a DECL_PRETTY_FUNCTION_P's
generation.
(tsubst, FUNCTION_NAME case): Remove.
(tsubst_copy, FUNCTION_NAME case): Remove.
(tsubst_expr, DECL_STMT case): Be careful with a
DECL_PRETTY_FUNCTION_P.
(instantiate_decl): Remove function_name_declared_p.
* semantics.c (begin_compound_statement): Don't call
declare_function_name here.
(setup_vtbl_ptr). Don't save & restore function_name_declared_p.
(finish_translation_unit): Call finish_fname_decls.
(expand_body): Remove function_name_declared_p.
* typeck2.c (digest_init): Allow any ERROR_MARK.
testsuite:
* gcc.dg/c99-func-2.c: Remove xfail.
* gcc.dg/c99-func-3.c: Remove xfail.
* gcc.dg/c99-func-4.c: Remove xfail.

From-SVN: r41520

20 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-decl.c
gcc/c-parse.in
gcc/c-semantics.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/lex.c
gcc/cp/optimize.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c99-func-2.c
gcc/testsuite/gcc.dg/c99-func-3.c
gcc/testsuite/gcc.dg/c99-func-4.c

index 7569d1225ba3202f5a0916ddc67772eac4a0e4d1..cd986491a4ed0161ea45eaafedd42b4c0c511d1c 100644 (file)
@@ -1,3 +1,54 @@
+2001-04-24  Zack Weinberg  <zackw@stanford.edu>
+           Nathan Sidwell <nathan@codesourcery.com>
+
+       Lazy __FUNCTION__ generation.
+       * c-common.h (RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME,
+       RID_C99_FUNCTION_NAME): New _RIDs.
+       (CTI_FUNCTION_ID, CTI_PRETTY_FUNCTION_ID, CTI_FUNC_ID): Remove.
+       (CTI_FUNCTION_NAME_DECL, CTI_PRETTY_FUNCTION_NAME_DECL,
+       CTI_C99_FUNCTION_NAME_DECL, CTI_SAVED_FUNCTION_NAME_DECLS): New
+       global tree slots.
+       (function_id_node, pretty_function_id_node, func_id_node): Remove.
+       (c99_function_name_decl_node, function_name_decl_node,
+       pretty_function_name_decl_node, saved_function_name_decls):
+       Declare.
+       (struct language_function): Remove x_function_name_declared_p.
+       (make_fname_decl): Remove a parameter.
+       (declare_function_names): Remove prototype.
+       (start_fname_decls, finish_fname_decls): Prototype.
+       (fname_as_string): Likewise.
+       (fname_string, fname_decl): Likewise.
+       * c-common.c (make_fname_decl): Adjust.
+       (struct fname_var_t): New struct.
+       (fname_vars): New static array.
+       (declare_function_name): Remove.
+       (start_fname_decls, finish_fname_decls): New functions.
+       (fname_as_string): New function from remnants of
+       declare_function_name.
+       (fname_string, fname_decl): New functions.
+
+       * c-decl.c (c_function_name_declared_p): Remove.
+       (init_decl_processing): Don't generate __FUNCTION__ et al ids,
+       don't call declare_function_name. Call start_fname_decls.
+       (c_make_fname_decl): Adjust parameters. Generate the name. Don't
+       clobber the line number. Call finish_decl.
+       (start_function): Call start_fname_decls.
+       (finish_function): Call finish_fname_decls.
+       Remove c_function_name_declared_p.
+       (push_c_function_context): Don't push c_function_name_declared_p.
+       (pop_c_function_context): Don't pop c_function_name_declared_p.
+       (c_begin_compound_stmt): Don't check c_function_name_declared_p.
+       * c-parse.in (STRING_FUNC_NAME, VAR_FUNC_NAME): New tokens.
+       (program): Call finish_fname_decls for C.
+       (primary): Add VAR_FUNC_NAME.
+       (reswords): Add slots for __FUNCTION__ et al.
+       (rid_to_yy): Add mappings for __FUNCTION__ et al.
+       (yylexname): If it's a STRING_FUNC_NAME generate the function name
+       now. Don't look for VAR_DECLs containing __FUNCTION__ et al.
+       * c-semantics.c (prune_unused_decls): Remove.
+       (finish_stmt_tree): Don't call prune_unused_decls.
+       (genrtl_decl_stmt): Don't prune unused decls here.
+
 2001-04-24  Nick Clifton  <nickc@cambridge.redhat.com>
 
        * dwarf2out.c (mem_loc_descriptor): If a SYMBOL_REF is in the
index 1b00362ba0ddd7a7ab3c9760b405522907229b72..872750320ed4df0715a7f25c0a6cc4cd218a1212 100644 (file)
@@ -164,11 +164,17 @@ cpp_reader *parse_in;             /* Declared in c-lex.h.  */
 
        tree void_list_node;
 
-  The identifiers __FUNCTION__, __PRETTY_FUNCTION__, and __func__.
+  The lazily created VAR_DECLS for __FUNCTION__, __PRETTY_FUNCTION__,
+  and __func__. (C doesn't generate __FUNCTION__ and__PRETTY_FUNCTION__
+  VAR_DECLS, but C++ does.)
 
-       tree function_id_node;
-       tree pretty_function_id_node;
-       tree func_id_node;
+       tree function_name_decl_node;
+       tree pretty_function_name_declnode;
+       tree c99_function_name_decl_node;
+
+  Stack of nested function name VAR_DECLs.
+  
+       tree saved_function_name_decls;
 
 */
 
@@ -204,7 +210,7 @@ int warn_sequence_point;
    type names and storage classes.  It is indexed by a RID_... value.  */
 tree *ridpointers;
 
-tree (*make_fname_decl)                PARAMS ((tree, const char *, int));
+tree (*make_fname_decl)                PARAMS ((tree, int));
 
 /* If non-NULL, the address of a language-specific function that
    returns 1 for language-specific statement codes.  */
@@ -228,6 +234,27 @@ enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
            A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, A_MALLOC,
            A_NO_LIMIT_STACK, A_PURE};
 
+/* Information about how a function name is generated. */
+struct fname_var_t
+{
+  tree *decl;  /* pointer to the VAR_DECL. */
+  unsigned rid;        /* RID number for the identifier. */
+  int pretty;  /* How pretty is it? */
+};
+
+/* The three ways of getting then name of the current function. */
+
+const struct fname_var_t fname_vars[] =
+{
+  /* C99 compliant __func__, must be first. */
+  {&c99_function_name_decl_node, RID_C99_FUNCTION_NAME, 0},
+  /* GCC __FUNCTION__ compliant. */
+  {&function_name_decl_node, RID_FUNCTION_NAME, 0},
+  /* GCC __PRETTY_FUNCTION__ compliant. */
+  {&pretty_function_name_decl_node, RID_PRETTY_FUNCTION_NAME, 1},
+  {NULL, 0, 0},
+};
+
 static void add_attribute              PARAMS ((enum attrs, const char *,
                                                 int, int, int));
 static void init_attributes            PARAMS ((void));
@@ -344,34 +371,157 @@ c_finish_else ()
   RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
 }
 
-/* Make bindings for __FUNCTION__, __PRETTY_FUNCTION__, and __func__.  */
+/* Push current bindings for the function name VAR_DECLS. */
+
+void
+start_fname_decls ()
+{
+  unsigned ix;
+  tree saved = NULL_TREE;
+  
+  for (ix = 0; fname_vars[ix].decl; ix++)
+    {
+      tree decl = *fname_vars[ix].decl;
+
+      if (decl)
+       {
+         saved = tree_cons (decl, build_int_2 (ix, 0), saved);
+         *fname_vars[ix].decl = NULL_TREE;
+       }
+    }
+  if (saved || saved_function_name_decls)
+    /* Normally they'll have been NULL, so only push if we've got a
+       stack, or they are non-NULL.  */
+    saved_function_name_decls = tree_cons (saved, NULL_TREE,
+                                          saved_function_name_decls);
+}
+
+/* Finish up the current bindings, adding them into the
+   current function's statement tree. This is done by wrapping the
+   function's body in a COMPOUND_STMT containing these decls too. This
+   must be done _before_ finish_stmt_tree is called. If there is no
+   current function, we must be at file scope and no statements are
+   involved. Pop the previous bindings. */
 
 void
-declare_function_name ()
+finish_fname_decls ()
 {
-  const char *name, *printable_name;
+  unsigned ix;
+  tree body = NULL_TREE;
+  tree stack = saved_function_name_decls;
 
-  if (current_function_decl == NULL)
+  for (; stack && TREE_VALUE (stack); stack = TREE_CHAIN (stack))
+    body = chainon (TREE_VALUE (stack), body);
+  
+  if (body)
     {
-      name = "";
-      printable_name = "top level";
+      /* They were called into existance, so add to statement tree. */
+      body = chainon (body,
+                     TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)));
+      body = build_stmt (COMPOUND_STMT, body);
+      
+      COMPOUND_STMT_NO_SCOPE (body) = 1;
+      TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)) = body;
     }
-  else
+  
+  for (ix = 0; fname_vars[ix].decl; ix++)
+    *fname_vars[ix].decl = NULL_TREE;
+  
+  if (stack)
     {
-      /* Allow functions to be nameless (such as artificial ones).  */
-      if (DECL_NAME (current_function_decl))
-        name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
-      else
-       name = "";
-      printable_name = (*decl_printable_name) (current_function_decl, 2);
+      /* We had saved values, restore them. */
+      tree saved;
 
-      /* ISO C99 defines __func__, which is a variable, not a string
-        constant, and which is not a defined symbol at file scope.  */
-      (*make_fname_decl) (func_id_node, name, 0);
+      for (saved = TREE_PURPOSE (stack); saved; saved = TREE_CHAIN (saved))
+       {
+         tree decl = TREE_PURPOSE (saved);
+         unsigned ix = TREE_INT_CST_LOW (TREE_VALUE (saved));
+         
+         *fname_vars[ix].decl = decl;
+       }
+      stack = TREE_CHAIN (stack);
+    }
+  saved_function_name_decls = stack;
+}
+
+/* Return the text name of the current function, suitable prettified
+   by PRETTY_P. */
+
+const char *
+fname_as_string (pretty_p)
+     int pretty_p;
+{
+  const char *name = NULL;
+  
+  if (pretty_p)
+    name = (current_function_decl
+           ? (*decl_printable_name) (current_function_decl, 2)
+           : "top level");
+  else if (current_function_decl && DECL_NAME (current_function_decl))
+    name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
+  else
+    name = "";
+  return name;
+}
+
+/* Return the text name of the current function, formatted as
+   required by the supplied RID value.  */
+
+const char *
+fname_string (rid)
+     unsigned rid;
+{
+  unsigned ix;
+  
+  for (ix = 0; fname_vars[ix].decl; ix++)
+    if (fname_vars[ix].rid == rid)
+      break;
+  return fname_as_string (fname_vars[ix].pretty);
+}
+
+/* Return the VAR_DECL for a const char array naming the current
+   function. If the VAR_DECL has not yet been created, create it
+   now. RID indicates how it should be formatted and IDENTIFIER_NODE
+   ID is its name (unfortunately C and C++ hold the RID values of
+   keywords in different places, so we can't derive RID from ID in
+   this language independant code.  */
+
+tree
+fname_decl (rid, id)
+     unsigned rid;
+     tree id;
+{
+  unsigned ix;
+  tree decl = NULL_TREE;
+
+  for (ix = 0; fname_vars[ix].decl; ix++)
+    if (fname_vars[ix].rid == rid)
+      break;
+
+  decl = *fname_vars[ix].decl;
+  if (!decl)
+    {
+      tree saved_last_tree = last_tree;
+      
+      decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
+      if (last_tree != saved_last_tree)
+       {
+         /* We created some statement tree for the decl. This belongs
+            at the start of the function, so remove it now and reinsert
+            it after the function is complete. */
+         tree stmts = TREE_CHAIN (saved_last_tree);
+
+         TREE_CHAIN (saved_last_tree) = NULL_TREE;
+         last_tree = saved_last_tree;
+         saved_function_name_decls = tree_cons (decl, stmts,
+                                                saved_function_name_decls);
+       }
+      *fname_vars[ix].decl = decl;
     }
+  if (!ix && !current_function_decl)
+    pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
   
-  (*make_fname_decl) (function_id_node, name, 0);
-  (*make_fname_decl) (pretty_function_id_node, printable_name, 1);
+  return decl;
 }
 
 /* Given a chain of STRING_CST nodes,
index fbdf1570d7185e5819f75376ffa797dfbc71311e..b9a7a9dd97f295ed200f112af1e30fc89234ff71 100644 (file)
@@ -75,6 +75,9 @@ enum rid
   RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL,      RID_PTRBASE,
   RID_PTREXTENT, RID_PTRVALUE,
 
+  /* Too many ways of getting the name of a function as a string */
+  RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME,
+
   /* C++ */
   RID_BOOL,     RID_WCHAR,    RID_CLASS,
   RID_PUBLIC,   RID_PRIVATE,  RID_PROTECTED,
@@ -154,11 +157,12 @@ enum c_tree_index
     CTI_G77_LONGINT_TYPE,
     CTI_G77_ULONGINT_TYPE,
 
-    /* These are not types, but we have to look them up all the time.  */
-    CTI_FUNCTION_ID,
-    CTI_PRETTY_FUNCTION_ID,
-    CTI_FUNC_ID,
-
+    /* These are not types, but we have to look them up all the time. */
+    CTI_FUNCTION_NAME_DECL,
+    CTI_PRETTY_FUNCTION_NAME_DECL,
+    CTI_C99_FUNCTION_NAME_DECL,
+    CTI_SAVED_FUNCTION_NAME_DECLS,
+    
     CTI_VOID_ZERO,
 
     CTI_MAX
@@ -202,9 +206,10 @@ enum c_tree_index
 #define g77_longint_type_node          c_global_trees[CTI_G77_LONGINT_TYPE]
 #define g77_ulongint_type_node         c_global_trees[CTI_G77_ULONGINT_TYPE]
 
-#define function_id_node               c_global_trees[CTI_FUNCTION_ID]
-#define pretty_function_id_node                c_global_trees[CTI_PRETTY_FUNCTION_ID]
-#define func_id_node                   c_global_trees[CTI_FUNC_ID]
+#define function_name_decl_node                c_global_trees[CTI_FUNCTION_NAME_DECL]
+#define pretty_function_name_decl_node c_global_trees[CTI_PRETTY_FUNCTION_NAME_DECL]
+#define c99_function_name_decl_node            c_global_trees[CTI_C99_FUNCTION_NAME_DECL]
+#define saved_function_name_decls      c_global_trees[CTI_SAVED_FUNCTION_NAME_DECLS]
 
 /* A node for `((void) 0)'.  */
 #define void_zero_node                  c_global_trees[CTI_VOID_ZERO]
@@ -260,9 +265,6 @@ struct language_function {
   struct stmt_tree_s x_stmt_tree;
   /* The stack of SCOPE_STMTs for the current function.  */
   tree x_scope_stmt_stack;
-  /* Nonzero if __FUNCTION__ and its ilk have been declared in this
-     function.  */
-  int x_function_name_declared_p;
 };
 
 /* When building a statement-tree, this is the last statement added to
@@ -468,19 +470,22 @@ extern int warn_long_long;
    what operator was specified for it.  */
 #define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
 
-/* Pointer to function to generate the VAR_DECL for __FUNCTION__ etc.
+/* Pointer to function to lazily generate the VAR_DECL for __FUNCTION__ etc.
    ID is the identifier to use, NAME is the string.
    TYPE_DEP indicates whether it depends on type of the function or not
    (i.e. __PRETTY_FUNCTION__).  */
 
-extern tree (*make_fname_decl)                  PARAMS ((tree, const char *, int));
+extern tree (*make_fname_decl)                  PARAMS ((tree, int));
 
 extern tree identifier_global_value            PARAMS ((tree));
 extern void record_builtin_type                        PARAMS ((enum rid,
                                                         const char *, tree));
 extern tree build_void_list_node               PARAMS ((void));
-
-extern void declare_function_name              PARAMS ((void));
+extern void start_fname_decls                  PARAMS ((void));
+extern void finish_fname_decls                 PARAMS ((void));
+extern const char *fname_as_string             PARAMS ((int));
+extern tree fname_decl                         PARAMS ((unsigned, tree));
+extern const char *fname_string                        PARAMS ((unsigned));
 extern void decl_attributes                    PARAMS ((tree, tree, tree));
 extern void init_function_format_info          PARAMS ((void));
 extern void check_function_format              PARAMS ((int *, tree, tree, tree));
index a8c1d300b2bd4674fde8995f2079cc4222a8b475..a386ecdad15afe6accdd3cd70e76398fdc71c746 100644 (file)
@@ -104,11 +104,6 @@ static struct stmt_tree_s c_stmt_tree;
 
 static tree c_scope_stmt_stack;
 
-/* Nonzero if __FUNCTION__ and its ilk have been declared in this
-   function.  */
-
-static int c_function_name_declared_p;
-
 /* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
    that have names.  Here so we can clear out their names' definitions
    at the end of the function.  */
@@ -279,7 +274,7 @@ static tree grokdeclarator          PARAMS ((tree, tree, enum decl_context,
                                                 int));
 static tree grokparms                  PARAMS ((tree, int));
 static void layout_array_type          PARAMS ((tree));
-static tree c_make_fname_decl           PARAMS ((tree, const char *, int));
+static tree c_make_fname_decl           PARAMS ((tree, int));
 static void c_expand_body               PARAMS ((tree, int));
 \f
 /* C-specific option variables.  */
@@ -3093,13 +3088,8 @@ init_decl_processing ()
 
   pedantic_lvalues = pedantic;
 
-  /* Create the global bindings for __FUNCTION__, __PRETTY_FUNCTION__,
-     and __func__.  */
-  function_id_node = get_identifier ("__FUNCTION__");
-  pretty_function_id_node = get_identifier ("__PRETTY_FUNCTION__");
-  func_id_node = get_identifier ("__func__");
   make_fname_decl = c_make_fname_decl;
-  declare_function_name ();
+  start_fname_decls ();
 
   start_identifier_warnings ();
 
@@ -3132,30 +3122,33 @@ init_decl_processing ()
    are string merging candidates, which is wrong for C99's __func__.  FIXME.  */
 
 static tree
-c_make_fname_decl (id, name, type_dep)
+c_make_fname_decl (id, type_dep)
      tree id;
-     const char *name;
-     int type_dep ATTRIBUTE_UNUSED;
+     int type_dep;
 {
+  const char *name = fname_as_string (type_dep);
   tree decl, type, init;
   size_t length = strlen (name);
 
   type =  build_array_type
           (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
-          build_index_type (build_int_2 (length, 0)));
+          build_index_type (size_int (length)));
 
   decl = build_decl (VAR_DECL, id, type);
+  /* We don't push the decl, so have to set its context here. */
+  DECL_CONTEXT (decl) = current_function_decl;
+  
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
-  TREE_ASM_WRITTEN (decl) = 1;
-  DECL_SOURCE_LINE (decl) = 0;
   DECL_ARTIFICIAL (decl) = 1;
-  DECL_IN_SYSTEM_HEADER (decl) = 1;
-  DECL_IGNORED_P (decl) = 1;
+  
   init = build_string (length + 1, name);
   TREE_TYPE (init) = type;
   DECL_INITIAL (decl) = init;
-  finish_decl (pushdecl (decl), init, NULL_TREE);
+
+  TREE_USED (decl) = 1;
+  
+  finish_decl (decl, init, NULL_TREE);
 
   return decl;
 }
@@ -3487,9 +3480,9 @@ finish_decl (decl, init, asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
-
   if (init != 0 && DECL_INITIAL (decl) == 0)
     init = 0;
+  
   /* Don't crash if parm is initialized.  */
   if (TREE_CODE (decl) == PARM_DECL)
     init = 0;
@@ -3507,7 +3500,6 @@ finish_decl (decl, init, asmspec_tree)
     }
 
   /* Deduce size of array from initialization, if not already known */
-
   if (TREE_CODE (type) == ARRAY_TYPE
       && TYPE_DOMAIN (type) == 0
       && TREE_CODE (decl) != TYPE_DECL)
@@ -6029,6 +6021,8 @@ start_function (declspecs, declarator, prefix_attributes, attributes)
 
   immediate_size_expand = old_immediate_size_expand;
 
+  start_fname_decls ();
+  
   return 1;
 }
 
@@ -6656,6 +6650,8 @@ finish_function (nested)
 #endif
        }
     }
+  
+  finish_fname_decls ();
 
   /* Tie off the statement tree for this function.  */
   finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
@@ -6674,7 +6670,6 @@ finish_function (nested)
         function.  For a nested function, this value is used in
         pop_c_function_context and then reset via pop_function_context.  */
       current_function_decl = NULL;
-      c_function_name_declared_p = 0;
     }
 }
 
@@ -6916,7 +6911,6 @@ push_c_function_context (f)
 
   p->base.x_stmt_tree = c_stmt_tree;
   p->base.x_scope_stmt_stack = c_scope_stmt_stack;
-  p->base.x_function_name_declared_p = c_function_name_declared_p;
   p->named_labels = named_labels;
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
@@ -6954,7 +6948,6 @@ pop_c_function_context (f)
 
   c_stmt_tree = p->base.x_stmt_tree;
   c_scope_stmt_stack = p->base.x_scope_stmt_stack;
-  c_function_name_declared_p = p->base.x_function_name_declared_p;
   named_labels = p->named_labels;
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;
@@ -7087,13 +7080,6 @@ c_begin_compound_stmt ()
 
   /* Create the COMPOUND_STMT.  */
   stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
-  /* If we haven't already declared __FUNCTION__ and its ilk then this
-     is the opening curly brace of the function.  Declare them now.  */
-  if (!c_function_name_declared_p)
-    {
-      c_function_name_declared_p = 1;
-      declare_function_name ();
-    }
 
   return stmt;
 }
index d187ab4e16a61f8ed14ddbd3df07eed0db5ee9c5..657c3fb700b9e5e903d369d50f457def0d10ce00 100644 (file)
@@ -124,6 +124,9 @@ end ifc
 %token REALPART IMAGPART VA_ARG
 %token PTR_VALUE PTR_BASE PTR_EXTENT
 
+/* function name can be a string const or a var decl. */
+%token STRING_FUNC_NAME VAR_FUNC_NAME
+
 /* Add precedence rules to solve dangling else s/r conflict */
 %nonassoc IF
 %nonassoc ELSE
@@ -298,7 +301,10 @@ program: /* empty */
                     get us back to the global binding level.  */
                  while (! global_bindings_p ())
                    poplevel (0, 0, 0);
-                 finish_file ();
+ifc
+                 finish_fname_decls ();
+end ifc
+                  finish_file ();
                }
        ;
 
@@ -631,6 +637,8 @@ primary:
        | CONSTANT
        | string
                { $$ = combine_strings ($1); }
+       | VAR_FUNC_NAME
+               { $$ = fname_decl (C_RID_CODE ($$), $$); }
        | '(' typename ')' '{' 
                { start_init (NULL_TREE, NULL, 0);
                  $2 = groktypename ($2);
@@ -2884,6 +2892,8 @@ static const struct resword reswords[] =
 {
   { "_Bool",           RID_BOOL,       0 },
   { "_Complex",                RID_COMPLEX,    0 },
+  { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
+  { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
   { "__alignof",       RID_ALIGNOF,    0 },
   { "__alignof__",     RID_ALIGNOF,    0 },
   { "__asm",           RID_ASM,        0 },
@@ -2898,6 +2908,7 @@ static const struct resword reswords[] =
   { "__const",         RID_CONST,      0 },
   { "__const__",       RID_CONST,      0 },
   { "__extension__",   RID_EXTENSION,  0 },
+  { "__func__",                RID_C99_FUNCTION_NAME, 0 },
   { "__imag",          RID_IMAGPART,   0 },
   { "__imag__",                RID_IMAGPART,   0 },
   { "__inline",                RID_INLINE,     0 },
@@ -3057,6 +3068,10 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_PTREXTENT */  PTR_EXTENT,
   /* RID_PTRVALUE */   PTR_VALUE,
 
+  /* RID_FUNCTION_NAME */              STRING_FUNC_NAME,
+  /* RID_PRETTY_FUNCTION_NAME */       STRING_FUNC_NAME,
+  /* RID_C99_FUNCTION_NAME */          VAR_FUNC_NAME,
+
   /* C++ */
   /* RID_BOOL */       TYPESPEC,
   /* RID_WCHAR */      0,
@@ -3098,7 +3113,7 @@ static const short rid_to_yy[RID_MAX] =
   /* RID_BITAND */     0,
   /* RID_BITOR */      0,
   /* RID_COMPL */      0,
-
+  
   /* Objective C */
   /* RID_ID */                 OBJECTNAME,
   /* RID_AT_ENCODE */          ENCODE,
@@ -3226,9 +3241,22 @@ yylexname ()
   if (C_IS_RESERVED_WORD (yylval.ttype))
     {
       enum rid rid_code = C_RID_CODE (yylval.ttype);
+      int yycode = rid_to_yy[(int) rid_code];
+
+      if (yycode == STRING_FUNC_NAME)
+       {
+          /* __FUNCTION__ and __PRETTY_FUNCTION__ get converted
+             to string constants.  */
+         const char *name = fname_string (rid_code);
+         
+         yylval.ttype = build_string (strlen (name) + 1, name);
+         last_token = CPP_STRING;  /* so yyerror won't choke */
+         return STRING;
+       }
+      
       /* Return the canonical spelling for this keyword.  */
       yylval.ttype = ridpointers[(int) rid_code];
-      return rid_to_yy[(int) rid_code];
+      return yycode;
     }
 
   decl = lookup_name (yylval.ttype);
@@ -3236,23 +3264,6 @@ yylexname ()
     {
       if (TREE_CODE (decl) == TYPE_DECL)
        return TYPENAME;
-      /* A user-invisible read-only initialized variable
-        should be replaced by its value.
-        We handle only strings since that's the only case used in C.  */
-      else if (TREE_CODE (decl) == VAR_DECL
-              && DECL_IGNORED_P (decl)
-              && TREE_READONLY (decl)
-              && DECL_INITIAL (decl) != 0
-              && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
-       {
-         tree stringval = DECL_INITIAL (decl);
-
-         /* Copy the string value so that we won't clobber anything
-            if we put something in the TREE_CHAIN of this one.  */
-         yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
-                                      TREE_STRING_POINTER (stringval));
-         return STRING;
-       }
     }
   else if (doing_objc_thang)
     {
index c491335e1e86d961639795936588880f9f568fb1..13480480a4337e757f9d80a55d56da94eaad18c5 100644 (file)
@@ -48,8 +48,6 @@ void (*lang_expand_stmt) PARAMS ((tree));
    variables and labels do not require any RTL generation.  */
 void (*lang_expand_decl_stmt) PARAMS ((tree));
 
-static tree prune_unused_decls PARAMS ((tree *, int *, void *));
-
 /* Create an empty statement tree rooted at T.  */
 
 void
@@ -73,8 +71,9 @@ add_stmt (t)
   /* Add T to the statement-tree.  */
   TREE_CHAIN (last_tree) = t;
   last_tree = t;
+  
   /* When we expand a statement-tree, we must know whether or not the
-     statements are full-expresions.  We record that fact here.  */
+     statements are full-expressions.  We record that fact here.  */
   STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
 
   /* Keep track of the number of statements in this function.  */
@@ -105,7 +104,7 @@ add_decl_stmt (decl)
    returns a new TREE_LIST representing the top of the SCOPE_STMT
    stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
    zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
-   and whose TREE_PURPOSE is the matching SCOPE_STMT iwth
+   and whose TREE_PURPOSE is the matching SCOPE_STMT with
    SCOPE_BEGIN_P set.  */
 
 tree
@@ -141,61 +140,6 @@ add_scope_stmt (begin_p, partial_p)
   return top;
 }
 
-/* Remove declarations of internal variables that are not used from a
-   stmt tree.  To qualify, the variable must have a name and must have
-   a zero DECL_SOURCE_LINE.  We tried to remove all variables for
-   which TREE_USED was false, but it turns out that there's tons of
-   variables for which TREE_USED is false but that are still in fact
-   used.  */
-
-static tree
-prune_unused_decls (tp, walk_subtrees, data)
-     tree *tp;
-     int *walk_subtrees ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
-{
-  tree t = *tp;
-
-  if (t == NULL_TREE)
-    return error_mark_node;
-
-  if (TREE_CODE (t) == DECL_STMT)
-    {
-      tree d = DECL_STMT_DECL (t);
-      if (!TREE_USED (d) && DECL_NAME (d) && DECL_SOURCE_LINE (d) == 0)
-       {
-         *tp = TREE_CHAIN (t);
-         /* Recurse on the new value of tp, otherwise we will skip
-            the next statement.  */
-         return prune_unused_decls (tp, walk_subtrees, data);
-       }
-    }
-  else if (TREE_CODE (t) == SCOPE_STMT)
-    {
-      /* Remove all unused decls from the BLOCK of this SCOPE_STMT.  */
-      tree block = SCOPE_STMT_BLOCK (t);
-
-      if (block)
-       {
-         tree *vp;
-
-         for (vp = &BLOCK_VARS (block); *vp; )
-           {
-             tree v = *vp;
-             if (! TREE_USED (v) && DECL_NAME (v) && DECL_SOURCE_LINE (v) == 0)
-               *vp = TREE_CHAIN (v);  /* drop */
-             else
-               vp = &TREE_CHAIN (v);  /* advance */
-           }
-         /* If there are now no variables, the entire BLOCK can be dropped.
-            (This causes SCOPE_NULLIFIED_P (t) to be true.)  */
-         if (BLOCK_VARS (block) == NULL_TREE)
-           SCOPE_STMT_BLOCK (t) = NULL_TREE;
-       }
-    }
-  return NULL_TREE;
-}
-
 /* Finish the statement tree rooted at T.  */
 
 void
@@ -209,9 +153,6 @@ finish_stmt_tree (t)
   *t = stmt;
   last_tree = NULL_TREE;
 
-  /* Remove unused decls from the stmt tree.  */
-  walk_stmt_tree (t, prune_unused_decls, NULL);
-
   if (cfun && stmt)
     {
       /* The line-number recorded in the outermost statement in a function
@@ -420,15 +361,7 @@ genrtl_decl_stmt (t)
                                DECL_ANON_UNION_ELEMS (decl));
     }
   else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
-    {
-      if (DECL_ARTIFICIAL (decl) && ! TREE_USED (decl))
-       /* Do not emit unused decls. This is not just an
-          optimization. We really do not want to emit
-          __PRETTY_FUNCTION__ etc, if they're never used.  */
-       DECL_IGNORED_P (decl) = 1;
-      else
-       make_rtl_for_local_static (decl);
-    }
+    make_rtl_for_local_static (decl);
   else if (TREE_CODE (decl) == LABEL_DECL 
           && C_DECLARED_LABEL_FLAG (decl))
     declare_nonlocal_label (decl);
index 31c1f92c7fb020da8bf64b5f3f751673a81207dc..69a674d954bf3db2ff69f6b8aab02a9f5b6049e2 100644 (file)
@@ -1,3 +1,35 @@
+2001-04-24  Nathan Sidwell <nathan@codesourcery.com>
+
+       Lazy __FUNCTION__ generation.
+       * cp-tree.def (FUNCTION_NAME): Remove.
+       * cp-tree.h (function_name_declared_p): Remove.
+       (cp_fname_init): Prototype.
+       * decl.c (init_decl_processing): Don't generate __FUNCTION__ et al ids,
+       don't call declare_function_name. Call start_fname_decls.
+       (cp_make_fname_decl): Adjust parameters. Generate the name. Don't
+       clobber the line number.
+       (cp_fname_init): New function.
+       (start_function): Call start_fname_decls.
+       (finish_function): Call finish_fname_decls.
+       * lex.c (reswords): Add slots for __FUNCTION__ et al.
+       (rid_to_yy): Add mappings for __FUNCTION__ et al.
+       * optimize.c (maybe_clone_body): Remove function_name_declared_p.
+       * parse.y (VAR_FUNC_NAME): New token.
+       (primary): Add VAR_FUNC_NAME.
+       * pt.c (tsubst_decl): Adjust a DECL_PRETTY_FUNCTION_P's
+       generation.
+       (tsubst, FUNCTION_NAME case): Remove.
+       (tsubst_copy, FUNCTION_NAME case): Remove.
+       (tsubst_expr, DECL_STMT case): Be careful with a
+       DECL_PRETTY_FUNCTION_P.
+       (instantiate_decl): Remove function_name_declared_p.
+       * semantics.c (begin_compound_statement): Don't call
+       declare_function_name here.
+       (setup_vtbl_ptr). Don't save & restore function_name_declared_p.
+       (finish_translation_unit): Call finish_fname_decls.
+       (expand_body): Remove function_name_declared_p.
+       * typeck2.c (digest_init): Allow any ERROR_MARK.
+
 2001-04-24  Nathan Sidwell  <nathan@codesourcery.com>
 
        * pt.c (tsubst_decl): Use VOID_TYPE_P.
index 5e89189774dcdd7bdace96e2cb1507bcb2b7d611..486667c3a80f5b4046a4c300166f61dfad5ad9f9 100644 (file)
@@ -200,9 +200,6 @@ DEFTREECODE (WRAPPER, "wrapper", 'x', 1)
    unused.  */
 DEFTREECODE (LOOKUP_EXPR, "lookup_expr", 'e', 1)
 
-/* Used to represent __PRETTY_FUNCTION__ in template bodies.  */
-DEFTREECODE (FUNCTION_NAME, "function_name", 'e', 0)
-
 /* A whole bunch of tree codes for the initial, superficial parsing of
    templates.  */
 DEFTREECODE (MODOP_EXPR, "modop_expr", 'e', 3)
index d5c358a0176f922f33abca78f7a0c9f10449ff8d..2723c316b4ee900b9f6cf7e991a6fcac658a6ed3 100644 (file)
@@ -968,12 +968,6 @@ struct cp_language_function
 
 #define in_function_try_handler cp_function_chain->in_function_try_handler
 
-/* Nonzero if __FUNCTION__ and its ilk have been declared in this
-   function.  */
-
-#define function_name_declared_p \
-  (cp_function_chain->base.x_function_name_declared_p)
-
 extern tree current_function_return_value;
 extern tree global_namespace;
 
@@ -3911,6 +3905,7 @@ extern int nonstatic_local_decl_p               PARAMS ((tree));
 extern tree declare_global_var                  PARAMS ((tree, tree));
 extern void register_dtor_fn                    PARAMS ((tree));
 extern tmpl_spec_kind current_tmpl_spec_kind    PARAMS ((int));
+extern tree cp_fname_init                      PARAMS ((const char *));
 
 /* in decl2.c */
 extern void init_decl2                         PARAMS ((void));
index 85a731013215e4d9f3edacb3846694a7221cb903..834e2dcd5da04e1ce14a72f9af645ac0c41d1312 100644 (file)
@@ -138,7 +138,7 @@ static tree get_atexit_node PARAMS ((void));
 static tree get_dso_handle_node PARAMS ((void));
 static tree start_cleanup_fn PARAMS ((void));
 static void end_cleanup_fn PARAMS ((void));
-static tree cp_make_fname_decl PARAMS ((tree, const char *, int));
+static tree cp_make_fname_decl PARAMS ((tree, int));
 static void initialize_predefined_identifiers PARAMS ((void));
 static tree check_special_function_return_type
   PARAMS ((special_function_kind, tree, tree));
@@ -6519,6 +6519,7 @@ init_decl_processing ()
 
   {
     tree bad_alloc_type_node, newtype, deltype;
+    
     if (flag_honor_std)
       push_namespace (std_identifier);
     bad_alloc_type_node = xref_tag
@@ -6526,7 +6527,8 @@ init_decl_processing ()
     if (flag_honor_std)
       pop_namespace ();
     newtype = build_exception_variant
-      (ptr_ftype_sizetype, add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1));
+      (ptr_ftype_sizetype, add_exception_specifier
+       (NULL_TREE, bad_alloc_type_node, -1));
     deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
     push_cp_library_fn (NEW_EXPR, newtype);
     push_cp_library_fn (VEC_NEW_EXPR, newtype);
@@ -6553,13 +6555,8 @@ init_decl_processing ()
   if (! supports_one_only ())
     flag_weak = 0;
 
-  /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */
-  function_id_node = get_identifier ("__FUNCTION__");
-  pretty_function_id_node = get_identifier ("__PRETTY_FUNCTION__");
-  func_id_node = get_identifier ("__func__");
-
   make_fname_decl = cp_make_fname_decl;
-  declare_function_name ();
+  start_fname_decls ();
 
   /* Prepare to check format strings against argument lists.  */
   init_function_format_info ();
@@ -6607,57 +6604,68 @@ init_decl_processing ()
   ggc_add_tree_root (&free_bindings, 1);
 }
 
+/* Generate an initializer for a function naming variable from
+   NAME. NAME may be NULL, in which case we generate a special
+   ERROR_MARK node which should be replaced later. */
+
+tree
+cp_fname_init (name)
+     const char *name;
+{
+  tree domain = NULL_TREE;
+  tree type;
+  tree init = NULL_TREE;
+  size_t length = 0;
+
+  if (name)
+    {
+      length = strlen (name);
+      domain = build_index_type (size_int (length));
+      init = build_string (length + 1, name);
+    }
+  
+  type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
+  type = build_cplus_array_type (type, domain);
+
+  if (init)
+    TREE_TYPE (init) = type;
+  else
+    /* We don't know the value until instantiation time. Make
+       something which will be digested now, but replaced later. */
+    init = build (ERROR_MARK, type);
+  
+  return init;
+}
+
 /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
    decl, NAME is the initialization string and TYPE_DEP indicates whether
    NAME depended on the type of the function. We make use of that to detect
-   __PRETTY_FUNCTION__ inside a template fn.  Because we build a tree for
-   the function before emitting any of it, we don't need to treat the
-   VAR_DECL specially. We can decide whether to emit it later, if it was
-   used.  */
+   __PRETTY_FUNCTION__ inside a template fn. This is being done
+   lazily at the point of first use, so we musn't push the decl now.  */
 
 static tree
-cp_make_fname_decl (id, name, type_dep)
+cp_make_fname_decl (id, type_dep)
      tree id;
-     const char *name;
      int type_dep;
 {
-  tree decl, type, init;
-  size_t length = strlen (name);
-  tree domain = NULL_TREE;
-
-  if (!processing_template_decl)
-    type_dep = 0;
-  if (!type_dep)
-    domain = build_index_type (size_int (length));
-
-  type =  build_cplus_array_type
-          (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
-          domain);
+  const char *name = (type_dep && processing_template_decl
+                     ? NULL : fname_as_string (type_dep));
+  tree init = cp_fname_init (name);
+  tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
 
-  decl = build_decl (VAR_DECL, id, type);
+  /* As we don't push the decl here, we must set the context. */
+  DECL_CONTEXT (decl) = current_function_decl;
+  DECL_PRETTY_FUNCTION_P (decl) = type_dep;
+      
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
-  DECL_SOURCE_LINE (decl) = 0;
   DECL_ARTIFICIAL (decl) = 1;
-  DECL_IN_SYSTEM_HEADER (decl) = 1;
-  DECL_IGNORED_P (decl) = 1;
-  pushdecl (decl);
-  if (processing_template_decl)
-    decl = push_template_decl (decl);
-  if (type_dep)
-    {
-      init = build (FUNCTION_NAME, type);
-      DECL_PRETTY_FUNCTION_P (decl) = 1;
-    }
-  else
-    {
-      init = build_string (length + 1, name);
-      TREE_TYPE (init) = type;
-    }
   DECL_INITIAL (decl) = init;
-  cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+  
+  TREE_USED (decl) = 1;
 
-  /* We will have to make sure we only emit this, if it is actually used. */
+  cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+      
   return decl;
 }
 
@@ -12966,6 +12974,7 @@ finish_enum (enumtype)
       if (scope && TREE_CODE (scope) == FUNCTION_DECL)
        add_stmt (build_min (TAG_DEFN, enumtype));
 
+
       return;
     }
 
@@ -13602,6 +13611,8 @@ start_function (declspecs, declarator, attrs, flags)
       DECL_CONTEXT (dtor_label) = current_function_decl;
     }
 
+  start_fname_decls ();
+  
   store_parm_decls (current_function_parms);
 
   return 1;
@@ -13931,6 +13942,8 @@ finish_function (flags)
 
   my_friendly_assert (building_stmt_tree (), 20000911);
 
+  finish_fname_decls ();
+  
   /* For a cloned function, we've already got all the code we need;
      there's no need to add any extra bits.  */
   if (!DECL_CLONED_FUNCTION_P (fndecl))
index cb6a4d92461ae8910fe188cd8447fb0fb7a774da..f005482aec1776fd4e42011aa55ed945b663a718 100644 (file)
@@ -402,6 +402,8 @@ CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT);
 static const struct resword reswords[] =
 {
   { "_Complex",                RID_COMPLEX,    0 },
+  { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
+  { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
   { "__alignof",       RID_ALIGNOF,    0 },
   { "__alignof__",     RID_ALIGNOF,    0 },
   { "__asm",           RID_ASM,        0 },
@@ -414,6 +416,7 @@ static const struct resword reswords[] =
   { "__const",         RID_CONST,      0 },
   { "__const__",       RID_CONST,      0 },
   { "__extension__",   RID_EXTENSION,  0 },
+  { "__func__",                RID_C99_FUNCTION_NAME,  0 },
   { "__imag",          RID_IMAGPART,   0 },
   { "__imag__",                RID_IMAGPART,   0 },
   { "__inline",                RID_INLINE,     0 },
@@ -585,6 +588,10 @@ const short rid_to_yy[RID_MAX] =
   /* RID_PTREXTENT */  0,
   /* RID_PTRVALUE */   0,
 
+  /* RID_FUNCTION_NAME */      VAR_FUNC_NAME,
+  /* RID_PRETTY_FUNCTION_NAME */ VAR_FUNC_NAME,
+  /* RID_c99_FUNCTION_NAME */  VAR_FUNC_NAME,
+
   /* C++ */
   /* RID_BOOL */       TYPESPEC,
   /* RID_WCHAR */      TYPESPEC,
index 8f6fd0e6fcfc1f27f82da31404d15dadb6fccb53..2ed10ea0c341e82ed609ccf6656d154490264090 100644 (file)
@@ -1123,7 +1123,6 @@ maybe_clone_body (fn)
       VARRAY_FREE (id.fns);
 
       /* Now, expand this function into RTL, if appropriate.  */
-      function_name_declared_p = 1;
       finish_function (0);
       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
       expand_body (clone);
index 37a2bb482f126e1383bfb4c1372c8885d1e472b0..22b3e9583a7320f079b4406dcf2113e622e01345 100644 (file)
@@ -259,6 +259,10 @@ cp_parse_init ()
    yylval is the node for the constant.  */
 %token CONSTANT
 
+/* __func__, __FUNCTION__ or __PRETTY_FUNCTION__.
+   yylval contains an IDENTIFIER_NODE which indicates which one.  */
+%token VAR_FUNC_NAME
+
 /* String constants in raw form.
    yylval is a STRING_CST node.  */
 %token STRING
@@ -1556,6 +1560,12 @@ primary:
                      (TREE_TYPE (TREE_TYPE ($$)),
                       TYPE_DOMAIN (TREE_TYPE ($$)));
                }
+       | VAR_FUNC_NAME
+               {
+                 $$ = fname_decl (C_RID_CODE ($$), $$);
+                 if (processing_template_decl)
+                   $$ = build_min_nt (LOOKUP_EXPR, DECL_NAME ($$));
+               }
        | '(' expr ')'
                { $$ = finish_parenthesized_expr ($2); }
        | '(' expr_or_declarator_intern ')'
index 1b88a783986602cddf45084bfc9e438e7c6e5af0..2a1dc4414ae6d86c81a69d11efd20e8f866f133a 100644 (file)
@@ -5987,10 +5987,9 @@ tsubst_decl (t, args, type)
        /* For __PRETTY_FUNCTION__ we have to adjust the initializer.  */
        if (DECL_PRETTY_FUNCTION_P (r))
          {
-           DECL_INITIAL (r) = tsubst (DECL_INITIAL (t),
-                                      args,
-                                      /*complain=*/1,
-                                      NULL_TREE);
+           const char *name = (*decl_printable_name)
+                               (current_function_decl, 2);
+           DECL_INITIAL (r) = cp_fname_init (name);
            TREE_TYPE (r) = TREE_TYPE (DECL_INITIAL (r));
          }
 
@@ -6794,24 +6793,6 @@ tsubst (t, args, complain, in_decl)
        return TREE_TYPE (e1); 
       }
 
-    case FUNCTION_NAME:
-      {
-       const char *name;
-       int len;
-       tree type;
-       tree str;
-
-       /* This code should match declare_hidden_char_array in
-          c-common.c.  */
-       name = (*decl_printable_name) (current_function_decl, 2);
-       len = strlen (name) + 1;
-       type =  build_array_type (char_type_node, 
-                                 build_index_type (size_int (len)));
-       str = build_string (len, name);
-       TREE_TYPE (str) = type;
-       return str;
-      }
-
     default:
       sorry ("use of `%s' in template",
             tree_code_name [(int) TREE_CODE (t)]);
@@ -7172,9 +7153,6 @@ tsubst_copy (t, args, complain, in_decl)
                                        in_decl),
                           tsubst (TREE_TYPE (t), args, complain, in_decl));
 
-    case FUNCTION_NAME:
-      return tsubst (t, args, complain, in_decl);
-
     default:
       return t;
     }
@@ -7254,7 +7232,10 @@ tsubst_expr (t, args, complain, in_decl)
          {
            init = DECL_INITIAL (decl);
            decl = tsubst (decl, args, complain, in_decl);
-           init = tsubst_expr (init, args, complain, in_decl);
+           if (DECL_PRETTY_FUNCTION_P (decl))
+             init = DECL_INITIAL (decl);
+           else
+             init = tsubst_expr (init, args, complain, in_decl);
            if (decl != error_mark_node)
              {
                 if (TREE_CODE (decl) != TYPE_DECL)
@@ -9934,10 +9915,6 @@ instantiate_decl (d, defer_ok)
       /* Set up context.  */
       start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
 
-      /* We already set up __FUNCTION__, etc., so we don't want to do
-        it again now.  */
-      function_name_declared_p = 1;
-
       /* Substitute into the body of the function.  */
       tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
                   /*complain=*/1, tmpl);
index 8dae039192e91b3b2f5841c9becd01cf5e07c01f..5a42fd034a24f746159bc7de92e1aad952739aac 100644 (file)
@@ -852,16 +852,6 @@ begin_compound_stmt (has_no_scope)
        to accidentally keep a block *inside* the scopeless block.  */ 
     keep_next_level (0);
 
-  /* If this is the outermost block of the function, declare the
-     variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth.  */
-  if (cfun
-      && !function_name_declared_p
-      && !has_no_scope)
-    {
-      function_name_declared_p = 1;
-      declare_function_name ();
-    }
-
   return r;
 }
 
@@ -1180,7 +1170,6 @@ setup_vtbl_ptr (member_init_list, base_init_list)
     {
       tree if_stmt;
       tree compound_stmt;
-      int saved_cfnd;
 
       /* If the dtor is empty, and we know there is not any possible
         way we could use any vtable entries, before they are possibly
@@ -1201,12 +1190,7 @@ setup_vtbl_ptr (member_init_list, base_init_list)
       finish_if_stmt_cond (boolean_true_node, if_stmt);
       current_vcalls_possible_p = &IF_COND (if_stmt);
 
-      /* Don't declare __PRETTY_FUNCTION__ and friends here when we
-        open the block for the if-body.  */
-      saved_cfnd = function_name_declared_p;
-      function_name_declared_p = 1;
       compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
-      function_name_declared_p = saved_cfnd;
 
       /* Make all virtual function table pointers in non-virtual base
         classes point to CURRENT_CLASS_TYPE's virtual function
@@ -1706,6 +1690,10 @@ finish_translation_unit ()
   pop_everything ();
   while (current_namespace != global_namespace)
     pop_namespace ();
+
+  /* Do file scope __FUNCTION__ et al. */
+  finish_fname_decls ();
+  
   finish_file ();
 }
 
@@ -2472,11 +2460,6 @@ expand_body (fn)
   genrtl_start_function (fn);
   current_function_is_thunk = DECL_THUNK_P (fn);
 
-  /* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
-     any of the other magic variables we set up when starting a
-     function body.  */
-  function_name_declared_p = 1;
-
   /* Expand the body.  */
   expand_stmt (DECL_SAVED_TREE (fn));
 
index 3c26b1b8ddad7eddf4288bb65b37777ad0b172cc..26b2a1c5a7147a633ce3238ea0a800006bb5c171 100644 (file)
@@ -470,6 +470,11 @@ digest_init (type, init, tail)
                                  && TREE_VALUE (init) == error_mark_node))
     return error_mark_node;
 
+  if (TREE_CODE (init) == ERROR_MARK)
+    /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside
+       a template function. This gets substituted during instantiation. */
+    return init;
+  
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   if (TREE_CODE (init) == NON_LVALUE_EXPR)
     init = TREE_OPERAND (init, 0);
index ac18210b6c07f439781de56d26ec3abb682b54c8..b93b67523abb2564c2ddcbed849ea8e1e2f9fc56 100644 (file)
@@ -1,3 +1,9 @@
+2001-04-24  Nathan Sidwell <nathan@codesourcery.com>
+
+       * gcc.dg/c99-func-2.c: Remove xfail.
+       * gcc.dg/c99-func-3.c: Remove xfail.
+       * gcc.dg/c99-func-4.c: Remove xfail.
+
 2001-04-23  Zack Weinberg  <zackw@stanford.edu>
 
        * gcc.c-torture/execute/20010124-1.c: No longer expected to fail.
index 11737d6ce45f8312c535bb8a63afa1bd75c7461f..d6a6f243f91293bdf747e07124257df8052d8bd0 100644 (file)
@@ -6,6 +6,5 @@
 void
 foo (void)
 {
-  __func__ "foo"; /* { dg-bogus "warning" "warning in place of error" } */
-  /* { dg-error "parse error" "__func__ not string constant" { xfail *-*-* } 9 } */
+  __func__ "foo"; /* { dg-error "parse error" "before string constant" } */
 }
index 5fa920a9f654f42e5c5ec55f1c34d0818a292936..f8a06a0e750952aeaea1d21bb68edf1821b41b84 100644 (file)
@@ -1,6 +1,6 @@
 /* Test for C99 __func__: not merging with string literals.  */
 /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
-/* { dg-do run { xfail *-*-* } } */
+/* { dg-do run } */
 /* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
 
 extern void abort (void);
index d1388033dabf0797af4a64a8911d714b127cf88e..10ec19566f8762ae0e918ef97b3cad02efa41822 100644 (file)
@@ -6,5 +6,5 @@
 void
 foo (void)
 {
-  char *p = __func__; /* { dg-error "discards" "__func__ pointer to const" { xfail *-*-* } } */
+  char *p = __func__; /* { dg-error "discards" "__func__ pointer to const" } */
 }
This page took 0.13866 seconds and 5 git commands to generate.