Commit ec835fb2 by Mark Mitchell Committed by Mark Mitchell

re PR c++/14586 (Bogus warning in templates about taking address of a temporary in a template)

	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
parent 1e0f07d3
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> 2004-03-15 Kazu Hirata <kazu@cs.umass.edu>
* cp-lang.c, ptree.c: Update copyright. * cp-lang.c, ptree.c: Update copyright.
......
...@@ -3555,7 +3555,8 @@ add_candidates (tree fns, tree args, ...@@ -3555,7 +3555,8 @@ add_candidates (tree fns, tree args,
} }
tree 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; struct z_candidate *candidates = 0, *cand;
tree arglist, fnname; tree arglist, fnname;
...@@ -3707,7 +3708,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3) ...@@ -3707,7 +3708,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
code = PREINCREMENT_EXPR; code = PREINCREMENT_EXPR;
else else
code = PREDECREMENT_EXPR; 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; break;
/* The caller will deal with these. */ /* 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) ...@@ -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) else if (TREE_CODE (cand->fn) == FUNCTION_DECL)
{ {
if (overloaded_p)
*overloaded_p = true;
if (warn_synth if (warn_synth
&& fnname == ansi_assopname (NOP_EXPR) && fnname == ansi_assopname (NOP_EXPR)
&& DECL_ARTIFICIAL (cand->fn) && DECL_ARTIFICIAL (cand->fn)
......
...@@ -3491,7 +3491,7 @@ extern tree build_new_function_call (tree, tree); ...@@ -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_operator_new_call (tree, tree, tree *, tree *);
extern tree build_new_method_call (tree, tree, tree, tree, int); 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_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 tree build_op_delete_call (enum tree_code, tree, tree, bool, tree);
extern bool can_convert (tree, tree); extern bool can_convert (tree, tree);
extern bool can_convert_arg (tree, tree, tree); extern bool can_convert_arg (tree, tree, tree);
...@@ -4177,7 +4177,8 @@ extern tree build_indirect_ref (tree, const char *); ...@@ -4177,7 +4177,8 @@ extern tree build_indirect_ref (tree, const char *);
extern tree build_array_ref (tree, tree); extern tree build_array_ref (tree, tree);
extern tree get_member_function_from_ptrfunc (tree *, tree); extern tree get_member_function_from_ptrfunc (tree *, tree);
extern tree convert_arguments (tree, tree, tree, int); 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 build_x_unary_op (enum tree_code, tree);
extern tree unary_complex_lvalue (enum tree_code, tree); extern tree unary_complex_lvalue (enum tree_code, tree);
extern tree build_x_conditional_expr (tree, tree, tree); extern tree build_x_conditional_expr (tree, tree, tree);
......
...@@ -380,7 +380,8 @@ grok_array_decl (tree array_expr, tree index_exp) ...@@ -380,7 +380,8 @@ grok_array_decl (tree array_expr, tree index_exp)
/* If they have an `operator[]', use that. */ /* If they have an `operator[]', use that. */
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp))) if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL, expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE); array_expr, index_exp, NULL_TREE,
/*overloaded_p=*/NULL);
else else
{ {
tree p1, p2, i1, i2; tree p1, p2, i1, i2;
......
...@@ -13975,12 +13975,26 @@ cp_parser_binary_expression (cp_parser* parser, ...@@ -13975,12 +13975,26 @@ cp_parser_binary_expression (cp_parser* parser,
++map_node) ++map_node)
if (map_node->token_type == token->type) if (map_node->token_type == token->type)
{ {
/* Assume that an overloaded operator will not be used. */
bool overloaded_p = false;
/* Consume the operator token. */ /* Consume the operator token. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
/* Parse the right-hand side of the expression. */ /* Parse the right-hand side of the expression. */
rhs = (*fn) (parser); rhs = (*fn) (parser);
/* Build the binary tree node. */ /* 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; break;
} }
......
...@@ -8271,7 +8271,8 @@ tsubst_copy_and_build (tree t, ...@@ -8271,7 +8271,8 @@ tsubst_copy_and_build (tree t,
return build_x_binary_op return build_x_binary_op
(TREE_CODE (t), (TREE_CODE (t),
RECUR (TREE_OPERAND (t, 0)), RECUR (TREE_OPERAND (t, 0)),
RECUR (TREE_OPERAND (t, 1))); RECUR (TREE_OPERAND (t, 1)),
/*overloaded_p=*/NULL);
case SCOPE_REF: case SCOPE_REF:
return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true, return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
......
...@@ -1729,7 +1729,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) ...@@ -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))) else if (CLASS_TYPE_P (TREE_TYPE (fn)))
/* If the "function" is really an object of class type, it might /* If the "function" is really an object of class type, it might
have an overloaded `operator ()'. */ 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) if (!result)
/* A call where the function is unknown. */ /* A call where the function is unknown. */
result = build_function_call (fn, args); result = build_function_call (fn, args);
......
...@@ -1493,7 +1493,8 @@ rationalize_conditional_expr (enum tree_code code, tree t) ...@@ -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 build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
? LE_EXPR : GE_EXPR), ? LE_EXPR : GE_EXPR),
TREE_OPERAND (t, 0), 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, 0), 0),
build_unary_op (code, TREE_OPERAND (t, 1), 0)); build_unary_op (code, TREE_OPERAND (t, 1), 0));
} }
...@@ -2026,7 +2027,7 @@ build_x_indirect_ref (tree expr, const char *errorstring) ...@@ -2026,7 +2027,7 @@ build_x_indirect_ref (tree expr, const char *errorstring)
} }
rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE, rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
NULL_TREE); NULL_TREE, /*overloaded_p=*/NULL);
if (!rval) if (!rval)
rval = build_indirect_ref (expr, errorstring); rval = build_indirect_ref (expr, errorstring);
...@@ -2653,7 +2654,8 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags) ...@@ -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. */ conversions on the operands. CODE is the kind of expression to build. */
tree 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_arg1;
tree orig_arg2; tree orig_arg2;
...@@ -2674,7 +2676,8 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2) ...@@ -2674,7 +2676,8 @@ build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
if (code == DOTSTAR_EXPR) if (code == DOTSTAR_EXPR)
expr = build_m_component_ref (arg1, arg2); expr = build_m_component_ref (arg1, arg2);
else 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) if (processing_template_decl && expr != error_mark_node)
return build_min_non_dep (code, expr, orig_arg1, orig_arg2); 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) ...@@ -3531,7 +3534,8 @@ build_x_unary_op (enum tree_code code, tree xarg)
|| (TREE_CODE (xarg) == OFFSET_REF))) || (TREE_CODE (xarg) == OFFSET_REF)))
/* Don't look for a function. */; /* Don't look for a function. */;
else 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) if (!exp && code == ADDR_EXPR)
{ {
/* A pointer to member-function can be formed only by saying /* A pointer to member-function can be formed only by saying
...@@ -4371,7 +4375,8 @@ build_x_compound_expr (tree op1, tree op2) ...@@ -4371,7 +4375,8 @@ build_x_compound_expr (tree op1, tree op2)
op2 = build_non_dependent_expr (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) if (!result)
result = build_compound_expr (op1, op2); result = build_compound_expr (op1, op2);
...@@ -5065,7 +5070,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) ...@@ -5065,7 +5070,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
else else
{ {
result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, 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) if (result == NULL_TREE)
return error_mark_node; return error_mark_node;
return result; return result;
...@@ -5232,7 +5238,8 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) ...@@ -5232,7 +5238,8 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
if (modifycode != NOP_EXPR) if (modifycode != NOP_EXPR)
{ {
tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
make_node (modifycode)); make_node (modifycode),
/*overloaded_p=*/NULL);
if (rval) if (rval)
return rval; return rval;
} }
......
...@@ -1091,7 +1091,8 @@ build_x_arrow (tree expr) ...@@ -1091,7 +1091,8 @@ build_x_arrow (tree expr)
if (IS_AGGR_TYPE (type)) if (IS_AGGR_TYPE (type))
{ {
while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr, 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) if (expr == error_mark_node)
return error_mark_node; return error_mark_node;
......
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> 2004-03-16 Paolo Bonzini <bonzini@gnu.org>
* g++.dg/eh/simd-1.C: Use vector_size attribute, not mode. * g++.dg/eh/simd-1.C: Use vector_size attribute, not mode.
......
// 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> ();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment