From: Nathan Sidwell Date: Tue, 24 Apr 2001 08:22:06 +0000 (+0000) Subject: Lazy __FUNCTION__ generation. X-Git-Tag: prereleases/libstdc++-3.0.95~4801 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=0ba8a114c724d36034e8996eefb7c94d4fe8aed0;p=gcc.git Lazy __FUNCTION__ generation. 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7569d1225ba3..cd986491a4ed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,54 @@ +2001-04-24 Zack Weinberg + Nathan Sidwell + + 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 * dwarf2out.c (mem_loc_descriptor): If a SYMBOL_REF is in the diff --git a/gcc/c-common.c b/gcc/c-common.c index 1b00362ba0dd..872750320ed4 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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, diff --git a/gcc/c-common.h b/gcc/c-common.h index fbdf1570d718..b9a7a9dd97f2 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -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)); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index a8c1d300b2bd..a386ecdad15a 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -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)); /* 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; } diff --git a/gcc/c-parse.in b/gcc/c-parse.in index d187ab4e16a6..657c3fb700b9 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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) { diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index c491335e1e86..13480480a433 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -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); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 31c1f92c7fb0..69a674d954bf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,35 @@ +2001-04-24 Nathan Sidwell + + 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 * pt.c (tsubst_decl): Use VOID_TYPE_P. diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 5e89189774dc..486667c3a80f 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d5c358a0176f..2723c316b4ee 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 85a731013215..834e2dcd5da0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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)) diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index cb6a4d92461a..f005482aec17 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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, diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 8f6fd0e6fcfc..2ed10ea0c341 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -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); diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 37a2bb482f12..22b3e9583a73 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -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 ')' diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1b88a7839866..2a1dc4414ae6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8dae039192e9..5a42fd034a24 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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)); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 3c26b1b8ddad..26b2a1c5a714 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ac18210b6c07..b93b67523abb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2001-04-24 Nathan Sidwell + + * 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 * gcc.c-torture/execute/20010124-1.c: No longer expected to fail. diff --git a/gcc/testsuite/gcc.dg/c99-func-2.c b/gcc/testsuite/gcc.dg/c99-func-2.c index 11737d6ce45f..d6a6f243f912 100644 --- a/gcc/testsuite/gcc.dg/c99-func-2.c +++ b/gcc/testsuite/gcc.dg/c99-func-2.c @@ -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" } */ } diff --git a/gcc/testsuite/gcc.dg/c99-func-3.c b/gcc/testsuite/gcc.dg/c99-func-3.c index 5fa920a9f654..f8a06a0e7509 100644 --- a/gcc/testsuite/gcc.dg/c99-func-3.c +++ b/gcc/testsuite/gcc.dg/c99-func-3.c @@ -1,6 +1,6 @@ /* Test for C99 __func__: not merging with string literals. */ /* Origin: Joseph Myers */ -/* { dg-do run { xfail *-*-* } } */ +/* { dg-do run } */ /* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/c99-func-4.c b/gcc/testsuite/gcc.dg/c99-func-4.c index d1388033dabf..10ec19566f87 100644 --- a/gcc/testsuite/gcc.dg/c99-func-4.c +++ b/gcc/testsuite/gcc.dg/c99-func-4.c @@ -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" } */ }