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: PR 7129


This patch fixes a regression (ICE) on the use of the
compound-assignment operators "<?=" and ">?=" in some situations in
G++.  These operators are extensions, naturally.

I also cleaned up some gunk in cp/call.c, including totally unecessary
uses of tree_cons; we consed up lists that we then just threw away.

Tested on i686-pc-linux-gnu, applied on the mainline and the 3.3
branch.

(Gaby, if you want this in 3.2.2 you can just apply the operators.def
portion of the patch.  If you don't want it in 3.2.2, please close the
PR or let me know and I will do it.)

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2003-02-03  Mark Mitchell  <mark@codesourcery.com>

	PR c++/7129
	* call.c (z_candidate): Add args.
	(convert_class_to_reference): Set it.
	(implicit_conversion): Tidy.
	(add_candidate): Add args parameter.
	(add_function_candidate): Adjust call to add_candidate.
	(add_conv_candidate): Likewise.
	(build_builtin_candidate): Likewise.
	(build_user_type_conversion_1): Eliminate wasteful tree_cons
	usage.
	(build_new_function_call): Likewise.
	(build_object_call): Likewise.
	(add_candidates): New function.
	(build_new_op): Use it.
	(covert_like_real): Adjust call to build_over_call.
	(build_over_call): Remove args parameter.
	* operators.def: Add <?= and >?=.

2003-02-03  Mark Mitchell  <mark@codesourcery.com>

	PR c++/7129
	* testsuite/g++.dg/ext/max.C: New test.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.354
diff -c -5 -p -r1.354 call.c
*** cp/call.c	30 Jan 2003 07:23:58 -0000	1.354
--- cp/call.c	4 Feb 2003 07:21:05 -0000
*************** extern int inhibit_warnings;
*** 42,52 ****
  static tree build_field_call (tree, tree, tree);
  static struct z_candidate * tourney (struct z_candidate *);
  static int equal_functions (tree, tree);
  static int joust (struct z_candidate *, struct z_candidate *, bool);
  static int compare_ics (tree, tree);
! static tree build_over_call (struct z_candidate *, tree, int);
  static tree build_java_interface_fn_ref (tree, tree);
  #define convert_like(CONV, EXPR) \
    convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
  #define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
    convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
--- 42,52 ----
  static tree build_field_call (tree, tree, tree);
  static struct z_candidate * tourney (struct z_candidate *);
  static int equal_functions (tree, tree);
  static int joust (struct z_candidate *, struct z_candidate *, bool);
  static int compare_ics (tree, tree);
! static tree build_over_call (struct z_candidate *, int);
  static tree build_java_interface_fn_ref (tree, tree);
  #define convert_like(CONV, EXPR) \
    convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
  #define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
    convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
*************** static tree non_reference (tree);
*** 90,100 ****
  static tree build_conv (enum tree_code, tree, tree);
  static bool is_subseq (tree, tree);
  static tree maybe_handle_ref_bind (tree *);
  static void maybe_handle_implicit_object (tree *);
  static struct z_candidate *add_candidate 
!         (struct z_candidate *, tree, tree, tree, tree, int);
  static tree source_type (tree);
  static void add_warning (struct z_candidate *, struct z_candidate *);
  static bool reference_related_p (tree, tree);
  static bool reference_compatible_p (tree, tree);
  static tree convert_class_to_reference (tree, tree, tree);
--- 90,100 ----
  static tree build_conv (enum tree_code, tree, tree);
  static bool is_subseq (tree, tree);
  static tree maybe_handle_ref_bind (tree *);
  static void maybe_handle_implicit_object (tree *);
  static struct z_candidate *add_candidate 
!         (struct z_candidate *, tree, tree, tree, tree, tree, int);
  static tree source_type (tree);
  static void add_warning (struct z_candidate *, struct z_candidate *);
  static bool reference_related_p (tree, tree);
  static bool reference_compatible_p (tree, tree);
  static tree convert_class_to_reference (tree, tree, tree);
