From f981720185940a12e9d4bd8f1000602a2ca07d05 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 23 Nov 1999 02:49:41 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 23 +++++++++++ gcc/cp/cp-tree.def | 3 ++ gcc/cp/cp-tree.h | 13 +++++-- gcc/cp/decl.c | 23 ++++++++++- gcc/cp/error.c | 2 +- gcc/cp/pt.c | 39 ++++++++++++++++++- gcc/cp/semantics.c | 15 ++++++- gcc/testsuite/g++.old-deja/g++.ext/pretty2.C | 2 - gcc/testsuite/g++.old-deja/g++.ext/pretty3.C | 6 +-- gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C | 2 +- 10 files changed, 111 insertions(+), 17 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c2f9d741492..d214aaa0e86 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,26 @@ +1999-11-22 Mark Mitchell + + * 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 * semantics.c (finish_unary_op_expr): Only set TREE_NEGATED_INT diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index d8eb62f65a5..de874cbd87a 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 61a76868473..44d16c6b1a1 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 91b8552d54b..adb3684f4ae 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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)) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 9151b8c604e..2b7b4eae3dc 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7e3a8abd088..18307b3e9aa 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 741f710800a..37510e5e7fa 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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 diff --git a/gcc/testsuite/g++.old-deja/g++.ext/pretty2.C b/gcc/testsuite/g++.old-deja/g++.ext/pretty2.C index 14eb5276ef5..8f69bf4b50f 100644 --- a/gcc/testsuite/g++.old-deja/g++.ext/pretty2.C +++ b/gcc/testsuite/g++.old-deja/g++.ext/pretty2.C @@ -3,8 +3,6 @@ // make sure __FUNCTION__ and __PRETTY_FUNCTION__ work in member functions -// execution test - XFAIL *-*-* - #include #include diff --git a/gcc/testsuite/g++.old-deja/g++.ext/pretty3.C b/gcc/testsuite/g++.old-deja/g++.ext/pretty3.C index 148b3badd6f..820f08e6f5e 100644 --- a/gcc/testsuite/g++.old-deja/g++.ext/pretty3.C +++ b/gcc/testsuite/g++.old-deja/g++.ext/pretty3.C @@ -3,8 +3,6 @@ // make sure __FUNCTION__ and __PRETTY_FUNCTION__ work in templates -// execution test - XFAIL *-*-* - #include #include @@ -21,7 +19,7 @@ template void f1 (T) if (strcmp (function, "f1")) bad = true; - if (strcmp (pretty, "void f1 (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) if (strcmp (function, "f1")) bad = true; - if (strcmp (pretty, "void f1 (int)")) + if (strcmp (pretty, "void f1 (T) [with T = int]")) bad = true; } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C index 54c49952dd7..827e2df71c8 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C @@ -18,7 +18,7 @@ char* S3::h(int) { return __PRETTY_FUNCTION__; } int main() { if (strcmp (S3::h(7), - "char *S3::h (int)") == 0) + "char *S3::h (U) [with U = int, T = double]") == 0) return 0; else return 1;