+2000-03-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * 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.
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;
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));
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,
#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));
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));
\f
/* C-specific option variables. */
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 ();
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.
+2000-03-08 Nathan Sidwell <nathan@codesourcery.com>
+
+ * 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 <nathan@codesourcery.com>
* typeck.c (convert_for_assignment): Don't look at array
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));
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)
{
/* 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.
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. */
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
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);
&& !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;
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;
/* 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);