This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH]: Fix 11788


Hi,
I've installed this obvious patch for 11788 where we failed to instantiate
a template. We were also losing side effects!

booted & tested on i686-pc-linux-gnu

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
         The voices in my head said this was stupid too
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2003-09-10  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/11788
	* typeck.c (build_address): If it is a function, mark it used.
	(build_unary_op): Do not lose object's side-effects when taking
	address of static member function.
	* class.c (resolve_address_of_overloaded_function): Use
	tsubst_flags_t parameter. Only expect overload sets. Adjust.
	(instantiate_type): Adjust flags passing. Do not lose object's
	side-effects when taking address of static member function.

Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.501
diff -c -3 -p -r1.501 typeck.c
*** cp/typeck.c	7 Sep 2003 04:10:08 -0000	1.501
--- cp/typeck.c	11 Sep 2003 14:40:25 -0000
*************** build_address (tree t)
*** 3581,3589 ****
    if (error_operand_p (t) || !cxx_mark_addressable (t))
      return error_mark_node;
  
!   addr = build1 (ADDR_EXPR, 
! 		 build_pointer_type (TREE_TYPE (t)),
! 		 t);
    if (staticp (t))
      TREE_CONSTANT (addr) = 1;
  
--- 3581,3587 ----
    if (error_operand_p (t) || !cxx_mark_addressable (t))
      return error_mark_node;
  
!   addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
    if (staticp (t))
      TREE_CONSTANT (addr) = 1;
  
