re PR c++/14586 (Bogus warning in templates about taking address of a temporary in...
authorMark Mitchell <mark@codesourcery.com>
Tue, 16 Mar 2004 22:18:11 +0000 (22:18 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 16 Mar 2004 22:18:11 +0000 (22:18 +0000)
PR c++/14586
* cp-tree.h (build_new_op): Change prototype.
(build_x_binary_op): Likewise.
* call.c (build_new_op): Add overloaded_p parameter.
* decl2.c (grok_array_decl): Adjust call to build_new_op.
* parser.c (cp_parser_binary_expression): Note that uses of
overloaded operators prevents an expression from being considered
an integral constant.
* pt.c (tsubst_copy_and_build): Adjust calls to build_new_op and/or
build_x_binary_op.
* semantics.c (finish_call_expr): Likewise.
* typeck.c (rationalize_conditional_expr): Likewise.
(build_x_indirect_ref): Likewise.
(build_x_binary_op): Likewise.
(build_x_unary_op): Likewise.
(build_x_compound_expr): Likewise.
(build_modify_expr): Likewise.
* typeck2.c (build_x_arrow): Likewise.

PR c++/14586
* g++.dg/parse/non-dependent3.C: New test.

From-SVN: r79553

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/non-dependent3.C [new file with mode: 0644]

index 3b4ae33..408fa1c 100644 (file)
@@ -1,3 +1,24 @@
+2004-03-16  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/14586
+       * cp-tree.h (build_new_op): Change prototype.
+       (build_x_binary_op): Likewise.
+       * call.c (build_new_op): Add overloaded_p parameter.
+       * decl2.c (grok_array_decl): Adjust call to build_new_op.
+       * parser.c (cp_parser_binary_expression): Note that uses of
+       overloaded operators prevents an expression from being considered
+       an integral constant.
+       * pt.c (tsubst_copy_and_build): Adjust calls to build_new_op and/or
+       build_x_binary_op.
+       * semantics.c (finish_call_expr): Likewise.
+       * typeck.c (rationalize_conditional_expr): Likewise.
+       (build_x_indirect_ref): Likewise.
+       (build_x_binary_op): Likewise.
+       (build_x_unary_op): Likewise.
+       (build_x_compound_expr): Likewise.
+       (build_modify_expr): Likewise.
+       * typeck2.c (build_x_arrow): Likewise.
+
 2004-03-15  Kazu Hirata  <kazu@cs.umass.edu>
 
        * cp-lang.c, ptree.c: Update copyright.
index 4eeb5e5..62182f3 100644 (file)
@@ -3555,7 +3555,8 @@ add_candidates (tree fns, tree args,
 }
 
 tree
-build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
+build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
+             bool *overloaded_p)
 {
   struct z_candidate *candidates = 0, *cand;
   tree arglist, fnname;
@@ -3707,7 +3708,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
            code = PREINCREMENT_EXPR;
          else
            code = PREDECREMENT_EXPR;   
-         result = build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE);
+         result = build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE,
+                                overloaded_p);
          break;
 
          /* The caller will deal with these.  */
@@ -3742,6 +3744,9 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
        }
       else if (TREE_CODE (cand->fn) == FUNCTION_DECL)
        {
+         if (overloaded_p)
+           *overloaded_p = true;
+
          if (warn_synth
              && fnname == ansi_assopname (NOP_EXPR)
              && DECL_ARTIFICIAL (cand->fn)
index 6ccfcc8..16e0abe 100644 (file)
@@ -3491,7 +3491,7 @@ extern tree build_new_function_call (tree, tree);
 extern tree build_operator_new_call (tree, tree, tree *, tree *);
 extern tree build_new_method_call (tree, tree, tree, tree, int);
 extern tree build_special_member_call (tree, tree, tree, tree, int);
-extern tree build_new_op (enum tree_code, int, tree, tree, tree);
+extern tree build_new_op (enum tree_code, int, tree, tree, tree, bool *);
 extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree);
 extern bool can_convert (tree, tree);
 extern bool can_convert_arg (tree, tree, tree);
@@ -4177,7 +4177,8 @@ extern tree build_indirect_ref                    (tree, const char *);
 extern tree build_array_ref                    (tree, tree);
 extern tree get_member_function_from_ptrfunc   (tree *, tree);
 extern tree convert_arguments                  (tree, tree, tree, int);
-extern tree build_x_binary_op                  (enum tree_code, tree, tree);
+extern tree build_x_binary_op                  (enum tree_code, tree, tree, 
+                                                bool *);
 extern tree build_x_unary_op                   (enum tree_code, tree);
 extern tree unary_complex_lvalue               (enum tree_code, tree);
 extern tree build_x_conditional_expr           (tree, tree, tree);
index 7310d09..baf1adf 100644 (file)
@@ -380,7 +380,8 @@ grok_array_decl (tree array_expr, tree index_exp)
   /* If they have an `operator[]', use that.  */
   if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
     expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
-                        array_expr, index_exp, NULL_TREE);
+                        array_expr, index_exp, NULL_TREE,
+                        /*overloaded_p=*/NULL);
   else
     {
       tree p1, p2, i1, i2;
index 20588b0..db40252 100644 (file)
@@ -13975,12 +13975,26 @@ cp_parser_binary_expression (cp_parser* parser,
           ++map_node)
        if (map_node->token_type == token->type)
          {
+           /* Assume that an overloaded operator will not be used.  */
+           bool overloaded_p = false;
+
            /* Consume the operator token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Parse the right-hand side of the expression.  */
            rhs = (*fn) (parser);
            /* Build the binary tree node.  */
-           lhs = build_x_binary_op (map_node->tree_type, lhs, rhs);
+           lhs = build_x_binary_op (map_node->tree_type, lhs, rhs, 
+                                    &overloaded_p);
+           /* If the binary operator required the use of an
+              overloaded operator, then this expression cannot be an
+              integral constant-expression.  An overloaded operator
+              can be used even if both operands are otherwise
+              permissible in an integral constant-expression if at
+              least one of the operands is of enumeration type.  */
+           if (overloaded_p
+               && (cp_parser_non_integral_constant_expression 
+                   (parser, "calls to overloaded operators")))
+             lhs = error_mark_node;
            break;
          }
 
index 45fa012..6001b1c 100644 (file)
@@ -8271,7 +8271,8 @@ tsubst_copy_and_build (tree t,
       return build_x_binary_op
        (TREE_CODE (t), 
         RECUR (TREE_OPERAND (t, 0)),
-        RECUR (TREE_OPERAND (t, 1)));
+        RECUR (TREE_OPERAND (t, 1)),
+        /*overloaded_p=*/NULL);
 
     case SCOPE_REF:
       return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
index b7a7f4a..9142a2c 100644 (file)
@@ -1729,7 +1729,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
   else if (CLASS_TYPE_P (TREE_TYPE (fn)))
     /* If the "function" is really an object of class type, it might
        have an overloaded `operator ()'.  */
-    result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE);
+    result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE,
+                          /*overloaded_p=*/NULL);
   if (!result)
     /* A call where the function is unknown.  */
     result = build_function_call (fn, args);
