]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/7129 (ICE with min/max assignment operators (<?= and >?=))
authorMark Mitchell <mark@codesourcery.com>
Tue, 4 Feb 2003 07:23:14 +0000 (07:23 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 4 Feb 2003 07:23:14 +0000 (07:23 +0000)
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 >?=.

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

From-SVN: r62370

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/operators.def
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/max.C [new file with mode: 0644]

index f3761581b7187b1253ef2a751e0e5325bed330dc..78017c3ba5a0f143bb2b8472437c7451b26eee17 100644 (file)
@@ -1,3 +1,23 @@
+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-01  Richard Sandiford  <rsandifo@redhat.com>
 
        * typeck.c (build_indirect_ref): Don't check flag_volatile.
index 440d58a0a22e90b6221264077711bac67811fc6f..5a2f8f18a7dc832aad78ff592b3890f00e7044da 100644 (file)
@@ -44,7 +44,7 @@ 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_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)
@@ -92,7 +92,7 @@ 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);
+        (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);
@@ -104,6 +104,8 @@ 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)
@@ -556,6 +558,8 @@ 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;
@@ -1034,6 +1038,12 @@ convert_class_to_reference (tree t, tree s, tree expr)
   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);
@@ -1269,11 +1279,12 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
     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)
+    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);
@@ -1283,9 +1294,10 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
       /* 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 conv;
+  return NULL_TREE;
 }
 
 /* Add a new entry to the list of candidates.  Used by the add_*_candidate
@@ -1293,13 +1305,14 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
 
 static struct z_candidate *
 add_candidate (struct z_candidate *candidates, 
-              tree fn, tree convs, tree access_path, tree
-              conversion_path, int viable)
+              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;
@@ -1326,6 +1339,7 @@ add_function_candidate (struct z_candidate *candidates,
   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
@@ -1333,8 +1347,11 @@ add_function_candidate (struct z_candidate *candidates,
   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);
@@ -1432,7 +1449,7 @@ add_function_candidate (struct z_candidate *candidates,
     }
 
  out:
-  return add_candidate (candidates, fn, convs, access_path,
+  return add_candidate (candidates, fn, orig_arglist, convs, access_path,
                        conversion_path, viable);
 }
 
@@ -1509,7 +1526,7 @@ add_conv_candidate (struct z_candidate *candidates, tree fn, tree obj,
   if (!sufficient_parms_p (parmnode))
     viable = 0;
 
-  return add_candidate (candidates, totype, convs, access_path,
+  return add_candidate (candidates, totype, arglist, convs, access_path,
                        conversion_path, viable);
 }
 
@@ -1556,7 +1573,7 @@ build_builtin_candidate (struct z_candidate *candidates, tree fnname,
        viable = 0;
     }      
 
-  return add_candidate (candidates, fnname, convs, 
+  return add_candidate (candidates, fnname, /*args=*/NULL_TREE, convs, 
                        /*access_path=*/NULL_TREE,
                        /*conversion_path=*/NULL_TREE,
                        viable);
@@ -2396,7 +2413,6 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
   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
@@ -2438,16 +2454,13 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
        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);
-       }
+       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), 
@@ -2487,15 +2500,12 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
             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);
-           } 
+           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,
@@ -2695,7 +2705,6 @@ build_new_function_call (tree fn, tree args)
       || TREE_CODE (fn) == TEMPLATE_DECL)
     {
       tree t1;
-      tree templates = NULL_TREE;
 
       args = resolve_args (args);
 
@@ -2709,14 +2718,11 @@ build_new_function_call (tree fn, tree args)
          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);  
-           }
+           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, 
@@ -2745,7 +2751,7 @@ build_new_function_call (tree fn, tree args)
          return error_mark_node;
        }
 
-      return build_over_call (cand, args, LOOKUP_NORMAL);
+      return build_over_call (cand, LOOKUP_NORMAL);
     }
 
   /* This is not really overloaded.  */
@@ -2787,14 +2793,12 @@ build_object_call (tree obj, tree args)
        {
          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);
-           }
+           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),
@@ -2855,7 +2859,7 @@ build_object_call (tree obj, tree args)
      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);
+    return build_over_call (cand, LOOKUP_NORMAL);
 
   obj = convert_like_with_context
           (TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1);
