cp-tree.def (FUNCTION_NAME): New tree node.

* cp-tree.def (FUNCTION_NAME): New tree node.
	* cp-tree.h (current_function_name_declared): Tweak documentation.
	(lang_decl_flags): Add pretty_function_p, adjust dummy.
	(DECL_PRETTY_FUNCTION_P): New macro.
	* decl.c (cp_finish_decl): Handle declarations of __FUNCTION__,
	etc., in a template function.  Use at_function_scope_p instead of
	expanding it inline.
	* pt.c (tsubst_decl): Handle DECL_PRETTY_FUNCTION_P declarations
	specially.
	(tsubst): Handle FUNCTION_NAME.
	(tsubst_copy): Likewise.
	(instantiate_decl): Prevent redeclarations of __PRETTY_FUNCTION__,
	etc. in instantiation.
	* semantics.c (begin_compound_stmt): Declare __FUNCTION__, etc.,
	even in template functions.
	(setup_vtbl_ptr): Don't declare __PRETTY_FUNCTION in the
	conditional scope at the top of a destructor.

	* error.c (dump_function_decl): Use `[ with ... ]' syntax for
	specializations too.

From-SVN: r30625
This commit is contained in:
Mark Mitchell 1999-11-23 02:49:41 +00:00 committed by Mark Mitchell
parent a96c67ec89
commit f981720185
10 changed files with 111 additions and 17 deletions

View File

@ -1,3 +1,26 @@
1999-11-22 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (FUNCTION_NAME): New tree node.
* cp-tree.h (current_function_name_declared): Tweak documentation.
(lang_decl_flags): Add pretty_function_p, adjust dummy.
(DECL_PRETTY_FUNCTION_P): New macro.
* decl.c (cp_finish_decl): Handle declarations of __FUNCTION__,
etc., in a template function. Use at_function_scope_p instead of
expanding it inline.
* pt.c (tsubst_decl): Handle DECL_PRETTY_FUNCTION_P declarations
specially.
(tsubst): Handle FUNCTION_NAME.
(tsubst_copy): Likewise.
(instantiate_decl): Prevent redeclarations of __PRETTY_FUNCTION__,
etc. in instantiation.
* semantics.c (begin_compound_stmt): Declare __FUNCTION__, etc.,
even in template functions.
(setup_vtbl_ptr): Don't declare __PRETTY_FUNCTION in the
conditional scope at the top of a destructor.
* error.c (dump_function_decl): Use `[ with ... ]' syntax for
specializations too.
1999-11-22 Nathan Sidwell <nathan@acm.org>
* semantics.c (finish_unary_op_expr): Only set TREE_NEGATED_INT

View File

@ -200,6 +200,9 @@ DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
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)

View File

@ -789,8 +789,9 @@ struct language_function
#define current_function_parms_stored \
cp_function_chain->parms_stored
/* Non-zero if we have already declared __FUNCTION__ (and related
variables) in the current function. */
/* One if we have already declared __FUNCTION__ (and related
variables) in the current function. Two if we are in the process
of doing so. */
#define current_function_name_declared \
cp_function_chain->name_declared
@ -1607,7 +1608,8 @@ struct lang_decl_flags
unsigned pending_inline_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
unsigned dummy : 3;
unsigned pretty_function_p : 1;
unsigned dummy : 2;
tree context;
@ -1766,6 +1768,11 @@ struct lang_decl
must be overridden by derived classes. */
#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.needs_final_overrider)
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */
#define DECL_PRETTY_FUNCTION_P(NODE) \
(DECL_LANG_SPECIFIC(NODE)->decl_flags.pretty_function_p)
/* The _TYPE context in which this _DECL appears. This field holds the
class where a virtual function instance is actually defined, and the
lexical scope of a friend function defined in a class body. */

View File

@ -7606,6 +7606,26 @@ 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 (current_function && 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);
@ -7639,8 +7659,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
return;
/* Add this declaration to the statement-tree. */
if (building_stmt_tree ()
&& TREE_CODE (current_scope ()) == FUNCTION_DECL)
if (building_stmt_tree () && at_function_scope_p ())
add_decl_stmt (decl);
if (TYPE_HAS_MUTABLE_P (type))

