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]

[patch] Fix PR c++/28606: Destructor accepted as return-type of constructor


The following invalid code snippet is accepted since GCC 4.0.0:

  struct A
  {
    ~A A();
  };

Even worse, the following code snippet is accepted, too:

  struct B;

  struct A
  {
    A::~B A();
  };

The problem is two-fold: The first testcase is accepted because
cp_parser_parse_and_diagnose_invalid_type_name does not handle
BIT_NOT_EXPRs (destructors) correctly and accepts them as type.

This is fixed by making the test for valid types more strict in
cp_parser_parse_and_diagnose_invalid_type_name (hunk #2 of the
patch) and by handling BIT_NOT_EXPRs as invalid types in
cp_parser_diagnose_invalid_type_name (hunk #1).

In the second testcase the destructor is correctly found to be
invalid. However, no diagnostic is issues as we are parsing
tentatively. The problem is that the parser isn't notified that a
problem occured. Hence the invalid destructor is accepted after all.
This problem is fixed by adding a call to cp_parser_simulate_error
(hunk #4).

A couple of lines above another call to cp_parser_simulate_error
was missing (hunk #3).

The code in hunk #3 was recently added by me to fix PR 27508.
I had some issues with invalid code that was accepted. With the
call to cp_parser_skip_to_end_of_statement the problems went away.
But as I now know, this only papered over the real problem, i.e.
the missing call to cp_parser_simulate_error.

Consuming the next token after the "~" (if it is a name) should
usually be enough to skip the invalid destructor. This last change
is not necessary for fixing the bugs, but should improve diagnostics
in some cases.

Bootstrapped and regtested on x86_64-unknown-linux-gnu.
Ok for mainline, 4.1 branch, and 4.0 branch?

Regards,
Volker

:ADDPATCH C++:


2006-08-04  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>

	PR c++/28606
	* parser.c (cp_parser_diagnose_invalid_type_name): Handle BIT_NOT_EXPR.
	Fix formatting.
	(cp_parser_parse_and_diagnose_invalid_type_name): Tighten condition
	for valid type-names.
	(cp_parser_unqualified_id): Fix error handling for destructors.

===================================================================
--- gcc/gcc/cp/parser.c	2006-08-04 02:38:34 +0200
+++ gcc/gcc/cp/parser.c	2006-08-04 02:46:26 +0200
@@ -2113,8 +2113,9 @@ cp_parser_diagnose_invalid_type_name
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
-    error ("invalid use of template-name %qE without an argument list",
-      decl);
+    error ("invalid use of template-name %qE without an argument list", decl);
+  else if (TREE_CODE (id) == BIT_NOT_EXPR)
+    error ("invalid use of destructor %qD as a type", id);
   else if (!parser->scope)
     {
       /* Issue an error message.  */
@@ -2207,8 +2208,7 @@ cp_parser_parse_and_diagnose_invalid_typ
       cp_parser_abort_tentative_parse (parser);
       return false;
     }
-  if (!cp_parser_parse_definitely (parser)
-      || TREE_CODE (id) != IDENTIFIER_NODE)
+  if (!cp_parser_parse_definitely (parser) || TREE_CODE (id) == TYPE_DECL)
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
@@ -3385,14 +3385,17 @@ cp_parser_unqualified_id (cp_parser* parser,
 	/* Check for invalid scopes.  */
 	if (scope == error_mark_node)
 	  {
-	    cp_parser_skip_to_end_of_statement (parser);
+	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+	      cp_lexer_consume_token (parser->lexer);
 	    return error_mark_node;
 	  }
 	if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
 	      error ("scope %qT before %<~%> is not a class-name", scope);
-	    cp_parser_skip_to_end_of_statement (parser);
+	    cp_parser_simulate_error (parser);
+	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+	      cp_lexer_consume_token (parser->lexer);
 	    return error_mark_node;
 	  }
 	gcc_assert (!scope || TYPE_P (scope));
@@ -3492,6 +3495,7 @@ cp_parser_unqualified_id (cp_parser* parser,
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
 	      error ("declaration of %<~%T%> as member of %qT",
 		     type_decl, scope);
+	    cp_parser_simulate_error (parser);
 	    return error_mark_node;
 	  }
 
===================================================================

2006-08-04  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>

	PR c++/28606
	* g++.dg/parse/dtor11.C: New test.

===================================================================
--- gcc/gcc/testsuite/g++.dg/parse/dtor11.C	2003-09-23 19:59:22 +0200
+++ gcc/gcc/testsuite/g++.dg/parse/dtor11.C	2006-08-04 02:56:31 +0200
@@ -0,0 +1,12 @@
+// PR c++/28606
+// { dg-do compile }
+
+struct A
+{
+  ~A A();     // { dg-error "destructor" }
+};
+
+struct B
+{
+  A::~B B();  // { dg-error "as member of" }
+};
===================================================================



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