+2011-06-09 David Krauss <potswa@mac.com>
+
+ PR c++/49118
+ * typeck2.c (build_x_arrow): Push fake template context
+ to produce diagnostic on acyclic endless operator-> drill-down.
+ * call.c (build_new_op): Change Boolean overload status
+ value to a pointer to the overload function.
+ * cp-tree.h: Likewise.
+ * typeck.c: Likewise.
+ * parser.c: Likewise.
+ * decl2.c: Likewise.
+ * pt.c: Likewise.
+
2011-06-09 Jason Merrill <jason@redhat.com>
* semantics.c (maybe_constant_value): Handle overflowed input.
static tree
build_new_op_1 (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
- bool *overloaded_p, tsubst_flags_t complain)
+ tree *overload, tsubst_flags_t complain)
{
tree orig_arg1 = arg1;
tree orig_arg2 = arg2;
else
code = PREDECREMENT_EXPR;
result = build_new_op_1 (code, flags, arg1, NULL_TREE, NULL_TREE,
- overloaded_p, complain);
+ overload, complain);
break;
/* The caller will deal with these. */
}
else if (TREE_CODE (cand->fn) == FUNCTION_DECL)
{
- if (overloaded_p)
- *overloaded_p = true;
+ if (overload)
+ *overload = cand->fn;
if (resolve_args (arglist, complain) == NULL)
result = error_mark_node;
tree
build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
- bool *overloaded_p, tsubst_flags_t complain)
+ tree *overload, tsubst_flags_t complain)
{
tree ret;
bool subtime = timevar_cond_start (TV_OVERLOAD);
- ret = build_new_op_1 (code, flags, arg1, arg2, arg3, overloaded_p, complain);
+ ret = build_new_op_1 (code, flags, arg1, arg2, arg3, overload, complain);
timevar_cond_stop (TV_OVERLOAD, subtime);
return ret;
}
extern tree build_special_member_call (tree, tree, VEC(tree,gc) **,
tree, int, tsubst_flags_t);
extern tree build_new_op (enum tree_code, int, tree,
- tree, tree, bool *,
+ tree, tree, tree *,
tsubst_flags_t);
extern tree build_op_call (tree, VEC(tree,gc) **,
tsubst_flags_t);
tsubst_flags_t);
extern tree build_x_binary_op (enum tree_code, tree,
enum tree_code, tree,
- enum tree_code, bool *,
+ enum tree_code, tree *,
tsubst_flags_t);
extern tree build_x_array_ref (tree, tree, tsubst_flags_t);
extern tree build_x_unary_op (enum tree_code, tree,
if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp)))
expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE,
- /*overloaded_p=*/NULL, tf_warning_or_error);
+ /*overload=*/NULL, tf_warning_or_error);
else
{
tree p1, p2, i1, i2;
cp_token *token;
enum tree_code tree_type, lhs_type, rhs_type;
enum cp_parser_prec new_prec, lookahead_prec;
- bool overloaded_p;
+ tree overload;
/* Parse the first expression. */
lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p, pidk);
else if (tree_type == TRUTH_ORIF_EXPR)
c_inhibit_evaluation_warnings -= lhs == truthvalue_true_node;
- overloaded_p = false;
+ overload = NULL;
/* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
ERROR_MARK for everything that is not a binary expression.
This makes warn_about_parentheses miss some warnings that
lhs = build2 (tree_type, boolean_type_node, lhs, rhs);
else
lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
- &overloaded_p, tf_warning_or_error);
+ &overload, tf_warning_or_error);
lhs_type = tree_type;
/* If the binary operator required the use of an overloaded operator,
otherwise permissible in an integral constant-expression if at
least one of the operands is of enumeration type. */
- if (overloaded_p
+ if (overload
&& cp_parser_non_integral_constant_expression (parser,
NIC_OVERLOADED))
return error_mark_node;
{
tree cond = cp_parser_binary_expression (parser, false, true,
PREC_NOT_OPERATOR, NULL);
- bool overloaded_p;
-
if (cond == error_mark_node
|| cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
{
return build_x_binary_op (TREE_CODE (cond),
TREE_OPERAND (cond, 0), ERROR_MARK,
TREE_OPERAND (cond, 1), ERROR_MARK,
- &overloaded_p, tf_warning_or_error);
+ /*overload=*/NULL, tf_warning_or_error);
}
/* Helper function, to parse omp for increment expression. */
(TREE_NO_WARNING (TREE_OPERAND (t, 1))
? ERROR_MARK
: TREE_CODE (TREE_OPERAND (t, 1))),
- /*overloaded_p=*/NULL,
+ /*overload=*/NULL,
complain);
case SCOPE_REF:
? LE_EXPR : GE_EXPR),
op0, TREE_CODE (op0),
op1, TREE_CODE (op1),
- /*overloaded_p=*/NULL,
+ /*overload=*/NULL,
complain),
cp_build_unary_op (code, op0, 0, complain),
cp_build_unary_op (code, op1, 0, complain),
}
rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
- NULL_TREE, /*overloaded_p=*/NULL, complain);
+ NULL_TREE, /*overload=*/NULL, complain);
if (!rval)
rval = cp_build_indirect_ref (expr, errorstring, complain);
tree
build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code,
- tree arg2, enum tree_code arg2_code, bool *overloaded_p,
+ tree arg2, enum tree_code arg2_code, tree *overload,
tsubst_flags_t complain)
{
tree orig_arg1;
expr = build_m_component_ref (arg1, arg2);
else
expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
- overloaded_p, complain);
+ overload, complain);
/* Check for cases such as x+y<<z which users are likely to
misinterpret. But don't warn about obj << x + y, since that is a
}
expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
- /*overloaded_p=*/NULL, complain);
+ /*overload=*/NULL, complain);
if (processing_template_decl && expr != error_mark_node)
return build_min_non_dep (ARRAY_REF, expr, orig_arg1, orig_arg2,
/* Don't look for a function. */;
else
exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
- /*overloaded_p=*/NULL, complain);
+ /*overload=*/NULL, complain);
if (!exp && code == ADDR_EXPR)
{
if (is_overloaded_fn (xarg))
}
result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE,
- /*overloaded_p=*/NULL, complain);
+ /*overload=*/NULL, complain);
if (!result)
result = cp_build_compound_expr (op1, op2, complain);
{
result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
lhs, rhs, make_node (NOP_EXPR),
- /*overloaded_p=*/NULL,
+ /*overload=*/NULL,
complain);
if (result == NULL_TREE)
return error_mark_node;
{
tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
make_node (modifycode),
- /*overloaded_p=*/NULL,
+ /*overload=*/NULL,
complain);
if (rval)
{
if (MAYBE_CLASS_TYPE_P (type))
{
+ struct tinst_level *actual_inst = current_instantiation ();
+ tree fn = NULL;
+
while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr,
NULL_TREE, NULL_TREE,
- /*overloaded_p=*/NULL,
- tf_warning_or_error)))
+ &fn, tf_warning_or_error)))
{
if (expr == error_mark_node)
return error_mark_node;
+ if (fn && DECL_USE_TEMPLATE (fn))
+ push_tinst_level (fn);
+ fn = NULL;
+
if (vec_member (TREE_TYPE (expr), types_memoized))
{
error ("circular pointer delegation detected");
last_rval = expr;
}
+ while (current_instantiation () != actual_inst)
+ pop_tinst_level ();
+
if (last_rval == NULL_TREE)
{
error ("base operand of %<->%> has non-pointer type %qT", type);
+2011-06-09 David Krauss <potswa@mac.com>
+
+ * g++.dg/template/arrow1.C: New.
+
2011-06-09 Jason Merrill <jason@redhat.com>
* lib/prune.exp: Prune "note"s.
--- /dev/null
+// PR c++/49118
+// { dg-do compile }
+
+template< int n >
+struct a {
+ a< n+1 >
+ operator->()
+ { return a< n+1 >(); }
+};
+
+int main() {
+ a<0>()->x; // { dg-error "instantiation depth exceeds maximum" }
+}
+
+// { dg-prune-output "incomplete type" }
+// { dg-prune-output "declaration of" }
+// { dg-prune-output "used but never defined" }