diff options
author | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-04-24 08:22:06 +0000 |
---|---|---|
committer | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2001-04-24 08:22:06 +0000 |
commit | 65b7f83fcb833ccbead60bbb1533884ad0898486 (patch) | |
tree | 268353894884ce2459e1f3b08adc4825b8ed0dd6 /gcc/cp | |
parent | 2b686fc594fc9314f3585e5f0e32a8d15fb79765 (diff) | |
download | gcc-65b7f83fcb833ccbead60bbb1533884ad0898486.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41520 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 32 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 3 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 103 | ||||
-rw-r--r-- | gcc/cp/lex.c | 7 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 1 | ||||
-rw-r--r-- | gcc/cp/parse.y | 10 | ||||
-rw-r--r-- | gcc/cp/pt.c | 37 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 25 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 5 |
10 files changed, 124 insertions, 106 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 31c1f92c7fb..69a674d954b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 5e89189774d..486667c3a80 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 d5c358a0176..2723c316b4e 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 85a73101321..834e2dcd5da 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 cb6a4d92461..f005482aec1 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 8f6fd0e6fcf..2ed10ea0c34 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 37a2bb482f1..22b3e9583a7 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 1b88a783986..2a1dc4414ae 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 8dae039192e..5a42fd034a2 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 3c26b1b8dda..26b2a1c5a71 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); |