@@ -3317,13 +3321,78 @@ prep_operand (tree operand)
   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 fns, mem_arglist = NULL_TREE, arglist, fnname;
+  tree arglist, fnname;
+  tree args[3];
   enum tree_code code2 = NOP_EXPR;
-  tree templates = NULL_TREE;
   tree conv;
   bool viable_candidates;
 
@@ -3385,98 +3454,45 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
     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))
+  /* 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 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);
-    }
+      tree fns;
 
-  if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
-    {
       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);
     }
-  else
-    fns = NULL_TREE;
 
-  if (fns)
+  /* 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)
     {
-      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);
-       }
+      args[0] = arg2;
+      args[1] = arg3;
+      args[2] = arg1;
+    }
+  else
+    {
+      args[0] = arg1;
+      args[1] = arg2;
+      args[2] = NULL_TREE;
     }
 
-  {
-    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);
-  }
+  candidates = add_builtin_candidates
+    (candidates, code, code2, fnname, args, flags);
 
   switch (code)
     {
@@ -3559,11 +3575,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
                         : candidates->fn);
        }
 
-      return build_over_call
-       (cand,
-        TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
-        ? mem_arglist : arglist,
-        LOOKUP_NORMAL);
+      return build_over_call (cand, LOOKUP_NORMAL);
     }
 
   /* Check for comparison of different enum types.  */
@@ -3907,7 +3919,7 @@ convert_like_real (tree convs, tree expr, tree fn, int argnum, int inner)
          }
        else
          args = build_this (expr);
-       expr = build_over_call (cand, args, LOOKUP_NORMAL);
+       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.  */
@@ -4238,9 +4250,10 @@ convert_for_arg_passing (tree type, tree val)
    bitmask of various LOOKUP_* flags which apply to the call itself.  */
 
 static tree
-build_over_call (struct z_candidate *cand, tree args, int flags)
+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));
@@ -4702,7 +4715,6 @@ build_new_method_call (tree instance, tree fns, tree args,
   tree mem_args = NULL_TREE, instance_ptr;
   tree name;
   tree user_args;
-  tree templates = NULL_TREE;
   tree call;
   tree fn;
   tree class_type;
@@ -4807,7 +4819,6 @@ build_new_method_call (tree instance, tree fns, tree 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,
@@ -4888,10 +4899,10 @@ build_new_method_call (tree instance, tree fns, tree args,
     flags |= LOOKUP_NONVIRTUAL;
 
   if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE)
-    call = build_over_call (cand, mem_args, flags);
+    call = build_over_call (cand, flags);
   else
     {
-      call = build_over_call (cand, args, flags);
+      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))
index d5896ab1856a7134385be3fa7acda52505260c9f..98e317409287564df29f7d0c761a1e5b691b830e 100644 (file)
@@ -5,7 +5,7 @@
    non-overloadable operators (like the `?:' ternary operator).  
    Written by Mark Mitchell <mark@codesourcery.com>
 
-   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -40,7 +40,7 @@ Boston, MA 02111-1307, USA.  */
      assignment operators, the same tree-codes are reused; i.e.,
      `operator +' will also have PLUS_EXPR as its CODE.
 
-   NEW_MANGLING
+   MANGLING
 
      The mangling prefix for the operator, as a C string, and as
      mangled under the new ABI.  For `operator +', for example, this
@@ -127,7 +127,7 @@ 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.  */
+/* 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.  */
@@ -145,6 +145,9 @@ 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)
index 3287f358a34533e2fbfd7263b4555818b70cf034..6ed5733aa2126134af06f2bf25513468f7e048cb 100644 (file)
@@ -1,3 +1,8 @@
+2003-02-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/7129
+       * testsuite/g++.dg/ext/max.C: New test.
+
 Mon Feb  3 16:05:11 CET 2003  Jan Hubicka  <jh@suse.cz>
 
        * gcc.c-torture/execute/20030203-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/ext/max.C b/gcc/testsuite/g++.dg/ext/max.C
new file mode 100644 (file)
index 0000000..bc65f1f
--- /dev/null
@@ -0,0 +1,6 @@
+struct s_t { 
+};
+void foo(void) {
+  s_t s; int i;
+  s<?=i; // { dg-error "" }
+}