re PR c++/49118 (Endless operator-> chain causes infinite loop)
authorDavid Krauss <potswa@mac.com>
Fri, 10 Jun 2011 05:18:36 +0000 (05:18 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 10 Jun 2011 05:18:36 +0000 (01:18 -0400)
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

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/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/arrow1.C [new file with mode: 0644]

index e134c27..dcea35a 100644 (file)
@@ -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.
index d955b63..4ee0eaf 100644 (file)
@@ -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;
 }
index ce2af00..f7bcd0d 100644 (file)
@@ -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,
index a0512cd..8eee458 100644 (file)
@@ -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;
index 35f8957..961f9fe 100644 (file)
@@ -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.  */
index ac150ce..814a08f 100644 (file)
@@ -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:
index 8e4fd42..1bed291 100644 (file)
@@ -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)
        {
index f291393..fa64d1d 100644 (file)
@@ -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);
index d93c01a..a1e9ae2 100644 (file)
@@ -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 (file)
index 0000000..c961410
--- /dev/null
@@ -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" }