C++ BUG: __PRETTY_FUNCTION__ broken
Mark Mitchell
mark@codesourcery.com
Tue Nov 30 23:39:00 GMT 1999
Here's a fix for these bugs.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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.
Index: testsuite/g++.old-deja/g++.ext/pretty2.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.ext/pretty2.C,v
retrieving revision 1.1
diff -c -p -r1.1 pretty2.C
*** pretty2.C 1999/11/22 15:51:14 1.1
--- pretty2.C 1999/11/23 02:40:22
***************
*** 3,10 ****
// make sure __FUNCTION__ and __PRETTY_FUNCTION__ work in member functions
- // execution test - XFAIL *-*-*
-
#include <stdio.h>
#include <string.h>
--- 3,8 ----
Index: testsuite/g++.old-deja/g++.ext/pretty3.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.ext/pretty3.C,v
retrieving revision 1.1
diff -c -p -r1.1 pretty3.C
*** pretty3.C 1999/11/22 15:51:14 1.1
--- pretty3.C 1999/11/23 02:40:22
***************
*** 3,10 ****
// make sure __FUNCTION__ and __PRETTY_FUNCTION__ work in templates
- // execution test - XFAIL *-*-*
-
#include <stdio.h>
#include <string.h>
--- 3,8 ----
*************** template<class T> void f1 (T)
*** 21,27 ****
if (strcmp (function, "f1"))
bad = true;
! if (strcmp (pretty, "void f1<float> (float)")) // only for float instantiation
bad = true;
}
--- 19,25 ----
if (strcmp (function, "f1"))
bad = true;
! if (strcmp (pretty, "void f1 (T) [with T = float]")) // only for float instantiation
bad = true;
}
*************** template<> void f1<int> (int)
*** 36,42 ****
if (strcmp (function, "f1"))
bad = true;
! if (strcmp (pretty, "void f1<int> (int)"))
bad = true;
}
--- 34,40 ----
if (strcmp (function, "f1"))
bad = true;
! if (strcmp (pretty, "void f1 (T) [with T = int]"))
bad = true;
}
Index: testsuite/g++.old-deja/g++.pt/memtemp77.C
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C,v
retrieving revision 1.4
diff -c -p -r1.4 memtemp77.C
*** memtemp77.C 1999/09/27 08:28:19 1.4
--- memtemp77.C 1999/11/23 02:40:24
*************** char* S3<char>::h(int) { return __PRETTY
*** 18,24 ****
int main()
{
if (strcmp (S3<double>::h(7),
! "char *S3<double>::h<int> (int)") == 0)
return 0;
else
return 1;
--- 18,24 ----
int main()
{
if (strcmp (S3<double>::h(7),
! "char *S3<T>::h (U) [with U = int, T = double]") == 0)
return 0;
else
return 1;
Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.39
diff -c -p -r1.39 cp-tree.def
*** cp-tree.def 1999/10/21 07:10:36 1.39
--- cp-tree.def 1999/11/23 02:40:36
*************** DEFTREECODE (SRCLOC, "srcloc", 'x', 2)
*** 200,205 ****
--- 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)
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.352
diff -c -p -r1.352 cp-tree.h
*** cp-tree.h 1999/11/21 17:44:34 1.352
--- cp-tree.h 1999/11/23 02:40:39
*************** struct language_function
*** 789,796 ****
#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. */
#define current_function_name_declared \
cp_function_chain->name_declared
--- 789,797 ----
#define current_function_parms_stored \
cp_function_chain->parms_stored
! /* 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
*************** struct lang_decl_flags
*** 1607,1613 ****
unsigned pending_inline_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
! unsigned dummy : 3;
tree context;
--- 1608,1615 ----
unsigned pending_inline_p : 1;
unsigned global_ctor_p : 1;
unsigned global_dtor_p : 1;
! unsigned pretty_function_p : 1;
! unsigned dummy : 2;
tree context;
*************** struct lang_decl
*** 1765,1770 ****
--- 1767,1777 ----
/* Nonzero for FUNCTION_DECL means that this member function
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
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.506
diff -c -p -r1.506 decl.c
*** decl.c 1999/11/19 13:03:00 1.506
--- decl.c 1999/11/23 02:40:48
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7606,7611 ****
--- 7606,7631 ----
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);
*************** cp_finish_decl (decl, init, asmspec_tree
*** 7639,7646 ****
return;
/* Add this declaration to the statement-tree. */
! if (building_stmt_tree ()
! && TREE_CODE (current_scope ()) == FUNCTION_DECL)
add_decl_stmt (decl);
if (TYPE_HAS_MUTABLE_P (type))
--- 7659,7665 ----
return;
/* Add this declaration to the statement-tree. */
! if (building_stmt_tree () && at_function_scope_p ())
add_decl_stmt (decl);
if (TYPE_HAS_MUTABLE_P (type))
Index: cp/error.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/error.c,v
retrieving revision 1.95
diff -c -p -r1.95 error.c
*** error.c 1999/11/10 22:31:29 1.95
--- error.c 1999/11/23 02:40:50
*************** dump_function_decl (t, flags)
*** 1112,1118 ****
t = DECL_TEMPLATE_RESULT (t);
/* Pretty print template instantiations only. */
! if (DECL_TEMPLATE_INSTANTIATION (t))
{
template_args = DECL_TI_ARGS (t);
t = most_general_template (t);
--- 1112,1118 ----
t = DECL_TEMPLATE_RESULT (t);
/* Pretty print template instantiations only. */
! if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
{
template_args = DECL_TI_ARGS (t);
t = most_general_template (t);
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.383
diff -c -p -r1.383 pt.c
*** pt.c 1999/11/16 05:58:53 1.383
--- pt.c 1999/11/23 02:40:55
*************** tsubst_decl (t, args, type, in_decl)
*** 5890,5896 ****
/* 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;
--- 5890,5896 ----
/* 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;
*************** tsubst_decl (t, args, type, in_decl)
*** 5903,5908 ****
--- 5903,5918 ----
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)
*************** tsubst (t, args, complain, in_decl)
*** 6676,6681 ****
--- 6686,6709 ----
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)]);
*************** tsubst_copy (t, args, complain, in_decl)
*** 7035,7041 ****
return build_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
in_decl),
tsubst (TREE_TYPE (t), args, complain, in_decl));
!
default:
return t;
}
--- 7063,7072 ----
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;
}
*************** instantiate_decl (d)
*** 9531,9536 ****
--- 9562,9571 ----
/* Set up context. */
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,
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.107
diff -c -p -r1.107 semantics.c
*** semantics.c 1999/11/22 16:08:14 1.107
--- semantics.c 1999/11/23 02:40:55
*************** begin_compound_stmt (has_no_scope)
*** 936,945 ****
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
if (current_function
&& !current_function_name_declared
- && !processing_template_decl
&& !has_no_scope)
{
declare_function_name ();
current_function_name_declared = 1;
}
--- 936,949 ----
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
if (current_function
&& !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;
}
*************** setup_vtbl_ptr ()
*** 1187,1192 ****
--- 1191,1197 ----
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
*************** setup_vtbl_ptr ()
*** 1202,1212 ****
/* 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
initialize the vtables.) */
finish_if_stmt_cond (boolean_true_node, if_stmt);
current_vcalls_possible_p = &IF_COND (if_stmt);
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
--- 1207,1223 ----
/* 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
! 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
More information about the Gcc-bugs
mailing list