From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26945 invoked by alias); 2 Jun 2011 19:26:03 -0000 Received: (qmail 26917 invoked by uid 22791); 2 Jun 2011 19:26:02 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,T_RP_MATCHES_RCVD,T_TO_NO_BRKTS_FREEMAIL X-Spam-Check-By: sourceware.org Received: from asmtpout021.mac.com (HELO asmtpout021.mac.com) (17.148.16.96) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 02 Jun 2011 19:25:48 +0000 MIME-version: 1.0 Content-type: multipart/mixed; boundary="Boundary_(ID_bNc0pRnDDCEZ1iSwSqxQtQ)" Received: from 224.246.192.25.in-addr.arpa (mc72036d0.tmodns.net [208.54.32.199]) by asmtp021.mac.com (Oracle Communications Messaging Exchange Server 7u4-20.01 64bit (built Nov 21 2010)) with ESMTPSA id <0LM600L1OGMHYT80@asmtp021.mac.com>; Thu, 02 Jun 2011 12:25:39 -0700 (PDT) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.4.6813,1.0.148,0.0.0000 definitions=2011-06-02_07:2011-06-02,2011-06-02,1970-01-01 signatures=0 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 spamscore=0 ipscore=0 suspectscore=4 phishscore=0 bulkscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx engine=6.0.2-1012030000 definitions=main-1106020125 Subject: [PATCH] [Bug c++/49118] fake template nesting for operator-> chain From: David Krauss In-reply-to: Date: Thu, 02 Jun 2011 19:26:00 -0000 Cc: Jason Merrill Message-id: <5902DD14-F11F-49ED-8C86-7DEB076DCC65@mac.com> References: To: gcc-patches@gcc.gnu.org Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-06/txt/msg00186.txt.bz2 --Boundary_(ID_bNc0pRnDDCEZ1iSwSqxQtQ) Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-length: 2106 This is my first frontend contribution. While it fixes the crash and produces an explanatory error message, the message isn't quite right. I don't understand the message generation system so I might need help. Or, it looks like there's an issue with template backtraces at the moment anyway, so there might be an interaction with another known bug. The problem occurs when operator-> drill-down behavior is infinitely chained, for example with a template template< int n > t< n + 1 > t< n >::operator->() There is no cycle to signal endlessness, and no template nesting, as drill-down is implemented as a deep expression, not tail-calls. The result is that the compiler hangs. My solution is to pretend that there is template nesting, presuming the user will find this intuitive. There is the added benefit of the maximum chain length being configured by the template nesting limit. Drill-down is implemented by build_x_arrow. If operator-> resolves, it calls it and uses the result type to lookup another operator->. I'd like to re-open a template context related to operator-> after generating the call. The function push_tinst_level seems to relate only to diagnostics, with no semantic effect, so it seems a good candidate. Optimally the re-opened context would be the preceding operator-> function itself, to create the illusion of nested calls. However, the result of build_new_op may be a target_expr or a call_expr. I'm not sure of the best way to recover the function declaration from this ambiguous tree, nor whether it would a performance issue (i.e., too much work for the reward). The identity of the class containing the *next* operator-> call is easy to recover, however, since it is the type of the expression from build_new_op. This introduces an off-by-one error, and gets us a class template rather than the more relevant function member. These problems shouldn't matter since this is all just for diagnostics. But perhaps the discrepancy between having a function type and a class type is interfering with message generation? Thanks for the help and consideration! --Boundary_(ID_bNc0pRnDDCEZ1iSwSqxQtQ) Content-type: application/octet-stream; name=endless_arrow.clog Content-transfer-encoding: 7bit Content-disposition: attachment; filename=endless_arrow.clog Content-length: 126 * cp/typeck2.c (build_x_arrow): push_tinst_level fake context to produce diagnostic on acyclic endless operator-> drill-down. --Boundary_(ID_bNc0pRnDDCEZ1iSwSqxQtQ) Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-length: 1 --Boundary_(ID_bNc0pRnDDCEZ1iSwSqxQtQ) Content-type: application/octet-stream; name=endless_arrow.patch Content-transfer-encoding: 7bit Content-disposition: attachment; filename=endless_arrow.patch Content-length: 1341 Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 174231) +++ cp/typeck2.c (working copy) @@ -1429,24 +1429,35 @@ build_x_arrow (tree expr) if (MAYBE_CLASS_TYPE_P (type)) { + struct tinst_level *actual_inst = current_instantiation (); + while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr, NULL_TREE, NULL_TREE, /*overloaded_p=*/NULL, tf_warning_or_error))) { + tree chain_type = TREE_TYPE (expr); + if (expr == error_mark_node) return error_mark_node; - if (vec_member (TREE_TYPE (expr), types_memoized)) + if (vec_member (chain_type, types_memoized)) { error ("circular pointer delegation detected"); return error_mark_node; } + + /* For diagnostic purposes, pretend that the chain is nested. */ + if (CLASS_TYPE_P (chain_type) && CLASSTYPE_TEMPLATE_INFO (chain_type)) + push_tinst_level (chain_type); - VEC_safe_push (tree, gc, types_memoized, TREE_TYPE (expr)); + VEC_safe_push (tree, gc, types_memoized, chain_type); 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); --Boundary_(ID_bNc0pRnDDCEZ1iSwSqxQtQ) Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-length: 2 --Boundary_(ID_bNc0pRnDDCEZ1iSwSqxQtQ)--