diff options
author | David Krauss <potswa@mac.com> | 2011-06-10 05:18:36 +0000 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-06-10 01:18:36 -0400 |
commit | 6904f4b401d50c17b1a0dbd6eac64212700973fa (patch) | |
tree | cf32c9ad430552e602f47206b7f64bdc57c16863 /gcc | |
parent | 0dbe3777353ae62281f913cfc5df518d1dce98c7 (diff) | |
download | gcc-6904f4b401d50c17b1a0dbd6eac64212700973fa.zip gcc-6904f4b401d50c17b1a0dbd6eac64212700973fa.tar.gz gcc-6904f4b401d50c17b1a0dbd6eac64212700973fa.tar.bz2 |
re PR c++/49118 (Endless operator-> chain causes infinite loop)
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.
From-SVN: r174889
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/call.c | 12 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 12 | ||||
-rw-r--r-- | gcc/cp/pt.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 18 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/arrow1.C | 17 |
10 files changed, 69 insertions, 28 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e134c27..dcea35a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d955b63..4ee0eaf 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4791,7 +4791,7 @@ avoid_sign_compare_warnings (tree orig_arg, tree arg) 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; @@ -4958,7 +4958,7 @@ build_new_op_1 (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, 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. */ @@ -5005,8 +5005,8 @@ build_new_op_1 (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 (overload) + *overload = cand->fn; if (resolve_args (arglist, complain) == NULL) result = error_mark_node; @@ -5165,11 +5165,11 @@ build_new_op_1 (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, 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; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ce2af00..f7bcd0d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4717,7 +4717,7 @@ extern tree build_new_method_call (tree, tree, VEC(tree,gc) **, 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); @@ -5611,7 +5611,7 @@ extern tree cp_build_function_call_vec (tree, VEC(tree,gc) **, 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, diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a0512cd..8eee458 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -361,7 +361,7 @@ grok_array_decl (tree array_expr, tree index_exp) 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; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 35f8957..961f9fe 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6585,7 +6585,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, 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); @@ -6688,7 +6688,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, 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 @@ -6703,7 +6703,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, 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, @@ -6712,7 +6712,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, 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; @@ -24245,8 +24245,6 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl) { 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)) { @@ -24275,7 +24273,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl) 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. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ac150ce..814a08f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12753,7 +12753,7 @@ tsubst_copy_and_build (tree t, (TREE_NO_WARNING (TREE_OPERAND (t, 1)) ? ERROR_MARK : TREE_CODE (TREE_OPERAND (t, 1))), - /*overloaded_p=*/NULL, + /*overload=*/NULL, complain); case SCOPE_REF: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 8e4fd42..1bed291 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2035,7 +2035,7 @@ rationalize_conditional_expr (enum tree_code code, tree t, ? 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), @@ -2689,7 +2689,7 @@ build_x_indirect_ref (tree expr, ref_operator errorstring, } 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); @@ -3497,7 +3497,7 @@ convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl, 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; @@ -3520,7 +3520,7 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code, 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 @@ -3560,7 +3560,7 @@ build_x_array_ref (tree arg1, tree arg2, tsubst_flags_t complain) } 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, @@ -4558,7 +4558,7 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain) /* 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)) @@ -5545,7 +5545,7 @@ build_x_compound_expr (tree op1, tree op2, tsubst_flags_t complain) } 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); @@ -6650,7 +6650,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, { 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; @@ -6833,7 +6833,7 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, { tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, make_node (modifycode), - /*overloaded_p=*/NULL, + /*overload=*/NULL, complain); if (rval) { diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index f291393..fa64d1d 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1429,14 +1429,20 @@ build_x_arrow (tree expr) 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"); @@ -1447,6 +1453,9 @@ build_x_arrow (tree expr) 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d93c01a..a1e9ae2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +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. diff --git a/gcc/testsuite/g++.dg/template/arrow1.C b/gcc/testsuite/g++.dg/template/arrow1.C new file mode 100644 index 0000000..c961410 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/arrow1.C @@ -0,0 +1,17 @@ +// 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" } |