index b7a66c2..31ca3e0 100644 (file)
@@ -1493,7 +1493,8 @@ rationalize_conditional_expr (enum tree_code code, tree t)
        build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
                                                    ? LE_EXPR : GE_EXPR),
                                                   TREE_OPERAND (t, 0),
-                                                  TREE_OPERAND (t, 1)),
+                                                  TREE_OPERAND (t, 1),
+                                                  /*overloaded_p=*/NULL),
                            build_unary_op (code, TREE_OPERAND (t, 0), 0),
                            build_unary_op (code, TREE_OPERAND (t, 1), 0));
     }
@@ -2026,7 +2027,7 @@ build_x_indirect_ref (tree expr, const char *errorstring)
     }
 
   rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
-                      NULL_TREE);
+                      NULL_TREE, /*overloaded_p=*/NULL);
   if (!rval)
     rval = build_indirect_ref (expr, errorstring);
 
@@ -2653,7 +2654,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
    conversions on the operands.  CODE is the kind of expression to build.  */
 
 tree
-build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
+build_x_binary_op (enum tree_code code, tree arg1, tree arg2, 
+                  bool *overloaded_p)
 {
   tree orig_arg1;
   tree orig_arg2;
@@ -2674,7 +2676,8 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
   if (code == DOTSTAR_EXPR)
     expr = build_m_component_ref (arg1, arg2);
   else
-    expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
+    expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, 
+                        overloaded_p);
 
   if (processing_template_decl && expr != error_mark_node)
     return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
@@ -3531,7 +3534,8 @@ build_x_unary_op (enum tree_code code, tree xarg)
          || (TREE_CODE (xarg) == OFFSET_REF)))
     /* Don't look for a function.  */;
   else
-    exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE);
+    exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
+                       /*overloaded_p=*/NULL);
   if (!exp && code == ADDR_EXPR)
     {
       /*  A pointer to member-function can be formed only by saying
@@ -4371,7 +4375,8 @@ build_x_compound_expr (tree op1, tree op2)
       op2 = build_non_dependent_expr (op2);
     }
 
-  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE);
+  result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE,
+                        /*overloaded_p=*/NULL);
   if (!result)
     result = build_compound_expr (op1, op2);
 
@@ -5065,7 +5070,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
          else
            {
              result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
-                                    lhs, rhs, make_node (NOP_EXPR));
+                                    lhs, rhs, make_node (NOP_EXPR),
+                                    /*overloaded_p=*/NULL);
              if (result == NULL_TREE)
                return error_mark_node;
              return result;
@@ -5232,7 +5238,8 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
   if (modifycode != NOP_EXPR)
     {
       tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
-                               make_node (modifycode));
+                               make_node (modifycode),
+                               /*overloaded_p=*/NULL);
       if (rval)
        return rval;
     }
index 4687486..6314456 100644 (file)
@@ -1091,7 +1091,8 @@ build_x_arrow (tree expr)
   if (IS_AGGR_TYPE (type))
     {
       while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
-                                  NULL_TREE, NULL_TREE)))
+                                  NULL_TREE, NULL_TREE,
+                                  /*overloaded_p=*/NULL)))
        {
          if (expr == error_mark_node)
            return error_mark_node;
index 62764c2..09f98bf 100644 (file)
@@ -1,3 +1,8 @@
+2004-03-16  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/14586
+       * g++.dg/parse/non-dependent3.C: New test.
+
 2004-03-16  Paolo Bonzini  <bonzini@gnu.org>
 
        * g++.dg/eh/simd-1.C: Use vector_size attribute, not mode.
diff --git a/gcc/testsuite/g++.dg/parse/non-dependent3.C b/gcc/testsuite/g++.dg/parse/non-dependent3.C
new file mode 100644 (file)
index 0000000..9dfb996
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/14586
+
+enum E { e }; 
+E & operator |= (E &f1, const E &f2); 
+E operator | (const E &f1, const E &f2) { 
+  E result = f1; 
+  result |= f2; 
+  return result; 
+} 
+template <typename> void foo () { 
+  const E flags = e | e; 
+} 
+template void foo<double> ();