*************** static tree direct_reference_binding (tr
*** 102,111 ****
--- 102,113 ----
  static bool promoted_arithmetic_type_p (tree);
  static tree conditional_conversion (tree, tree);
  static char *name_as_c_string (tree, tree, bool *);
  static tree call_builtin_trap (void);
  static tree prep_operand (tree);
+ static struct z_candidate *add_candidates (tree, tree, tree, tree,
+ 					   int, struct z_candidate *);
  
  tree
  build_vfield_ref (tree datum, tree type)
  {
    if (datum == error_mark_node)
*************** build_method_call (tree instance, tree n
*** 554,563 ****
--- 556,567 ----
  
  struct z_candidate GTY(()) {
    /* The FUNCTION_DECL that will be called if this candidate is
       selected by overload resolution.  */
    tree fn;
+   /* The arguments to use when calling this function.  */
+   tree args;
    tree convs;
    tree second_conv;
    int viable;
    /* If FN is a member function, the binfo indicating the path used to
       qualify the name of FN at the call site.  This path is used to
*************** convert_class_to_reference (tree t, tree
*** 1032,1041 ****
--- 1036,1051 ----
    candidates = splice_viable (candidates);
    cand = tourney (candidates);
    if (!cand)
      return NULL_TREE;
  
+   /* Now that we know that this is the function we're going to use fix
+      the dummy first argument.  */
+   cand->args = tree_cons (NULL_TREE,
+ 			  build_this (expr),
+ 			  TREE_CHAIN (cand->args));
+ 
    conv = build1 (IDENTITY_CONV, s, expr);
    conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
  		     conv);
    TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
    ICS_USER_FLAG (conv) = 1;
*************** implicit_conversion (tree to, tree from,
*** 1267,1307 ****
      conv = reference_binding (to, from, expr, flags);
    else
      conv = standard_conversion (to, from, expr);
  
    if (conv)
!     ;
!   else if (expr != NULL_TREE
! 	   && (IS_AGGR_TYPE (from)
! 	       || IS_AGGR_TYPE (to))
! 	   && (flags & LOOKUP_NO_CONVERSION) == 0)
      {
        cand = build_user_type_conversion_1
  	(to, expr, LOOKUP_ONLYCONVERTING);
        if (cand)
  	conv = cand->second_conv;
  
        /* We used to try to bind a reference to a temporary here, but that
  	 is now handled by the recursive call to this function at the end
  	 of reference_binding.  */
      }
  
!   return conv;
  }
  
  /* Add a new entry to the list of candidates.  Used by the add_*_candidate
     functions.  */
  
  static struct z_candidate *
  add_candidate (struct z_candidate *candidates, 
! 	       tree fn, tree convs, tree access_path, tree
! 	       conversion_path, int viable)
  {
    struct z_candidate *cand
      = (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
  
    cand->fn = fn;
    cand->convs = convs;
    cand->access_path = access_path;
    cand->conversion_path = conversion_path;
    cand->viable = viable;
    cand->next = candidates;
--- 1277,1320 ----
      conv = reference_binding (to, from, expr, flags);
    else
      conv = standard_conversion (to, from, expr);
  
    if (conv)
!     return conv;
! 
!   if (expr != NULL_TREE
!       && (IS_AGGR_TYPE (from)
! 	  || IS_AGGR_TYPE (to))
!       && (flags & LOOKUP_NO_CONVERSION) == 0)
      {
        cand = build_user_type_conversion_1
  	(to, expr, LOOKUP_ONLYCONVERTING);
        if (cand)
  	conv = cand->second_conv;
  
        /* We used to try to bind a reference to a temporary here, but that
  	 is now handled by the recursive call to this function at the end
  	 of reference_binding.  */
+       return conv;
      }
  
!   return NULL_TREE;
  }
  
  /* Add a new entry to the list of candidates.  Used by the add_*_candidate
     functions.  */
  
  static struct z_candidate *
  add_candidate (struct z_candidate *candidates, 
! 	       tree fn, tree args, tree convs, tree access_path, 
! 	       tree conversion_path, int viable)
  {
    struct z_candidate *cand
      = (struct z_candidate *) ggc_alloc_cleared (sizeof (struct z_candidate));
  
    cand->fn = fn;
+   cand->args = args;
    cand->convs = convs;
    cand->access_path = access_path;
    cand->conversion_path = conversion_path;
    cand->viable = viable;
    cand->next = candidates;
*************** add_function_candidate (struct z_candida
*** 1324,1342 ****
--- 1337,1359 ----
  {
    tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
    int i, len;
    tree convs;
    tree parmnode, argnode;
+   tree orig_arglist;
    int viable = 1;
  
    /* The `this', `in_chrg' and VTT arguments to constructors are not
       considered in overload resolution.  */
    if (DECL_CONSTRUCTOR_P (fn))
      {
        parmlist = skip_artificial_parms_for (fn, parmlist);
+       orig_arglist = arglist;
        arglist = skip_artificial_parms_for (fn, arglist);
      }
+   else 
+     orig_arglist = arglist;
  
    len = list_length (arglist);
    convs = make_tree_vec (len);
  
    /* 13.3.2 - Viable functions [over.match.viable]
*************** add_function_candidate (struct z_candida
*** 1430,1440 ****
  	parmnode = TREE_CHAIN (parmnode);
        argnode = TREE_CHAIN (argnode);
      }
  
   out:
!   return add_candidate (candidates, fn, convs, access_path,
  			conversion_path, viable);
  }
  
  /* Create an overload candidate for the conversion function FN which will
     be invoked for expression OBJ, producing a pointer-to-function which
--- 1447,1457 ----
  	parmnode = TREE_CHAIN (parmnode);
        argnode = TREE_CHAIN (argnode);
      }
  
   out:
!   return add_candidate (candidates, fn, orig_arglist, convs, access_path,
  			conversion_path, viable);
  }
  
  /* Create an overload candidate for the conversion function FN which will
     be invoked for expression OBJ, producing a pointer-to-function which
*************** add_conv_candidate (struct z_candidate *
*** 1507,1517 ****
      viable = 0;
  
    if (!sufficient_parms_p (parmnode))
      viable = 0;
  
!   return add_candidate (candidates, totype, convs, access_path,
  			conversion_path, viable);
  }
  
  static struct z_candidate *
  build_builtin_candidate (struct z_candidate *candidates, tree fnname,
--- 1524,1534 ----
      viable = 0;
  
    if (!sufficient_parms_p (parmnode))
      viable = 0;
  
!   return add_candidate (candidates, totype, arglist, convs, access_path,
  			conversion_path, viable);
  }
  
  static struct z_candidate *
  build_builtin_candidate (struct z_candidate *candidates, tree fnname,
*************** build_builtin_candidate (struct z_candid
*** 1554,1564 ****
  	TREE_VEC_ELT (convs, 0) = t;
        else
  	viable = 0;
      }      
  
!   return add_candidate (candidates, fnname, convs, 
  			/*access_path=*/NULL_TREE,
  			/*conversion_path=*/NULL_TREE,
  			viable);
  }
  
--- 1571,1581 ----
  	TREE_VEC_ELT (convs, 0) = t;
        else
  	viable = 0;
      }      
  
!   return add_candidate (candidates, fnname, /*args=*/NULL_TREE, convs, 
  			/*access_path=*/NULL_TREE,
  			/*conversion_path=*/NULL_TREE,
  			viable);
  }
  
*************** build_user_type_conversion_1 (tree totyp
*** 2394,2404 ****
  {
    struct z_candidate *candidates, *cand;
    tree fromtype = TREE_TYPE (expr);
    tree ctors = NULL_TREE, convs = NULL_TREE, *p;
    tree args = NULL_TREE;
-   tree templates = NULL_TREE;
  
    /* We represent conversion within a hierarchy using RVALUE_CONV and
       BASE_CONV, as specified by [over.best.ics]; these become plain
       constructor calls, as specified in [dcl.init].  */
    my_friendly_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype)
--- 2411,2420 ----
*************** build_user_type_conversion_1 (tree totyp
*** 2436,2455 ****
        tree ctor = OVL_CURRENT (ctors);
        if (DECL_NONCONVERTING_P (ctor))
  	continue;
  
        if (TREE_CODE (ctor) == TEMPLATE_DECL) 
! 	{
! 	  templates = tree_cons (NULL_TREE, ctor, templates);
! 	  candidates = 
! 	    add_template_candidate (candidates, ctor, totype,
! 				    NULL_TREE, args, NULL_TREE, 
! 				    TYPE_BINFO (totype),
! 				    TYPE_BINFO (totype),
! 				    flags,
! 				    DEDUCE_CALL);
! 	}
        else 
  	candidates = add_function_candidate (candidates, ctor, totype,
  					     args, TYPE_BINFO (totype), 
  					     TYPE_BINFO (totype),
  					     flags); 
--- 2452,2468 ----
        tree ctor = OVL_CURRENT (ctors);
        if (DECL_NONCONVERTING_P (ctor))
  	continue;
  
        if (TREE_CODE (ctor) == TEMPLATE_DECL) 
! 	candidates = 
! 	  add_template_candidate (candidates, ctor, totype,
! 				  NULL_TREE, args, NULL_TREE, 
! 				  TYPE_BINFO (totype),
! 				  TYPE_BINFO (totype),
! 				  flags,
! 				  DEDUCE_CALL);
        else 
  	candidates = add_function_candidate (candidates, ctor, totype,
  					     args, TYPE_BINFO (totype), 
  					     TYPE_BINFO (totype),
  					     flags); 
*************** build_user_type_conversion_1 (tree totyp
*** 2485,2503 ****
  	     the implicit object parameter.
  
  	     So we pass fromtype as CTYPE to add_*_candidate.  */
  
  	  if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	    {
! 	      templates = tree_cons (NULL_TREE, fn, templates);
! 	      candidates = 
! 		add_template_candidate (candidates, fn, fromtype, NULL_TREE,
! 					args, totype, TYPE_BINFO (fromtype), 
! 					conversion_path,
! 					flags,
! 					DEDUCE_CONV);
! 	    } 
  	  else 
  	    candidates = add_function_candidate (candidates, fn, fromtype,
  						 args,
  						 TYPE_BINFO (fromtype),
  						 conversion_path,
--- 2498,2513 ----
  	     the implicit object parameter.
  
  	     So we pass fromtype as CTYPE to add_*_candidate.  */
  
  	  if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	    candidates = 
! 	      add_template_candidate (candidates, fn, fromtype, NULL_TREE,
! 				      args, totype, TYPE_BINFO (fromtype), 
! 				      conversion_path,
! 				      flags,
! 				      DEDUCE_CONV);
  	  else 
  	    candidates = add_function_candidate (candidates, fn, fromtype,
  						 args,
  						 TYPE_BINFO (fromtype),
  						 conversion_path,
*************** build_new_function_call (tree fn, tree a
*** 2693,2703 ****
  
    if (really_overloaded_fn (fn) 
        || TREE_CODE (fn) == TEMPLATE_DECL)
      {
        tree t1;
-       tree templates = NULL_TREE;
  
        args = resolve_args (args);
  
        if (args == error_mark_node)
  	return error_mark_node;
--- 2703,2712 ----
*************** build_new_function_call (tree fn, tree a
*** 2707,2724 ****
  	  tree t = OVL_CURRENT (t1);
  
  	  my_friendly_assert (!DECL_FUNCTION_MEMBER_P (t), 20020913);
  
  	  if (TREE_CODE (t) == TEMPLATE_DECL)
! 	    {
! 	      templates = tree_cons (NULL_TREE, t, templates);
! 	      candidates = add_template_candidate
! 		(candidates, t, NULL_TREE, explicit_targs, args, 
! 		 NULL_TREE, /*access_path=*/NULL_TREE, 
! 		 /*conversion_path=*/NULL_TREE,
! 		 LOOKUP_NORMAL, DEDUCE_CALL);  
! 	    }
  	  else if (! template_only)
  	    candidates = add_function_candidate
  	      (candidates, t, NULL_TREE, args, 
  	       /*access_path=*/NULL_TREE,
  	       /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
--- 2716,2730 ----
  	  tree t = OVL_CURRENT (t1);
  
  	  my_friendly_assert (!DECL_FUNCTION_MEMBER_P (t), 20020913);
  
  	  if (TREE_CODE (t) == TEMPLATE_DECL)
! 	    candidates = add_template_candidate
! 	      (candidates, t, NULL_TREE, explicit_targs, args, 
! 	       NULL_TREE, /*access_path=*/NULL_TREE, 
! 	       /*conversion_path=*/NULL_TREE,
! 	       LOOKUP_NORMAL, DEDUCE_CALL);  
  	  else if (! template_only)
  	    candidates = add_function_candidate
  	      (candidates, t, NULL_TREE, args, 
  	       /*access_path=*/NULL_TREE,
  	       /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL);
*************** build_new_function_call (tree fn, tree a
*** 2743,2753 ****
  		    DECL_NAME (OVL_FUNCTION (fn)), args);
  	  print_z_candidates (candidates);
  	  return error_mark_node;
  	}
  
!       return build_over_call (cand, args, LOOKUP_NORMAL);
      }
  
    /* This is not really overloaded.  */
    fn = OVL_CURRENT (fn);
  
--- 2749,2759 ----
  		    DECL_NAME (OVL_FUNCTION (fn)), args);
  	  print_z_candidates (candidates);
  	  return error_mark_node;
  	}
  
!       return build_over_call (cand, LOOKUP_NORMAL);
      }
  
    /* This is not really overloaded.  */
    fn = OVL_CURRENT (fn);
  
*************** build_object_call (tree obj, tree args)
*** 2785,2802 ****
  
        for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	    {
! 	      candidates 
! 		= add_template_candidate (candidates, fn, base, NULL_TREE,
! 					  mem_args, NULL_TREE, 
! 					  TYPE_BINFO (type),
! 					  TYPE_BINFO (type),
! 					  LOOKUP_NORMAL, DEDUCE_CALL);
! 	    }
  	  else
  	    candidates = add_function_candidate
  	      (candidates, fn, base, mem_args, TYPE_BINFO (type),
  	       TYPE_BINFO (type), LOOKUP_NORMAL);
  	}
--- 2791,2806 ----
  
        for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
  	{
  	  tree fn = OVL_CURRENT (fns);
  	  if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	    candidates 
! 	      = add_template_candidate (candidates, fn, base, NULL_TREE,
! 					mem_args, NULL_TREE, 
! 					TYPE_BINFO (type),
! 					TYPE_BINFO (type),
! 					LOOKUP_NORMAL, DEDUCE_CALL);
  	  else
  	    candidates = add_function_candidate
  	      (candidates, fn, base, mem_args, TYPE_BINFO (type),
  	       TYPE_BINFO (type), LOOKUP_NORMAL);
  	}
*************** build_object_call (tree obj, tree args)
*** 2853,2863 ****
    /* Since cand->fn will be a type, not a function, for a conversion
       function, we must be careful not to unconditionally look at
       DECL_NAME here.  */
    if (TREE_CODE (cand->fn) == FUNCTION_DECL
        && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
!     return build_over_call (cand, mem_args, LOOKUP_NORMAL);
  
    obj = convert_like_with_context
            (TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1);
  
    /* FIXME */
--- 2857,2867 ----
    /* Since cand->fn will be a type, not a function, for a conversion
       function, we must be careful not to unconditionally look at
       DECL_NAME here.  */
    if (TREE_CODE (cand->fn) == FUNCTION_DECL
        && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR)
!     return build_over_call (cand, LOOKUP_NORMAL);
  
    obj = convert_like_with_context
            (TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1);
  
    /* FIXME */
*************** prep_operand (tree operand)
*** 3315,3331 ****
      }
  
    return operand;
  }
  
  tree
  build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
  {
    struct z_candidate *candidates = 0, *cand;
!   tree fns, mem_arglist = NULL_TREE, arglist, fnname;
    enum tree_code code2 = NOP_EXPR;
-   tree templates = NULL_TREE;
    tree conv;
    bool viable_candidates;
  
    if (error_operand_p (arg1) 
        || error_operand_p (arg2) 
--- 3319,3400 ----
      }
  
    return operand;
  }
  
+ /* Add each of the viable functions in FNS (a FUNCTION_DECL or
+    OVERLOAD) to the CANDIDATES, returning an updated list of
+    CANDIDATES.  The ARGS are the arguments provided to the call,
+    without any implicit object parameter.  CONVERSION_PATH,
+    ACCESS_PATH, and FLAGS are as for add_function_candidate.  */
+ 
+ static struct z_candidate *
+ add_candidates (tree fns, tree args,
+ 		tree conversion_path, tree access_path,
+ 		int flags,
+ 		struct z_candidate *candidates)
+ {
+   tree ctype;
+   tree non_static_args;
+ 
+   ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
+   /* Delay creating the implicit this parameter until it is needed.  */
+   non_static_args = NULL_TREE;
+ 
+   while (fns) 
+     {
+       tree fn;
+       tree fn_args;
+ 
+       fn = OVL_CURRENT (fns);
+       /* Figure out which set of arguments to use.  */
+       if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
+ 	{
+ 	  /* If this function is a non-static member, prepend the implicit
+ 	     object parameter.  */
+ 	  if (!non_static_args)
+ 	    non_static_args = tree_cons (NULL_TREE,
+ 					 build_this (TREE_VALUE (args)),
+ 					 TREE_CHAIN (args));
+ 	  fn_args = non_static_args;
+ 	}
+       else
+ 	/* Otherwise, just use the list of arguments provided.  */
+ 	fn_args = args;
+ 
+       if (TREE_CODE (fn) == TEMPLATE_DECL)
+ 	candidates = add_template_candidate (candidates, 
+ 					     fn, 
+ 					     ctype,
+ 					     NULL_TREE,
+ 					     fn_args,
+ 					     NULL_TREE,
+ 					     access_path,
+ 					     conversion_path,
+ 					     flags,
+ 					     DEDUCE_CALL);
+       else
+ 	candidates = add_function_candidate (candidates,
+ 					     fn,
+ 					     ctype,
+ 					     fn_args,
+ 					     access_path,
+ 					     conversion_path,
+ 					     flags);
+       fns = OVL_NEXT (fns);
+     }
+ 
+   return candidates;
+ }
+ 
  tree
  build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
  {
    struct z_candidate *candidates = 0, *cand;
!   tree arglist, fnname;
!   tree args[3];
    enum tree_code code2 = NOP_EXPR;
    tree conv;
    bool viable_candidates;
  
    if (error_operand_p (arg1) 
        || error_operand_p (arg2) 
*************** build_new_op (enum tree_code code, int f
*** 3383,3484 ****
      arglist = tree_cons (NULL_TREE, arg3, arglist);
    if (arg2)
      arglist = tree_cons (NULL_TREE, arg2, arglist);
    arglist = tree_cons (NULL_TREE, arg1, arglist);
  
!   fns = lookup_function_nonclass (fnname, arglist);
! 
!   if (fns && TREE_CODE (fns) == TREE_LIST)
!     fns = TREE_VALUE (fns);
!   for (; fns; fns = OVL_NEXT (fns))
      {
!       tree fn = OVL_CURRENT (fns);
!       if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	{
! 	  templates = tree_cons (NULL_TREE, fn, templates);
! 	  candidates 
! 	    = add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
! 				      arglist, TREE_TYPE (fnname),
! 				      /*access_path=*/NULL_TREE,
! 				      /*conversion_path=*/NULL_TREE,
! 				      flags, DEDUCE_CALL); 
! 	}
!       else
! 	candidates = add_function_candidate (candidates, fn, NULL_TREE,
! 					     arglist,
! 					     /*access_path=*/NULL_TREE,
! 					     /*conversion_path=*/NULL_TREE,
! 					     flags);
!     }
  
-   if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
-     {
        fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1);
        if (fns == error_mark_node)
  	return fns;
      }
-   else
-     fns = NULL_TREE;
  
!   if (fns)
      {
!       tree conversion_path = BASELINK_BINFO (fns);
! 
!       mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
!       for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
! 	{
! 	  tree fn = OVL_CURRENT (fns);
! 	  tree this_arglist;
! 	  tree access_path = TYPE_BINFO (TREE_TYPE (arg1));
! 
! 	  if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
! 	    this_arglist = mem_arglist;
! 	  else
! 	    this_arglist = arglist;
! 
! 	  if (TREE_CODE (fn) == TEMPLATE_DECL)
! 	    {
! 	      /* A member template.  */
! 	      templates = tree_cons (NULL_TREE, fn, templates);
! 	      candidates 
! 		= add_template_candidate (candidates, fn, 
! 					  BINFO_TYPE (conversion_path),
! 					  NULL_TREE,
! 					  this_arglist,  TREE_TYPE (fnname),
! 					  access_path, conversion_path,
! 					  flags, DEDUCE_CALL); 
! 	    }
! 	  else
! 	    candidates = add_function_candidate
! 	      (candidates, fn, BINFO_TYPE (conversion_path), this_arglist, 
! 	       access_path, conversion_path, flags);
! 	}
      }
  
!   {
!     tree args[3];
! 
!     /* Rearrange the arguments for ?: so that add_builtin_candidate only has
!        to know about two args; a builtin candidate will always have a first
!        parameter of type bool.  We'll handle that in
!        build_builtin_candidate.  */
!     if (code == COND_EXPR)
!       {
! 	args[0] = arg2;
! 	args[1] = arg3;
! 	args[2] = arg1;
!       }
!     else
!       {
! 	args[0] = arg1;
! 	args[1] = arg2;
! 	args[2] = NULL_TREE;
!       }
! 
!     candidates = add_builtin_candidates
!       (candidates, code, code2, fnname, args, flags);
!   }
  
    switch (code)
      {
      case COMPOUND_EXPR:
      case ADDR_EXPR:
--- 3452,3500 ----
      arglist = tree_cons (NULL_TREE, arg3, arglist);
    if (arg2)
      arglist = tree_cons (NULL_TREE, arg2, arglist);
    arglist = tree_cons (NULL_TREE, arg1, arglist);
  
!   /* Add namespace-scope operators to the list of functions to
!      consider.  */
!   candidates = add_candidates (lookup_function_nonclass (fnname, arglist),
! 			       arglist, NULL_TREE, NULL_TREE,
! 			       flags, candidates);
!   /* Add class-member operators to the candidate set.  */
!   if (CLASS_TYPE_P (TREE_TYPE (arg1)))
      {
!       tree fns;
  
        fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1);
        if (fns == error_mark_node)
  	return fns;
+       if (fns)
+ 	candidates = add_candidates (BASELINK_FUNCTIONS (fns), arglist, 
+ 				     BASELINK_BINFO (fns),
+ 				     TYPE_BINFO (TREE_TYPE (arg1)),
+ 				     flags, candidates);
      }
  
!   /* Rearrange the arguments for ?: so that add_builtin_candidate only has
!      to know about two args; a builtin candidate will always have a first
!      parameter of type bool.  We'll handle that in
!      build_builtin_candidate.  */
!   if (code == COND_EXPR)
      {
!       args[0] = arg2;
!       args[1] = arg3;
!       args[2] = arg1;
!     }
!   else
!     {
!       args[0] = arg1;
!       args[1] = arg2;
!       args[2] = NULL_TREE;
      }
  
!   candidates = add_builtin_candidates
!     (candidates, code, code2, fnname, args, flags);
  
    switch (code)
      {
      case COMPOUND_EXPR:
      case ADDR_EXPR:
*************** build_new_op (enum tree_code code, int f
*** 3557,3571 ****
  			 cand == candidates
  			 ? candidates->next->fn
  			 : candidates->fn);
  	}
  
!       return build_over_call
! 	(cand,
! 	 TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
! 	 ? mem_arglist : arglist,
! 	 LOOKUP_NORMAL);
      }
  
    /* Check for comparison of different enum types.  */
    switch (code)
      {
--- 3573,3583 ----
  			 cand == candidates
  			 ? candidates->next->fn
  			 : candidates->fn);
  	}
  
!       return build_over_call (cand, LOOKUP_NORMAL);
      }
  
    /* Check for comparison of different enum types.  */
    switch (code)
      {
*************** convert_like_real (tree convs, tree expr
*** 3905,3915 ****
  	      abort ();
  	    args = tree_cons (NULL_TREE, t, args);
  	  }
  	else
  	  args = build_this (expr);
! 	expr = build_over_call (cand, args, LOOKUP_NORMAL);
  
  	/* If this is a constructor or a function returning an aggr type,
  	   we need to build up a TARGET_EXPR.  */
  	if (DECL_CONSTRUCTOR_P (convfn))
  	  expr = build_cplus_new (totype, expr);
--- 3917,3927 ----
  	      abort ();
  	    args = tree_cons (NULL_TREE, t, args);
  	  }
  	else
  	  args = build_this (expr);
! 	expr = build_over_call (cand, LOOKUP_NORMAL);
  
  	/* If this is a constructor or a function returning an aggr type,
  	   we need to build up a TARGET_EXPR.  */
  	if (DECL_CONSTRUCTOR_P (convfn))
  	  expr = build_cplus_new (totype, expr);
*************** convert_for_arg_passing (tree type, tree
*** 4236,4248 ****
     has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
     ARGS is a TREE_LIST of the unconverted arguments to the call.  FLAGS is a
     bitmask of various LOOKUP_* flags which apply to the call itself.  */
  
  static tree
! build_over_call (struct z_candidate *cand, tree args, int flags)
  {
    tree fn = cand->fn;
    tree convs = cand->convs;
    tree converted_args = NULL_TREE;
    tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
    tree conv, arg, val;
    int i = 0;
--- 4248,4261 ----
     has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
     ARGS is a TREE_LIST of the unconverted arguments to the call.  FLAGS is a
     bitmask of various LOOKUP_* flags which apply to the call itself.  */
  
  static tree
! build_over_call (struct z_candidate *cand, int flags)
  {
    tree fn = cand->fn;
+   tree args = cand->args;
    tree convs = cand->convs;
    tree converted_args = NULL_TREE;
    tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
    tree conv, arg, val;
    int i = 0;
*************** build_new_method_call (tree instance, tr
*** 4700,4710 ****
    tree access_binfo;
    tree optype;
    tree mem_args = NULL_TREE, instance_ptr;
    tree name;
    tree user_args;
-   tree templates = NULL_TREE;
    tree call;
    tree fn;
    tree class_type;
    int template_only = 0;
  
--- 4713,4722 ----
*************** build_new_method_call (tree instance, tr
*** 4805,4815 ****
  	this_arglist = args;
  
        if (TREE_CODE (t) == TEMPLATE_DECL)
  	{
  	  /* A member template.  */
- 	  templates = tree_cons (NULL_TREE, t, templates);
  	  candidates = 
  	    add_template_candidate (candidates, t, 
  				    class_type,
  				    explicit_targs,
  				    this_arglist, optype,
--- 4817,4826 ----
*************** build_new_method_call (tree instance, tr
*** 4886,4899 ****
    if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
        && resolves_to_fixed_type_p (instance, 0))
      flags |= LOOKUP_NONVIRTUAL;
  
    if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE)
!     call = build_over_call (cand, mem_args, flags);
    else
      {
!       call = build_over_call (cand, args, flags);
        /* In an expression of the form `a->f()' where `f' turns out to
  	 be a static member function, `a' is none-the-less evaluated.  */
        if (!is_dummy_object (instance_ptr) && TREE_SIDE_EFFECTS (instance))
  	call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
      }
--- 4897,4910 ----
    if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
        && resolves_to_fixed_type_p (instance, 0))
      flags |= LOOKUP_NONVIRTUAL;
  
    if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE)
!     call = build_over_call (cand, flags);
    else
      {
!       call = build_over_call (cand, flags);
        /* In an expression of the form `a->f()' where `f' turns out to
  	 be a static member function, `a' is none-the-less evaluated.  */
        if (!is_dummy_object (instance_ptr) && TREE_SIDE_EFFECTS (instance))
  	call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
      }
Index: cp/operators.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/operators.def,v
retrieving revision 1.12
diff -c -5 -p -r1.12 operators.def
*** cp/operators.def	30 Dec 2002 18:06:39 -0000	1.12
--- cp/operators.def	4 Feb 2003 07:12:25 -0000
***************
*** 3,13 ****
     This file contains definitions of the various C++ operators,
     including both overloadable operators (like `+') and
     non-overloadable operators (like the `?:' ternary operator).  
     Written by Mark Mitchell <mark@codesourcery.com>
  
!    Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
  GCC is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
--- 3,13 ----
     This file contains definitions of the various C++ operators,
     including both overloadable operators (like `+') and
     non-overloadable operators (like the `?:' ternary operator).  
     Written by Mark Mitchell <mark@codesourcery.com>
  
!    Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
  
  This file is part of GCC.
  
  GCC is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
*************** Boston, MA 02111-1307, USA.  */
*** 38,48 ****
       The tree_code for this operator.  For `operator +', for example,
       this would be PLUS_EXPR.  Because there are no tree codes for
       assignment operators, the same tree-codes are reused; i.e.,
       `operator +' will also have PLUS_EXPR as its CODE.
  
!    NEW_MANGLING
  
       The mangling prefix for the operator, as a C string, and as
       mangled under the new ABI.  For `operator +', for example, this
       would be "pl".
  
--- 38,48 ----
       The tree_code for this operator.  For `operator +', for example,
       this would be PLUS_EXPR.  Because there are no tree codes for
       assignment operators, the same tree-codes are reused; i.e.,
       `operator +' will also have PLUS_EXPR as its CODE.
  
!    MANGLING
  
       The mangling prefix for the operator, as a C string, and as
       mangled under the new ABI.  For `operator +', for example, this
       would be "pl".
  
*************** DEF_SIMPLE_OPERATOR (",", COMPOUND_EXPR,
*** 125,135 ****
  DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2)
  DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2)
  DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2)
  DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2)
  DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", 2)
! /* These are extensions.  */
  DEF_SIMPLE_OPERATOR ("<?", MIN_EXPR, "v23min", 2)
  DEF_SIMPLE_OPERATOR (">?", MAX_EXPR, "v23max", 2)
  /* This one is needed for mangling.  */
  DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", 2);
  
--- 125,135 ----
  DEF_SIMPLE_OPERATOR ("->*", MEMBER_REF, "pm", 2)
  DEF_SIMPLE_OPERATOR ("->", COMPONENT_REF, "pt", 2)
  DEF_SIMPLE_OPERATOR ("[]", ARRAY_REF, "ix", 2)
  DEF_SIMPLE_OPERATOR ("++", POSTINCREMENT_EXPR, "pp", 2)
  DEF_SIMPLE_OPERATOR ("--", POSTDECREMENT_EXPR, "mm", 2)
! /* These operators are GNU extensions.  */
  DEF_SIMPLE_OPERATOR ("<?", MIN_EXPR, "v23min", 2)
  DEF_SIMPLE_OPERATOR (">?", MAX_EXPR, "v23max", 2)
  /* This one is needed for mangling.  */
  DEF_SIMPLE_OPERATOR ("::", SCOPE_REF, "sr", 2);
  
*************** DEF_ASSN_OPERATOR ("%=", TRUNC_MOD_EXPR,
*** 143,152 ****
--- 143,155 ----
  DEF_ASSN_OPERATOR ("&=", BIT_AND_EXPR, "aN", 2)
  DEF_ASSN_OPERATOR ("|=", BIT_IOR_EXPR, "oR", 2)
  DEF_ASSN_OPERATOR ("^=", BIT_XOR_EXPR, "eO", 2)
  DEF_ASSN_OPERATOR ("<<=", LSHIFT_EXPR, "lS", 2)
  DEF_ASSN_OPERATOR (">>=", RSHIFT_EXPR, "rS", 2)
+ /* These operators are GNU extensions.  */
+ DEF_ASSN_OPERATOR ("<?=", MIN_EXPR, "v23miN", 2);
+ DEF_ASSN_OPERATOR (">?=", MAX_EXPR, "v23maX", 2);
  
  /* Ternary operators.  */
  DEF_SIMPLE_OPERATOR ("?:", COND_EXPR, "qu", 3)
  
  /* Miscellaneous.  */
Index: testsuite/g++.dg/ext/max.C
===================================================================
RCS file: testsuite/g++.dg/ext/max.C
diff -N testsuite/g++.dg/ext/max.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/ext/max.C	4 Feb 2003 07:12:25 -0000
***************
*** 0 ****
--- 1,6 ----
+ struct s_t { 
+ };
+ void foo(void) {
+   s_t s; int i;
+   s<?=i; // { dg-error "" }
+ }


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