View File

@ -1112,7 +1112,7 @@ dump_function_decl (t, flags)
t = DECL_TEMPLATE_RESULT (t);
/* Pretty print template instantiations only. */
if (DECL_TEMPLATE_INSTANTIATION (t))
if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
{
template_args = DECL_TI_ARGS (t);
t = most_general_template (t);

View File

@ -5890,7 +5890,7 @@ tsubst_decl (t, args, type, in_decl)
/* This declaration is going to have to be around for a while,
so me make sure it is on a saveable obstack. */
r = copy_node (t);
TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r);
DECL_CONTEXT (r) = ctx;
@ -5903,6 +5903,16 @@ tsubst_decl (t, args, type, in_decl)
copy_lang_decl (r);
DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
/* 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));
}
/* Even if the original location is out of scope, the newly
substituted one is not. */
if (TREE_CODE (r) == VAR_DECL)
@ -6676,6 +6686,24 @@ 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 (build_int_2 (len, 0)));
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)]);
@ -7035,7 +7063,10 @@ tsubst_copy (t, args, complain, in_decl)
return build_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
in_decl),
tsubst (TREE_TYPE (t), args, complain, in_decl));
case FUNCTION_NAME:
return tsubst (t, args, complain, in_decl);
default:
return t;
}
@ -9532,6 +9563,10 @@ instantiate_decl (d)
start_function (NULL_TREE, d, NULL_TREE, SF_PRE_PARSED);
store_parm_decls ();
/* We already set up __FUNCTION__, etc., so we don't want to do
it again now. */
current_function_name_declared = 1;
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
/*complain=*/1, tmpl);

View File

@ -936,10 +936,14 @@ begin_compound_stmt (has_no_scope)
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
if (current_function
&& !current_function_name_declared
&& !processing_template_decl
&& !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;
}
@ -1187,6 +1191,7 @@ setup_vtbl_ptr ()
tree binfo = TYPE_BINFO (current_class_type);
tree if_stmt;
tree compound_stmt;
int saved_cfnd;
/* If the dtor is empty, and we know there is not possible way we
could use any vtable entries, before they are possibly set by
@ -1202,11 +1207,17 @@ setup_vtbl_ptr ()
/* If it is not safe to avoid setting up the vtables, then
someone will change the condition to be boolean_true_node.
(Actually, for now, we do not have code to set the condition
appropriate, so we just assume that we always need to
appropriately, so we just assume that we always need to
initialize the vtables.) */
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 = current_function_name_declared;
current_function_name_declared = 1;
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
current_function_name_declared = saved_cfnd;
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function

View File

@ -3,8 +3,6 @@
// make sure __FUNCTION__ and __PRETTY_FUNCTION__ work in member functions
// execution test - XFAIL *-*-*
#include <stdio.h>
#include <string.h>

View File

@ -3,8 +3,6 @@
// make sure __FUNCTION__ and __PRETTY_FUNCTION__ work in templates
// execution test - XFAIL *-*-*
#include <stdio.h>
#include <string.h>
@ -21,7 +19,7 @@ template<class T> void f1 (T)
if (strcmp (function, "f1"))
bad = true;
if (strcmp (pretty, "void f1<float> (float)")) // only for float instantiation
if (strcmp (pretty, "void f1 (T) [with T = float]")) // only for float instantiation
bad = true;
}
@ -36,7 +34,7 @@ template<> void f1<int> (int)
if (strcmp (function, "f1"))
bad = true;
if (strcmp (pretty, "void f1<int> (int)"))
if (strcmp (pretty, "void f1 (T) [with T = int]"))
bad = true;
}

View File

@ -18,7 +18,7 @@ char* S3<char>::h(int) { return __PRETTY_FUNCTION__; }
int main()
{
if (strcmp (S3<double>::h(7),
"char *S3<double>::h<int> (int)") == 0)
"char *S3<T>::h (U) [with U = int, T = double]") == 0)
return 0;
else
return 1;