*************** build_unary_op (enum tree_code code, tre
*** 4003,4014 ****
        {
  	tree addr;
  
- 	if (TREE_CODE (arg) == COMPONENT_REF
- 	    && TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
- 	  arg = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
- 
  	if (TREE_CODE (arg) != COMPONENT_REF)
  	  addr = build_address (arg);
  	else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
  	  {
  	    error ("attempt to take address of bit-field structure member `%D'",
--- 4001,4024 ----
        {
  	tree addr;
  
  	if (TREE_CODE (arg) != COMPONENT_REF)
  	  addr = build_address (arg);
+ 	else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+ 	  {
+ 	    tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
+ 
+ 	    /* We can only get here with a single static member
+ 	       function.  */
+ 	    my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL
+ 				&& DECL_STATIC_FUNCTION_P (fn),
+ 				20030906);
+ 	    mark_used (fn);
+ 	    addr = build_address (fn);
+ 	    if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
+ 	      /* Do not lose object's side effects.  */
+ 	      addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
+ 			    TREE_OPERAND (arg, 0), addr);
+ 	  }
  	else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
  	  {
  	    error ("attempt to take address of bit-field structure member `%D'",
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.568
diff -c -3 -p -r1.568 class.c
*** cp/class.c	6 Sep 2003 18:37:56 -0000	1.568
--- cp/class.c	11 Sep 2003 14:40:42 -0000
*************** static int method_name_cmp (const void *
*** 129,136 ****
  static int resort_method_name_cmp (const void *, const void *);
  static void add_implicitly_declared_members (tree, int, int, int);
  static tree fixed_type_or_null (tree, int *, int *);
! static tree resolve_address_of_overloaded_function (tree, tree, int,
! 							  int, int, tree);
  static tree build_vtbl_ref_1 (tree, tree);
  static tree build_vtbl_initializer (tree, tree, tree, tree, int *);
  static int count_fields (tree);
--- 129,136 ----
  static int resort_method_name_cmp (const void *, const void *);
  static void add_implicitly_declared_members (tree, int, int, int);
  static tree fixed_type_or_null (tree, int *, int *);
! static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t,
! 						    bool, tree);
  static tree build_vtbl_ref_1 (tree, tree);
  static tree build_vtbl_initializer (tree, tree, tree, tree, int *);
  static int count_fields (tree);
*************** pop_lang_context (void)
*** 5675,5692 ****
  
  /* Given an OVERLOAD and a TARGET_TYPE, return the function that
     matches the TARGET_TYPE.  If there is no satisfactory match, return
!    error_mark_node, and issue an error message if COMPLAIN is
!    nonzero.  Permit pointers to member function if PTRMEM is nonzero.
!    If TEMPLATE_ONLY, the name of the overloaded function
!    was a template-id, and EXPLICIT_TARGS are the explicitly provided
     template arguments.  */
  
  static tree
  resolve_address_of_overloaded_function (tree target_type, 
  					tree overload,
! 					int complain,
! 	                                int ptrmem,
! 					int template_only,
  					tree explicit_targs)
  {
    /* Here's what the standard says:
--- 5675,5691 ----
  
  /* Given an OVERLOAD and a TARGET_TYPE, return the function that
     matches the TARGET_TYPE.  If there is no satisfactory match, return
!    error_mark_node, and issue a error & warning messages under control
!    of FLAGS.  Permit pointers to member function if FLAGS permits.  If
!    TEMPLATE_ONLY, the name of the overloaded function was a
!    template-id, and EXPLICIT_TARGS are the explicitly provided
     template arguments.  */
  
  static tree
  resolve_address_of_overloaded_function (tree target_type, 
  					tree overload,
! 					tsubst_flags_t flags,
! 					bool template_only,
  					tree explicit_targs)
  {
    /* Here's what the standard says:
*************** resolve_address_of_overloaded_function (
*** 5730,5738 ****
  			&& (TREE_CODE (TREE_TYPE (target_type)) 
  			    == METHOD_TYPE)), 0);
  
!   if (TREE_CODE (overload) == COMPONENT_REF)
!     overload = TREE_OPERAND (overload, 1);
! 
    /* Check that the TARGET_TYPE is reasonable.  */
    if (TYPE_PTRFN_P (target_type))
      /* This is OK.  */;
--- 5729,5736 ----
  			&& (TREE_CODE (TREE_TYPE (target_type)) 
  			    == METHOD_TYPE)), 0);
  
!   my_friendly_assert (is_overloaded_fn (overload), 20030910);
!   
    /* Check that the TARGET_TYPE is reasonable.  */
    if (TYPE_PTRFN_P (target_type))
      /* This is OK.  */;
*************** resolve_address_of_overloaded_function (
*** 5748,5754 ****
      }
    else 
      {
!       if (complain)
  	error ("\
  cannot resolve overloaded function `%D' based on conversion to type `%T'", 
  		  DECL_NAME (OVL_FUNCTION (overload)), target_type);
--- 5746,5752 ----
      }
    else 
      {
!       if (flags & tf_error)
  	error ("\
  cannot resolve overloaded function `%D' based on conversion to type `%T'", 
  		  DECL_NAME (OVL_FUNCTION (overload)), target_type);
*************** cannot resolve overloaded function `%D' 
*** 5842,5849 ****
  	    continue;
  
  	  /* Instantiate the template.  */
! 	  instantiation = instantiate_template (fn, targs,
! 						complain ? tf_error : tf_none);
  	  if (instantiation == error_mark_node)
  	    /* Instantiation failed.  */
  	    continue;
--- 5840,5846 ----
  	    continue;
  
  	  /* Instantiate the template.  */
! 	  instantiation = instantiate_template (fn, targs, flags);
  	  if (instantiation == error_mark_node)
  	    /* Instantiation failed.  */
  	    continue;
*************** cannot resolve overloaded function `%D' 
*** 5873,5879 ****
    if (matches == NULL_TREE)
      {
        /* There were *no* matches.  */
!       if (complain)
  	{
   	  error ("no matches converting function `%D' to type `%#T'", 
  		    DECL_NAME (OVL_FUNCTION (overload)),
--- 5870,5876 ----
    if (matches == NULL_TREE)
      {
        /* There were *no* matches.  */
!       if (flags & tf_error)
  	{
   	  error ("no matches converting function `%D' to type `%#T'", 
  		    DECL_NAME (OVL_FUNCTION (overload)),
*************** cannot resolve overloaded function `%D' 
*** 5894,5900 ****
      {
        /* There were too many matches.  */
  
!       if (complain)
  	{
  	  tree match;
  
--- 5891,5897 ----
      {
        /* There were too many matches.  */
  
!       if (flags & tf_error)
  	{
  	  tree match;
  
*************** cannot resolve overloaded function `%D' 
*** 5917,5927 ****
    fn = TREE_PURPOSE (matches);
  
    if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
!       && !ptrmem && !flag_ms_extensions)
      {
        static int explained;
        
!       if (!complain)
          return error_mark_node;
  
        pedwarn ("assuming pointer to member `%D'", fn);
--- 5914,5924 ----
    fn = TREE_PURPOSE (matches);
  
    if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
!       && !(flags & tf_ptrmem_ok) && !flag_ms_extensions)
      {
        static int explained;
        
!       if (!(flags & tf_error))
          return error_mark_node;
  
        pedwarn ("assuming pointer to member `%D'", fn);
*************** cannot resolve overloaded function `%D' 
*** 5948,5954 ****
  
  /* This function will instantiate the type of the expression given in
     RHS to match the type of LHSTYPE.  If errors exist, then return
!    error_mark_node. FLAGS is a bit mask.  If ITF_COMPLAIN is set, then
     we complain on errors.  If we are not complaining, never modify rhs,
     as overload resolution wants to try many possible instantiations, in
     the hope that at least one will work.
--- 5945,5951 ----
  
  /* This function will instantiate the type of the expression given in
     RHS to match the type of LHSTYPE.  If errors exist, then return
!    error_mark_node. FLAGS is a bit mask.  If TF_ERROR is set, then
     we complain on errors.  If we are not complaining, never modify rhs,
     as overload resolution wants to try many possible instantiations, in
     the hope that at least one will work.
*************** cannot resolve overloaded function `%D' 
*** 5959,5972 ****
  tree
  instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
  {
!   int complain = (flags & tf_error);
!   int allow_ptrmem = flags & tf_ptrmem_ok;
    
    flags &= ~tf_ptrmem_ok;
    
    if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
      {
!       if (complain)
  	error ("not enough type information");
        return error_mark_node;
      }
--- 5956,5968 ----
  tree
  instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
  {
!   tsubst_flags_t flags_in = flags;
    
    flags &= ~tf_ptrmem_ok;
    
    if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
      {
!       if (flags & tf_error)
  	error ("not enough type information");
        return error_mark_node;
      }
*************** instantiate_type (tree lhstype, tree rhs
*** 5983,5989 ****
  	;
        else
  	{
! 	  if (complain)
  	    error ("argument of type `%T' does not match `%T'",
  		   TREE_TYPE (rhs), lhstype);
  	  return error_mark_node;
--- 5979,5985 ----
  	;
        else
  	{
! 	  if (flags & tf_error)
  	    error ("argument of type `%T' does not match `%T'",
  		   TREE_TYPE (rhs), lhstype);
  	  return error_mark_node;
*************** instantiate_type (tree lhstype, tree rhs
*** 6034,6046 ****
        return instantiate_type (lhstype, rhs, flags);
  
      case COMPONENT_REF:
!       return instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
  
      case OFFSET_REF:
        rhs = TREE_OPERAND (rhs, 1);
        if (BASELINK_P (rhs))
! 	return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs),
! 	                         flags | allow_ptrmem);
  
        /* This can happen if we are forming a pointer-to-member for a
  	 member template.  */
--- 6030,6050 ----
        return instantiate_type (lhstype, rhs, flags);
  
      case COMPONENT_REF:
!       {
! 	tree addr = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
! 
! 	if (addr != error_mark_node
! 	    && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
! 	  /* Do not lose object's side effects. */
! 	  addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
! 			TREE_OPERAND (rhs, 0), addr);
! 	return addr;
!       }
  
      case OFFSET_REF:
        rhs = TREE_OPERAND (rhs, 1);
        if (BASELINK_P (rhs))
! 	return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags_in);
  
        /* This can happen if we are forming a pointer-to-member for a
  	 member template.  */
*************** instantiate_type (tree lhstype, tree rhs
*** 6054,6075 ****
  	tree args = TREE_OPERAND (rhs, 1);
  
  	return
! 	  resolve_address_of_overloaded_function (lhstype,
! 						  fns,
! 						  complain,
! 	                                          allow_ptrmem,
! 						  /*template_only=*/1,
  						  args);
        }
  
      case OVERLOAD:
      case FUNCTION_DECL:
        return 
! 	resolve_address_of_overloaded_function (lhstype, 
! 						rhs,
! 						complain,
! 	                                        allow_ptrmem,
! 						/*template_only=*/0,
  						/*explicit_targs=*/NULL_TREE);
  
      case TREE_LIST:
--- 6058,6073 ----
  	tree args = TREE_OPERAND (rhs, 1);
  
  	return
! 	  resolve_address_of_overloaded_function (lhstype, fns, flags_in,
! 						  /*template_only=*/true,
  						  args);
        }
  
      case OVERLOAD:
      case FUNCTION_DECL:
        return 
! 	resolve_address_of_overloaded_function (lhstype, rhs, flags_in,
! 						/*template_only=*/false,
  						/*explicit_targs=*/NULL_TREE);
  
      case TREE_LIST:
*************** instantiate_type (tree lhstype, tree rhs
*** 6131,6137 ****
      case PREDECREMENT_EXPR:
      case POSTINCREMENT_EXPR:
      case POSTDECREMENT_EXPR:
!       if (complain)
  	error ("invalid operation on uninstantiated type");
        return error_mark_node;
  
--- 6129,6135 ----
      case PREDECREMENT_EXPR:
      case POSTINCREMENT_EXPR:
      case POSTDECREMENT_EXPR:
!       if (flags & tf_error)
  	error ("invalid operation on uninstantiated type");
        return error_mark_node;
  
*************** instantiate_type (tree lhstype, tree rhs
*** 6147,6160 ****
      case TRUTH_ANDIF_EXPR:
      case TRUTH_ORIF_EXPR:
      case TRUTH_NOT_EXPR:
!       if (complain)
  	error ("not enough type information");
        return error_mark_node;
  
      case COND_EXPR:
        if (type_unknown_p (TREE_OPERAND (rhs, 0)))
  	{
! 	  if (complain)
  	    error ("not enough type information");
  	  return error_mark_node;
  	}
--- 6145,6158 ----
      case TRUTH_ANDIF_EXPR:
      case TRUTH_ORIF_EXPR:
      case TRUTH_NOT_EXPR:
!       if (flags & tf_error)
  	error ("not enough type information");
        return error_mark_node;
  
      case COND_EXPR:
        if (type_unknown_p (TREE_OPERAND (rhs, 0)))
  	{
! 	  if (flags & tf_error)
  	    error ("not enough type information");
  	  return error_mark_node;
  	}
// { dg-do run }

// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 6 Sep 2003 <nathan@codesourcery.com>
// Origin: Volker Reichelt <reichelt@igpm.rwth-aachen.de>

// PR c++/11788 we failed to instantiate a decl, and we lost some side
// effects

static int flag = 0;

template <typename> struct A
{
  A &active ()  { flag++;}
  
  static void foo() {}

  static void bar () {}
  static void bar (int) {}

  int m;
};

void (*baz ()) ()
{
    A<int> a;
    return &a.active ().foo;
}

void (*boz ()) ()
{
    A<int> a;
    return &a.active ().bar;
}

int *buz ()
{
  A<int> a;
  
  return &a.active ().m;
}

int main ()
{
  baz ();
  boz ();
  buz ();
  
  return flag != 3;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]