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