This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] Fix PR c++/22508 ICE after invalid operator new


Mark Mitchell wrote:
> Volker Reichelt wrote:
> > Consider the testcase
> > 
> >   struct A
> >   {
> >     void* operator new(__SIZE_TYPE__) throw(X);
> >   };
> > 
> >   A* p = new A;
> 
> I rather think we should fix this by just ignoring the exception 
> specification on the operator when its invalid.

This is actually what happens - sort of:
The function cp_parser_exception_specification_opt calls
cp_parser_type_id_list which in turn calls cp_parser_type_id to
parse a type. Since X is not a type, this fails and we end up with
an empty exception specification (which is good). Alas the parser thinks
that the exception specification should have ended before the X - as
indicated by the following error message before the segfault:

  PR22508.cc:3: error: expected type-specifier before 'X'
  PR22508.cc:3: error: expected `)' before 'X'
  PR22508.cc:3: error: expected ';' before 'X'

We then have a superfluous "X)" before the ";" in the token stream.
And that's why the function is finally rejected. This can be demonstrated
by the following code snippet without exception specification that also
crashes:

  struct A
  {
    void* operator new(__SIZE_TYPE__) X;
  };

  A* p = new A;

PR22508A.cc:3: error: expected ';' before 'X'
PR22508A.cc:6: internal compiler error: Segmentation fault

One option would be to complain about superfluous tokens before the ";"
but otherwise ignore them. This could be done with the following patch.

===================================================================
--- gcc/gcc/cp/parser.c	2 Jul 2005 13:19:38 -0000	1.346
+++ gcc/gcc/cp/parser.c	5 Aug 2005 23:03:06 -0000
@@ -13541,8 +13541,6 @@ cp_parser_member_declaration (cp_parser*
 	      cp_parser_error (parser, "expected %<;%>");
 	      /* Skip tokens until we find a `;'.  */
 	      cp_parser_skip_to_end_of_statement (parser);
-
-	      break;
 	    }
 
 	  if (decl)
===================================================================

The patch causes two regressions in the testsuite: In one case
(g++.dg/parse/crash11.C) we'd generate less errors and in the second
case (g++.dg/tc1/dr176.C) we'd generate more errors.

One could also conditionalize the above break statement on the type of the
current declaration: A function declaration with its parentheses seems to
have more structure than a type declaration. Therefore one might be
confident that one really saw a function declaration plus garbage if there
are superfluous tokens before the ";". So 

  if (TREE_CODE (decl) != FUNCTION_DECL)
    break;

might be a sensible choice.

What do you suggest? Using the original patch, or removing the "break",
or conditionalizing the "break"? Or something completely different?

> The problem with keeping around invalid trees is that it's so easy to 
> fall over them.  I think that we should try to work in the direction 
> that whatever trees we keep are actually reasonable, rather than full of 
> error_mark_nodes.

In theory I agree, in practice there are so many ways to write invalid
C++ programs that this is a difficult task which
a) is often not worth the hassle (and the bloat)
b) can make error messages even worse - if the compiler is trying to be
   smart and starts guessing what the user intended although something
   completely different was intended. This usually srews up follow-up
   messages completely.

Regards,
Volker



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]