This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Lazy __FUNCTION__ processing.
- To: gcc-patches at gcc dot gnu dot org
- Subject: Lazy __FUNCTION__ processing.
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Fri, 20 Apr 2001 15:44:32 +0100
- CC: mark at codesourcery dot com, zackw at stanford dot edu, pfeifer at dbai dot tuwien dot ac dot at
- Organization: Codesourcery LLC
Hi,
here's a patch which implements lazy processing of __FUNCTION__,
__PRETTY_FUNCTION__ and __func__. The current implementation instantiates
these VAR_DECLS at the start of every function, and then takes steps
to remove them if they were unused. This implementation makes them
keywords which can either be intercepted in the lexer (to generate
string constants), or in the parser (to generate a VAR_DECL).
As we now use function-at-a-time compilation this is relatively easy.
The string constant case is rather trivial, and applies to C's handling
of __FUNCTION__ and __PRETTY_FUNCTION__. for the variable case
(__func__ and C++), we have three global variables which hold the
relevant VAR_DECL. If it is NULL, the VAR_DECL is created, and any
statement tree that that generates is squirrelled away until the end of
the function (it will have been created in the scope of first use). At
the end of the function, should any of these variables have been created,
their statement trees are consed up to the start of the function, inside
a new compound statement. We no longer have to walk the tree pruning
unused decls.
We have to push and pop existing declarations of these things to deal with
their use at file scope and for nested functions.
This also fixes bug 460 where C was treating __func__ as a string constant
not a constant array of char.
I ran some tests on one of Gerald's C++ files that he sent me. It showed
a reduction in memory usage, but negligible change in speed. Here are the
contracted diffs from compiler runs.
< == old
> == new
tree space
< block 11518 359k 1.207
> block 12537 391k 1.415
< integer_type 361 36k 0.123
> integer_type 284 28k 0.104
< array_type 13971 1418k 4.760
> array_type 929 94k 0.341
< integer_cst 6667 208k 0.699
> integer_cst 6543 204k 0.739
< string_cst 8735 272k 0.916
> string_cst 4439 138k 0.501
< var_decl 12815 1301k 4.366
> var_decl 6372 647k 2.338
< function_name 2147 33k 0.113
< Total 571016 29M
> Total 545906 27M
ggc areas
< Total 44M 31M 454k
> Total 41M 29M 425k
string space
< entries 21296
> entries 19094
< bytes 1323k (59k overhead)
> bytes 1243k (56k overhead)
run time
< TOTAL : 44.80 0.57 48.21
> TOTAL : 45.55 0.80 50.45
The savings are not just the string values, but also the number of array types
and var_decls. (The var decls will be gc'd, but the others not so.)
So a saving of around 6% in memory. The one number that went up is the number
of block trees, I'm not sure why that is.
booted and tested on i686-pc-linux-gnu, ok for mainline.
I've not tested this on the branch, let me know if that's appropriate.
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
gcc:
2001-04-20 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.
* 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:
2001-04-20 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.
testsuite:
2001-04-20 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.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.c,v
retrieving revision 1.229
diff -c -3 -p -r1.229 c-common.c
*** c-common.c 2001/03/28 11:03:48 1.229
--- c-common.c 2001/04/20 14:22:24
*************** cpp_reader *parse_in; /* Declared in c-
*** 164,174 ****
tree void_list_node;
! The identifiers __FUNCTION__, __PRETTY_FUNCTION__, and __func__.
! tree function_id_node;
! tree pretty_function_id_node;
! tree func_id_node;
*/
--- 164,180 ----
tree void_list_node;
! 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_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;
*/
*************** int warn_sequence_point;
*** 204,210 ****
type names and storage classes. It is indexed by a RID_... value. */
tree *ridpointers;
! tree (*make_fname_decl) PARAMS ((tree, const char *, int));
/* If non-NULL, the address of a language-specific function that
returns 1 for language-specific statement codes. */
--- 210,216 ----
type names and storage classes. It is indexed by a RID_... value. */
tree *ridpointers;
! 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. */
*************** enum attrs {A_PACKED, A_NOCOMMON, A_COMM
*** 228,233 ****
--- 234,260 ----
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));
*************** c_finish_else ()
*** 344,377 ****
RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
}
! /* Make bindings for __FUNCTION__, __PRETTY_FUNCTION__, and __func__. */
void
! declare_function_name ()
{
! const char *name, *printable_name;
! if (current_function_decl == NULL)
{
! name = "";
! printable_name = "top level";
}
else
{
! /* 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);
!
! /* 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);
}
! (*make_fname_decl) (function_id_node, name, 0);
! (*make_fname_decl) (pretty_function_id_node, printable_name, 1);
}
/* Given a chain of STRING_CST nodes,
--- 371,510 ----
RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
}
! /* 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 front of the
! current function's statement tree (should there be one). Pop
! the previous bindings. */
!
! void
! finish_fname_decls ()
! {
! unsigned ix;
! tree body = NULL_TREE;
! tree stack = saved_function_name_decls;
!
! for (; stack && TREE_VALUE (stack); stack = TREE_CHAIN (stack))
! body = chainon (TREE_VALUE (stack), body);
!
! if (body)
! {
! /* 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;
! }
!
! for (ix = 0; fname_vars[ix].decl; ix++)
! *fname_vars[ix].decl = NULL_TREE;
!
! if (stack)
{
! /* We had saved values, restore them. */
! tree saved;
!
! 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;
+ }
+
+ 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;
+ }
+
+ 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);
+ }
+
+ 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");
! return decl;
}
/* Given a chain of STRING_CST nodes,
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.66
diff -c -3 -p -r1.66 c-common.h
*** c-common.h 2001/04/12 18:23:08 1.66
--- c-common.h 2001/04/20 14:22:24
*************** enum rid
*** 75,80 ****
--- 75,83 ----
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,
*************** enum c_tree_index
*** 153,164 ****
CTI_G77_UINTEGER_TYPE,
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,
CTI_VOID_ZERO,
CTI_MAX
--- 156,168 ----
CTI_G77_UINTEGER_TYPE,
CTI_G77_LONGINT_TYPE,
CTI_G77_ULONGINT_TYPE,
+ /* 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
*************** enum c_tree_index
*** 202,210 ****
#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]
/* A node for `((void) 0)'. */
#define void_zero_node c_global_trees[CTI_VOID_ZERO]
--- 206,215 ----
#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_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]
*************** struct language_function {
*** 260,268 ****
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
--- 265,270 ----
*************** extern int warn_long_long;
*** 468,486 ****
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.
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 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 decl_attributes PARAMS ((tree, tree, tree));
extern void init_function_format_info PARAMS ((void));
extern void check_function_format PARAMS ((int *, tree, tree, tree));
--- 470,491 ----
what operator was specified for it. */
#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
! /* 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, 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 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: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.217
diff -c -3 -p -r1.217 c-decl.c
*** c-decl.c 2001/03/28 11:03:49 1.217
--- c-decl.c 2001/04/20 14:22:26
*************** static struct stmt_tree_s c_stmt_tree;
*** 104,114 ****
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. */
--- 104,109 ----
*************** static tree grokdeclarator PARAMS ((tre
*** 279,285 ****
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 void c_expand_body PARAMS ((tree, int));
/* C-specific option variables. */
--- 274,280 ----
int));
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
! static tree c_make_fname_decl PARAMS ((tree, int));
static void c_expand_body PARAMS ((tree, int));
/* C-specific option variables. */
*************** init_decl_processing ()
*** 3093,3105 ****
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_identifier_warnings ();
--- 3088,3095 ----
pedantic_lvalues = pedantic;
make_fname_decl = c_make_fname_decl;
! start_fname_decls ();
start_identifier_warnings ();
*************** init_decl_processing ()
*** 3132,3162 ****
are string merging candidates, which is wrong for C99's __func__. FIXME. */
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;
}
--- 3122,3155 ----
are string merging candidates, which is wrong for C99's __func__. FIXME. */
static tree
! c_make_fname_decl (id, type_dep)
tree id;
! 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 (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;
DECL_ARTIFICIAL (decl) = 1;
!
init = build_string (length + 1, name);
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
+ TREE_USED (decl) = 1;
+
+ finish_decl (decl, init, NULL_TREE);
+
return decl;
}
*************** finish_decl (decl, init, asmspec_tree)
*** 3487,3495 ****
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;
--- 3480,3488 ----
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;
*************** finish_decl (decl, init, asmspec_tree)
*** 3507,3513 ****
}
/* 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)
--- 3500,3505 ----
*************** start_function (declspecs, declarator, p
*** 6029,6034 ****
--- 6021,6028 ----
immediate_size_expand = old_immediate_size_expand;
+ start_fname_decls ();
+
return 1;
}
*************** finish_function (nested)
*** 6656,6661 ****
--- 6650,6657 ----
#endif
}
}
+
+ finish_fname_decls ();
/* Tie off the statement tree for this function. */
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
*************** finish_function (nested)
*** 6674,6680 ****
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;
}
}
--- 6670,6675 ----
*************** push_c_function_context (f)
*** 6916,6922 ****
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;
--- 6911,6916 ----
*************** pop_c_function_context (f)
*** 6954,6960 ****
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;
--- 6948,6953 ----
*************** c_begin_compound_stmt ()
*** 7087,7099 ****
/* 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;
}
--- 7080,7085 ----
Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-parse.in,v
retrieving revision 1.84
diff -c -3 -p -r1.84 c-parse.in
*** c-parse.in 2001/03/07 01:31:59 1.84
--- c-parse.in 2001/04/20 14:22:27
*************** end ifc
*** 124,129 ****
--- 124,132 ----
%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
*************** program: /* empty */
*** 298,304 ****
get us back to the global binding level. */
while (! global_bindings_p ())
poplevel (0, 0, 0);
! finish_file ();
}
;
--- 301,310 ----
get us back to the global binding level. */
while (! global_bindings_p ())
poplevel (0, 0, 0);
! ifc
! finish_fname_decls ();
! end ifc
! finish_file ();
}
;
*************** primary:
*** 631,636 ****
--- 637,644 ----
| CONSTANT
| string
{ $$ = combine_strings ($1); }
+ | VAR_FUNC_NAME
+ { $$ = fname_decl (C_RID_CODE ($$), $$); }
| '(' typename ')' '{'
{ start_init (NULL_TREE, NULL, 0);
$2 = groktypename ($2);
*************** static const struct resword reswords[] =
*** 2884,2889 ****
--- 2892,2899 ----
{
{ "_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 },
*************** static const struct resword reswords[] =
*** 2898,2903 ****
--- 2908,2914 ----
{ "__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 },
*************** static const short rid_to_yy[RID_MAX] =
*** 3057,3062 ****
--- 3068,3077 ----
/* 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,
*************** static const short rid_to_yy[RID_MAX] =
*** 3098,3104 ****
/* RID_BITAND */ 0,
/* RID_BITOR */ 0,
/* RID_COMPL */ 0,
!
/* Objective C */
/* RID_ID */ OBJECTNAME,
/* RID_AT_ENCODE */ ENCODE,
--- 3113,3119 ----
/* RID_BITAND */ 0,
/* RID_BITOR */ 0,
/* RID_COMPL */ 0,
!
/* Objective C */
/* RID_ID */ OBJECTNAME,
/* RID_AT_ENCODE */ ENCODE,
*************** yylexname ()
*** 3226,3231 ****
--- 3241,3259 ----
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];
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-semantics.c,v
retrieving revision 1.23
diff -c -3 -p -r1.23 c-semantics.c
*** c-semantics.c 2001/04/11 15:51:51 1.23
--- c-semantics.c 2001/04/20 14:22:28
*************** void (*lang_expand_stmt) PARAMS ((tree))
*** 48,55 ****
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
--- 48,53 ----
*************** add_scope_stmt (begin_p, partial_p)
*** 141,201 ****
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
--- 139,144 ----
*************** finish_stmt_tree (t)
*** 209,217 ****
*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
--- 152,157 ----
*************** genrtl_decl_stmt (t)
*** 420,434 ****
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);
! }
else if (TREE_CODE (decl) == LABEL_DECL
&& C_DECLARED_LABEL_FLAG (decl))
declare_nonlocal_label (decl);
--- 360,366 ----
DECL_ANON_UNION_ELEMS (decl));
}
else if (TREE_CODE (decl) == VAR_DECL && TREE_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: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.55
diff -c -3 -p -r1.55 cp-tree.def
*** cp-tree.def 2001/03/28 11:01:33 1.55
--- cp-tree.def 2001/04/20 14:22:33
*************** DEFTREECODE (WRAPPER, "wrapper", 'x', 1)
*** 200,208 ****
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)
--- 200,205 ----
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.601
diff -c -3 -p -r1.601 cp-tree.h
*** cp-tree.h 2001/04/19 22:49:47 1.601
--- cp-tree.h 2001/04/20 14:22:34
*************** struct cp_language_function
*** 968,979 ****
#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;
--- 968,973 ----
*************** extern int nonstatic_local_decl_p
*** 3911,3916 ****
--- 3905,3911 ----
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: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.773
diff -c -3 -p -r1.773 decl.c
*** decl.c 2001/04/19 22:49:47 1.773
--- decl.c 2001/04/20 14:22:39
*************** static tree get_atexit_node PARAMS ((voi
*** 138,144 ****
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 void initialize_predefined_identifiers PARAMS ((void));
static tree check_special_function_return_type
PARAMS ((special_function_kind, tree, tree));
--- 138,144 ----
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, int));
static void initialize_predefined_identifiers PARAMS ((void));
static tree check_special_function_return_type
PARAMS ((special_function_kind, tree, tree));
*************** init_decl_processing ()
*** 6519,6524 ****
--- 6519,6525 ----
{
tree bad_alloc_type_node, newtype, deltype;
+
if (flag_honor_std)
push_namespace (std_identifier);
bad_alloc_type_node = xref_tag
*************** init_decl_processing ()
*** 6526,6532 ****
if (flag_honor_std)
pop_namespace ();
newtype = build_exception_variant
! (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);
--- 6527,6534 ----
if (flag_honor_std)
pop_namespace ();
newtype = build_exception_variant
! (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);
*************** init_decl_processing ()
*** 6553,6565 ****
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 ();
/* Prepare to check format strings against argument lists. */
init_function_format_info ();
--- 6555,6562 ----
if (! supports_one_only ())
flag_weak = 0;
make_fname_decl = cp_make_fname_decl;
! start_fname_decls ();
/* Prepare to check format strings against argument lists. */
init_function_format_info ();
*************** init_decl_processing ()
*** 6607,6663 ****
ggc_add_tree_root (&free_bindings, 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 (size_int (length));
!
! type = build_cplus_array_type
! (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
! domain);
!
! decl = build_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;
- 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);
! /* We will have to make sure we only emit this, if it is actually used. */
return decl;
}
--- 6604,6667 ----
ggc_add_tree_root (&free_bindings, 1);
}
+ 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. 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, type_dep)
tree id;
int type_dep;
{
! 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));
! /* 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_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = init;
!
! TREE_USED (decl) = 1;
! cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
!
return decl;
}
*************** start_function (declspecs, declarator, a
*** 13614,13619 ****
--- 13618,13625 ----
DECL_CONTEXT (dtor_label) = current_function_decl;
}
+ start_fname_decls ();
+
store_parm_decls (current_function_parms);
return 1;
*************** finish_function (flags)
*** 13943,13948 ****
--- 13949,13956 ----
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: cp/lex.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/lex.c,v
retrieving revision 1.242
diff -c -3 -p -r1.242 lex.c
*** lex.c 2001/04/19 22:49:48 1.242
--- lex.c 2001/04/20 14:22:39
*************** CONSTRAINT(ridbits_fit, RID_LAST_MODIFIE
*** 402,407 ****
--- 402,409 ----
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 },
*************** static const struct resword reswords[] =
*** 414,419 ****
--- 416,422 ----
{ "__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 },
*************** const short rid_to_yy[RID_MAX] =
*** 584,589 ****
--- 587,596 ----
/* RID_PTRBASE */ 0,
/* 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,
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.64
diff -c -3 -p -r1.64 optimize.c
*** optimize.c 2001/04/11 19:45:49 1.64
--- optimize.c 2001/04/20 14:22:39
*************** maybe_clone_body (fn)
*** 1123,1129 ****
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);
--- 1123,1128 ----
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.216
diff -c -3 -p -r1.216 parse.y
*** parse.y 2001/03/26 08:37:25 1.216
--- parse.y 2001/04/20 14:22:40
*************** cp_parse_init ()
*** 259,264 ****
--- 259,268 ----
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
*************** primary:
*** 1555,1560 ****
--- 1559,1570 ----
TREE_TYPE ($$) = build_cplus_array_type
(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); }
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.529
diff -c -3 -p -r1.529 pt.c
*** pt.c 2001/04/12 14:15:48 1.529
--- pt.c 2001/04/20 14:22:43
*************** tsubst_decl (t, args, type)
*** 5987,5996 ****
/* 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);
TREE_TYPE (r) = TREE_TYPE (DECL_INITIAL (r));
}
--- 5987,5995 ----
/* For __PRETTY_FUNCTION__ we have to adjust the initializer. */
if (DECL_PRETTY_FUNCTION_P (r))
{
! 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));
}
*************** tsubst (t, args, complain, in_decl)
*** 6794,6817 ****
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)]);
--- 6793,6798 ----
*************** tsubst_copy (t, args, complain, in_decl)
*** 7172,7180 ****
in_decl),
tsubst (TREE_TYPE (t), args, complain, in_decl));
- case FUNCTION_NAME:
- return tsubst (t, args, complain, in_decl);
-
default:
return t;
}
--- 7153,7158 ----
*************** tsubst_expr (t, args, complain, in_decl)
*** 7254,7260 ****
{
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
! init = tsubst_expr (init, args, complain, in_decl);
if (decl != error_mark_node)
{
if (TREE_CODE (decl) != TYPE_DECL)
--- 7232,7241 ----
{
init = DECL_INITIAL (decl);
decl = tsubst (decl, 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)
*************** instantiate_decl (d, defer_ok)
*** 9933,9942 ****
/* 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,
--- 9914,9919 ----
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.204
diff -c -3 -p -r1.204 semantics.c
*** semantics.c 2001/04/19 22:49:48 1.204
--- semantics.c 2001/04/20 14:22:44
*************** begin_compound_stmt (has_no_scope)
*** 852,867 ****
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;
}
--- 852,857 ----
*************** setup_vtbl_ptr (member_init_list, base_i
*** 1180,1186 ****
{
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
--- 1170,1175 ----
*************** setup_vtbl_ptr (member_init_list, base_i
*** 1201,1212 ****
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
--- 1190,1196 ----
*************** finish_translation_unit ()
*** 1706,1711 ****
--- 1690,1699 ----
pop_everything ();
while (current_namespace != global_namespace)
pop_namespace ();
+
+ /* Do file scope __FUNCTION__ et al. */
+ finish_fname_decls ();
+
finish_file ();
}
*************** expand_body (fn)
*** 2471,2481 ****
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));
--- 2459,2464 ----
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/typeck2.c,v
retrieving revision 1.99
diff -c -3 -p -r1.99 typeck2.c
*** typeck2.c 2001/02/16 01:24:14 1.99
--- typeck2.c 2001/04/20 14:22:44
*************** digest_init (type, init, tail)
*** 470,475 ****
--- 470,480 ----
&& 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: objc/Make-lang.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/objc/Make-lang.in,v
retrieving revision 1.34
diff -c -3 -p -r1.34 Make-lang.in
*** Make-lang.in 2001/03/27 22:57:35 1.34
--- Make-lang.in 2001/04/20 14:22:45
*************** $(srcdir)/objc/objc-parse.c : $(srcdir)/
*** 71,78 ****
$(srcdir)/objc/objc-parse.y: $(srcdir)/c-parse.in
echo '/*WARNING: This file is automatically generated!*/' >tmp-objc-prs.y
! sed -e "/^ifc$$/,/^end ifc$$/d" \
! -e "/^ifobjc$$/d" -e "/^end ifobjc$$/d" \
$(srcdir)/c-parse.in >>tmp-objc-prs.y
$(SHELL) $(srcdir)/move-if-change tmp-objc-prs.y $(srcdir)/objc/objc-parse.y
--- 71,78 ----
$(srcdir)/objc/objc-parse.y: $(srcdir)/c-parse.in
echo '/*WARNING: This file is automatically generated!*/' >tmp-objc-prs.y
! sed -e "/^ifc *$$/,/^end +ifc *$$/d" \
! -e "/^ifobjc *$$/d" -e "/^end +ifobjc *$$/d" \
$(srcdir)/c-parse.in >>tmp-objc-prs.y
$(SHELL) $(srcdir)/move-if-change tmp-objc-prs.y $(srcdir)/objc/objc-parse.y
Index: testsuite/gcc.dg/c99-func-2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.dg/c99-func-2.c,v
retrieving revision 1.1
diff -c -3 -p -r1.1 c99-func-2.c
*** c99-func-2.c 2000/08/10 08:19:44 1.1
--- c99-func-2.c 2001/04/20 14:22:48
***************
*** 6,11 ****
void
foo (void)
{
! __func__ "foo"; /* { dg-bogus "warning" "warning in place of error" } */
! /* { dg-error "parse error" "__func__ not string constant" { xfail *-*-* } 9 } */
}
--- 6,10 ----
void
foo (void)
{
! __func__ "foo"; /* { dg-error "parse error" "before string constant" } */
}
Index: testsuite/gcc.dg/c99-func-3.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.dg/c99-func-3.c,v
retrieving revision 1.1
diff -c -3 -p -r1.1 c99-func-3.c
*** c99-func-3.c 2000/08/15 18:08:04 1.1
--- c99-func-3.c 2001/04/20 14:22:48
***************
*** 1,6 ****
/* Test for C99 __func__: not merging with string literals. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
! /* { dg-do run { xfail *-*-* } } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
extern void abort (void);
--- 1,6 ----
/* Test for C99 __func__: not merging with string literals. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
! /* { dg-do run } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
extern void abort (void);
Index: testsuite/gcc.dg/c99-func-4.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/gcc.dg/c99-func-4.c,v
retrieving revision 1.1
diff -c -3 -p -r1.1 c99-func-4.c
*** c99-func-4.c 2000/08/15 18:08:04 1.1
--- c99-func-4.c 2001/04/20 14:22:48
***************
*** 6,10 ****
void
foo (void)
{
! char *p = __func__; /* { dg-error "discards" "__func__ pointer to const" { xfail *-*-* } } */
}
--- 6,10 ----
void
foo (void)
{
! char *p = __func__; /* { dg-error "discards" "__func__ pointer to const" } */
}