From 2ce07e2d9247f692e424385deb1e8b154bf1b388 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 8 Mar 2000 11:21:28 +0000 Subject: [PATCH] c-common.h (make_fname_decl): Declare. gcc: * c-common.h (make_fname_decl): Declare. * c-common.c (make_fname_decl): Define. (declare_hidden_char_array): Remove. (declare_function_name): Use make_fname_decl. * c-decl.c (c_make_fname_decl): New function. (init_decl_processing): Set make_fname_decl. gcc/cp: * decl.c (cp_make_fname_decl): New function. (wrapup_globals_for_namespace): Don't emit unused static vars. (init_decl_processing): Remove comment about use of array_domain_type. Set make_fname_decl. (cp_finish_decl): Remove __FUNCTION__ nadgering. * semantics.c (begin_compound_stmt): Remove current_function_name_declared flagging. (expand_stmt): Don't emit unused local statics. * typeck.c (decay_conversion): Don't treat __FUNCTION__ decls specially. From-SVN: r32418 --- gcc/ChangeLog | 9 +++++ gcc/c-common.c | 41 ++++----------------- gcc/c-common.h | 7 ++++ gcc/c-decl.c | 39 ++++++++++++++++++++ gcc/cp/ChangeLog | 13 +++++++ gcc/cp/decl.c | 89 +++++++++++++++++++++++++++++++++------------- gcc/cp/semantics.c | 13 ++++--- gcc/cp/typeck.c | 8 ++--- 8 files changed, 147 insertions(+), 72 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a25e94c7de2a..60c467d0f679 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2000-03-08 Nathan Sidwell + + * c-common.h (make_fname_decl): Declare. + * c-common.c (make_fname_decl): Define. + (declare_hidden_char_array): Remove. + (declare_function_name): Use make_fname_decl. + * c-decl.c (c_make_fname_decl): New function. + (init_decl_processing): Set make_fname_decl. + Tue Mar 7 23:50:31 2000 Jeffrey A Law (law@cygnus.com) * cccp.c (handle_directive): Initialize backslash_newlines_p. diff --git a/gcc/c-common.c b/gcc/c-common.c index 35e2b0201152..6acc1fd9e8a6 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -135,6 +135,8 @@ enum cpp_token cpp_token; tree c_global_trees[CTI_MAX]; +tree (*make_fname_decl) PARAMS ((tree, const char *, int)); + /* Nonzero means the expression being parsed will never be evaluated. This is a count, since unevaluated expressions can nest. */ int skip_evaluation; @@ -148,7 +150,6 @@ enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION, enum format_type { printf_format_type, scanf_format_type, strftime_format_type }; -static void declare_hidden_char_array PARAMS ((const char *, const char *)); static void add_attribute PARAMS ((enum attrs, const char *, int, int, int)); static void init_attributes PARAMS ((void)); @@ -269,42 +270,12 @@ declare_function_name () name = ""; printable_name = (*decl_printable_name) (current_function_decl, 2); } - - declare_hidden_char_array ("__FUNCTION__", name); - declare_hidden_char_array ("__PRETTY_FUNCTION__", printable_name); + + (*make_fname_decl) (get_identifier ("__FUNCTION__"), name, 0); + (*make_fname_decl) (get_identifier ("__PRETTY_FUNCTION__"), printable_name, 1); /* The ISO C people "of course" couldn't use __FUNCTION__ in the ISO C 99 standard; instead a new variable is invented. */ - declare_hidden_char_array ("__func__", name); -} - -static void -declare_hidden_char_array (name, value) - const char *name, *value; -{ - tree decl, type, init; - unsigned int vlen; - - /* If the default size of char arrays isn't big enough for the name, - or if we want to give warnings for large objects, make a bigger one. */ - vlen = strlen (value) + 1; - type = char_array_type_node; - if (compare_tree_int (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), vlen) < 0 - || warn_larger_than) - type = build_array_type (char_type_node, - build_index_type (build_int_2 (vlen, 0))); - - decl = build_decl (VAR_DECL, get_identifier (name), type); - 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 (vlen, value); - TREE_TYPE (init) = type; - DECL_INITIAL (decl) = init; - finish_decl (pushdecl (decl), init, NULL_TREE); + (*make_fname_decl) (get_identifier ("__func__"), name, 0); } /* Given a chain of STRING_CST nodes, diff --git a/gcc/c-common.h b/gcc/c-common.h index dfcac1ea8b6f..17db8fbdc402 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -74,6 +74,13 @@ extern tree c_global_trees[CTI_MAX]; #define int_ftype_int c_global_trees[CTI_INT_FTYPE_INT] #define ptr_ftype_sizetype c_global_trees[CTI_PTR_FTYPE_SIZETYPE] +/* Pointer to function to 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 void declare_function_name PARAMS ((void)); extern void decl_attributes PARAMS ((tree, tree, tree)); extern void init_function_format_info PARAMS ((void)); diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 6b5d295a2fa3..8a574601a9ca 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -288,6 +288,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)); /* C-specific option variables. */ @@ -3059,6 +3060,7 @@ init_decl_processing () pedantic_lvalues = pedantic; /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */ + make_fname_decl = c_make_fname_decl; declare_function_name (); start_identifier_warnings (); @@ -3085,6 +3087,43 @@ init_decl_processing () ggc_add_tree_root (&static_dtors, 1); } +/* 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. As we don't yet implement + delayed emission of static data, we mark the decl as emitted + so it is not placed in the output. Anything using it must therefore pull + out the STRING_CST initializer directly. This does mean that these names + are string merging candidates, which C99 does not permit. */ + +static tree +c_make_fname_decl (id, name, type_dep) + tree id; + const char *name; + int type_dep ATTRIBUTE_UNUSED; +{ + 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))); + + decl = build_decl (VAR_DECL, id, type); + 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); + + return decl; +} + /* Return a definition for a builtin function named NAME and whose data type is TYPE. TYPE should be a function type with argument types. FUNCTION_CODE tells later passes how to compile calls to this function. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 948ea7dab59f..c4af8f9e40bc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2000-03-08 Nathan Sidwell + + * decl.c (cp_make_fname_decl): New function. + (wrapup_globals_for_namespace): Don't emit unused static vars. + (init_decl_processing): Remove comment about use of + array_domain_type. Set make_fname_decl. + (cp_finish_decl): Remove __FUNCTION__ nadgering. + * semantics.c (begin_compound_stmt): Remove + current_function_name_declared flagging. + (expand_stmt): Don't emit unused local statics. + * typeck.c (decay_conversion): Don't treat __FUNCTION__ decls + specially. + 2000-03-08 Nathan Sidwell * typeck.c (convert_for_assignment): Don't look at array diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c3d070da6f34..63fc93aa0a80 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -182,6 +182,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)); #if defined (DEBUG_CP_BINDING_LEVELS) static void indent PARAMS ((void)); @@ -1784,7 +1785,15 @@ wrapup_globals_for_namespace (namespace, data) Put them into VEC from back to front, then take out from front. */ for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) - vec[len - i - 1] = decl; + { + /* Pretend we've output an unused static variable. This ensures + that the toplevel __FUNCTION__ etc won't be emitted, unless + needed. */ + if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) + && !TREE_USED (decl)) + TREE_ASM_WRITTEN (decl) = 1; + vec[len - i - 1] = decl; + } if (last_time) { @@ -6168,9 +6177,7 @@ init_decl_processing () /* Make a type to be the domain of a few array types whose domains don't really matter. - 200 is small enough that it always fits in size_t - and large enough that it can hold most function names for the - initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */ + 200 is small enough that it always fits in size_t. */ array_domain_type = build_index_type (build_int_2 (200, 0)); /* Make a type for arrays of characters. @@ -6340,6 +6347,7 @@ init_decl_processing () flag_weak = 0; /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */ + make_fname_decl = cp_make_fname_decl; declare_function_name (); /* Prepare to check format strings against argument lists. */ @@ -6390,6 +6398,59 @@ init_decl_processing () ggc_add_tree_root (&static_aggregates, 1); } +/* 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. */ + +static tree +cp_make_fname_decl (id, name, 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 (build_int_2 (length, 0)); + + type = build_cplus_array_type + (build_qualified_type (char_type_node, TYPE_QUAL_CONST), + domain); + + decl = build_lang_decl (VAR_DECL, id, type); + TREE_STATIC (decl) = 1; + TREE_READONLY (decl) = 1; + DECL_SOURCE_LINE (decl) = 0; + DECL_ARTIFICIAL (decl) = 1; + DECL_IN_SYSTEM_HEADER (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); + + /* We will have to make sure we only emit this, if it is actually used. */ + return decl; +} + /* Function to print any language-specific context for an error message. */ static void @@ -7627,26 +7688,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags) return; } - /* Handling __FUNCTION__ and its ilk in a template-function requires - some special processing because we are called from - language-independent code. */ - if (cfun && processing_template_decl - && current_function_name_declared == 2) - { - /* Since we're in a template function, we need to - push_template_decl. The language-independent code in - declare_hidden_char_array doesn't know to do this. */ - retrofit_lang_decl (decl); - decl = push_template_decl (decl); - - if (strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), - "__PRETTY_FUNCTION__") == 0) - { - init = build (FUNCTION_NAME, const_string_type_node); - DECL_PRETTY_FUNCTION_P (decl) = 1; - } - } - /* If a name was specified, get the string. */ if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index ad961f8b9a0c..3402d3bb5f4b 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -980,13 +980,8 @@ begin_compound_stmt (has_no_scope) && !current_function_name_declared && !has_no_scope) { - /* When we get callbacks from the middle-end, we need to know - we're in the midst of declaring these variables. */ - current_function_name_declared = 2; - /* Actually insert the declarations. */ - declare_function_name (); - /* And now just remember that we're all done. */ current_function_name_declared = 1; + declare_function_name (); } return r; @@ -2397,7 +2392,11 @@ expand_stmt (t) expand_anon_union_decl (decl, NULL_TREE, DECL_ANON_UNION_ELEMS (decl)); } - else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) + else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (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. */ make_rtl_for_local_static (decl); } break; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 071d2eef18f4..868ebec6a555 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1716,12 +1716,8 @@ decay_conversion (exp) /* Replace a nonvolatile const static variable with its value. We don't do this for arrays, though; we want the address of the first element of the array, not the address of the first element - of its initializing constant. We *do* replace variables that the - user isn't really supposed to know about; this is a hack to deal - with __PRETTY_FUNCTION__ and the like. */ - else if (TREE_READONLY_DECL_P (exp) - && (code != ARRAY_TYPE - || (TREE_CODE (exp) == VAR_DECL && DECL_IGNORED_P (exp)))) + of its initializing constant. */ + else if (TREE_READONLY_DECL_P (exp) && code != ARRAY_TYPE) { exp = decl_constant_value (exp); type = TREE_TYPE (exp);