public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: David Krauss <potswa@mac.com>
To: gcc-patches@gcc.gnu.org
Cc: Jason Merrill <jason@gcc.gnu.org>
Subject: [PATCH] [Bug c++/49118] fake template nesting for operator-> chain
Date: Thu, 02 Jun 2011 19:26:00 -0000	[thread overview]
Message-ID: <5902DD14-F11F-49ED-8C86-7DEB076DCC65@mac.com> (raw)
In-Reply-To: <bug-49118-18186-fnN8jlsJie@http.gcc.gnu.org/bugzilla/>

[-- Attachment #1: Type: text/plain, Size: 2106 bytes --]

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!


[-- Attachment #2: endless_arrow.clog --]
[-- Type: application/octet-stream, Size: 126 bytes --]

* cp/typeck2.c (build_x_arrow): push_tinst_level fake context
to produce diagnostic on acyclic endless operator-> drill-down.

[-- Attachment #3: Type: text/plain, Size: 1 bytes --]



[-- Attachment #4: endless_arrow.patch --]
[-- Type: application/octet-stream, Size: 1341 bytes --]

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);

[-- Attachment #5: Type: text/plain, Size: 2 bytes --]




       reply	other threads:[~2011-06-02 19:26 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <bug-49118-18186@http.gcc.gnu.org/bugzilla/>
     [not found] ` <bug-49118-18186-fnN8jlsJie@http.gcc.gnu.org/bugzilla/>
2011-06-02 19:26   ` David Krauss [this message]
2011-06-06 20:28     ` Jason Merrill
2011-06-09 23:43       ` David Krauss
2011-06-10  3:00         ` Jason Merrill
2011-06-10  3:29           ` David Krauss
2011-06-10  6:50             ` Jason Merrill

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5902DD14-F11F-49ED-8C86-7DEB076DCC65@mac.com \
    --to=potswa@mac.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).