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]

[C++ PATCH] Fix 20789 & 21929


This patch fixes two ICEs,

20789 - the initializer of an in-class static member turned out to be invalid. We ended up setting DECL_INITIAL to an INIT_EXPR and that would cause dependent_expr_p to go into infinite recursion.

21989 - we did not expect parser->scope to be error_mark_node. I tidied up the bits of the parser that seemed broken in this regard.

whilst there I cleaned up cp_parser_skip_to_end_of_block_or_statement. which I found a bit confusing.

booted & tested on i686-pc-linux-gnu, installed mainline. queued for 4.0 (minus the skip_to_end cleanup)

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2005-06-13  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/20789
	* decl.c (cp_finish_decl): Clear runtime runtime initialization if
	in-class decl's initializer is bad.

	PR c++/21929
	* parser.c (struct cp_parser): Document that scope could be
	error_mark.
	(cp_parser_diagnose_invalid_type_name): Cope with error_mark for
	scope.
	(cp_parser_nested_name_specifier): Return NULL_TREE on error.
	(cp_parser_postfix_expression): Deal with null or error_mark
	scope.
	(cp_parser_elaborated_type_specifier): Adjust
	cp_parser_nested_name_specifier call.

	* parser (cp_parser_skip_to_end_of_block_or_statement): Cleanup.

2005-06-13  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/21929
	* g++.dg/parse/crash26.C: New.

	PR c++/20789
	* g++.dg/init/member1.C: New.

Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1403
diff -c -3 -p -r1.1403 decl.c
*** cp/decl.c	3 Jun 2005 16:16:12 -0000	1.1403
--- cp/decl.c	13 Jun 2005 15:41:01 -0000
*************** cp_finish_decl (tree decl, tree init, tr
*** 4834,4839 ****
--- 4834,4849 ----
  		     "initialized", decl);
  	      init = NULL_TREE;
  	    }
+ 	  if (DECL_EXTERNAL (decl) && init)
+ 	    {
+ 	      /* The static data member cannot be initialized by a
+ 		 non-constant when being declared.  */
+ 	      error ("%qD cannot be initialized by a non-constant expression"
+ 		     " when being declared", decl);
+ 	      DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
+ 	      init = NULL_TREE;
+ 	    }
+ 	  
  	  /* Handle:
  
  	     [dcl.init]
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.340
diff -c -3 -p -r1.340 parser.c
*** cp/parser.c	8 Jun 2005 11:09:00 -0000	1.340
--- cp/parser.c	13 Jun 2005 15:41:07 -0000
*************** typedef struct cp_parser GTY(())
*** 1217,1223 ****
    /* The scope in which names should be looked up.  If NULL_TREE, then
       we look up names in the scope that is currently open in the
       source program.  If non-NULL, this is either a TYPE or
!      NAMESPACE_DECL for the scope in which we should look.
  
       This value is not cleared automatically after a name is looked
       up, so we must be careful to clear it before starting a new look
--- 1217,1224 ----
    /* The scope in which names should be looked up.  If NULL_TREE, then
       we look up names in the scope that is currently open in the
       source program.  If non-NULL, this is either a TYPE or
!      NAMESPACE_DECL for the scope in which we should look.  It can
!      also be ERROR_MARK, when we've parsed a bogus scope.
  
       This value is not cleared automatically after a name is looked
       up, so we must be careful to clear it before starting a new look
*************** typedef struct cp_parser GTY(())
*** 1225,1231 ****
       will look up `Z' in the scope of `X', rather than the current
       scope.)  Unfortunately, it is difficult to tell when name lookup
       is complete, because we sometimes peek at a token, look it up,
!      and then decide not to consume it.  */
    tree scope;
  
    /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the
--- 1226,1232 ----
       will look up `Z' in the scope of `X', rather than the current
       scope.)  Unfortunately, it is difficult to tell when name lookup
       is complete, because we sometimes peek at a token, look it up,
!      and then decide not to consume it.   */
    tree scope;
  
    /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the
*************** cp_parser_diagnose_invalid_type_name (cp
*** 2045,2051 ****
    if (TREE_CODE (decl) == TEMPLATE_DECL)
      error ("invalid use of template-name %qE without an argument list",
        decl);
!   else if (!parser->scope)
      {
        /* Issue an error message.  */
        error ("%qE does not name a type", id);
--- 2046,2052 ----
    if (TREE_CODE (decl) == TEMPLATE_DECL)
      error ("invalid use of template-name %qE without an argument list",
        decl);
!   else if (!parser->scope || parser->scope == error_mark_node)
      {
        /* Issue an error message.  */
        error ("%qE does not name a type", id);
*************** cp_parser_consume_semicolon_at_end_of_st
*** 2313,2348 ****
  static void
  cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
  {
!   unsigned nesting_depth = 0;
  
!   while (true)
      {
!       cp_token *token;
! 
!       /* Peek at the next token.  */
!       token = cp_lexer_peek_token (parser->lexer);
!       /* If we've run out of tokens, stop.  */
        if (token->type == CPP_EOF)
  	break;
!       /* If the next token is a `;', we have reached the end of the
! 	 statement.  */
!       if (token->type == CPP_SEMICOLON && !nesting_depth)
  	{
! 	  /* Consume the `;'.  */
! 	  cp_lexer_consume_token (parser->lexer);
  	  break;
  	}
        /* Consume the token.  */
!       token = cp_lexer_consume_token (parser->lexer);
!       /* If the next token is a non-nested `}', then we have reached
! 	 the end of the current block.  */
!       if (token->type == CPP_CLOSE_BRACE
! 	  && (nesting_depth == 0 || --nesting_depth == 0))
! 	break;
!       /* If it the next token is a `{', then we are entering a new
! 	 block.  Consume the entire block.  */
!       if (token->type == CPP_OPEN_BRACE)
! 	++nesting_depth;
      }
  }
  
--- 2314,2361 ----
  static void
  cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
  {
!   int nesting_depth = 0;
  
!   while (nesting_depth >= 0)
      {
!       cp_token *token = cp_lexer_peek_token (parser->lexer);
!       
        if (token->type == CPP_EOF)
  	break;
! 
!       switch (token->type)
  	{
! 	case CPP_EOF:
! 	  /* If we've run out of tokens, stop.  */
! 	  nesting_depth = -1;
! 	  continue;
! 
! 	case CPP_SEMICOLON:
! 	  /* Stop if this is an unnested ';'. */
! 	  if (!nesting_depth)
! 	    nesting_depth = -1;
! 	  break;
! 
! 	case CPP_CLOSE_BRACE:
! 	  /* Stop if this is an unnested '}', or closes the outermost
! 	     nesting level.  */
! 	  nesting_depth--;
! 	  if (!nesting_depth)
! 	    nesting_depth = -1;
! 	  break;
! 	  
! 	case CPP_OPEN_BRACE:
! 	  /* Nest. */
! 	  nesting_depth++;
! 	  break;
! 
! 	default:
  	  break;
  	}
+       
        /* Consume the token.  */
!       cp_lexer_consume_token (parser->lexer);
!       
      }
  }
  
*************** cp_parser_nested_name_specifier_opt (cp_
*** 3664,3672 ****
  /* Parse a nested-name-specifier.  See
     cp_parser_nested_name_specifier_opt for details.  This function
     behaves identically, except that it will an issue an error if no
!    nested-name-specifier is present, and it will return
!    ERROR_MARK_NODE, rather than NULL_TREE, if no nested-name-specifier
!    is present.  */
  
  static tree
  cp_parser_nested_name_specifier (cp_parser *parser,
--- 3677,3683 ----
  /* Parse a nested-name-specifier.  See
     cp_parser_nested_name_specifier_opt for details.  This function
     behaves identically, except that it will an issue an error if no
!    nested-name-specifier is present.  */
  
  static tree
  cp_parser_nested_name_specifier (cp_parser *parser,
*************** cp_parser_nested_name_specifier (cp_pars
*** 3688,3694 ****
      {
        cp_parser_error (parser, "expected nested-name-specifier");
        parser->scope = NULL_TREE;
-       return error_mark_node;
      }
  
    return scope;
--- 3699,3704 ----
*************** cp_parser_postfix_expression (cp_parser 
*** 3973,3979 ****
  	  id = cp_parser_identifier (parser);
  
  	/* Don't process id if nested name specifier is invalid.  */
! 	if (scope == error_mark_node)
  	  return error_mark_node;
  	/* If we look up a template-id in a non-dependent qualifying
  	   scope, there's no need to create a dependent type.  */
--- 3983,3989 ----
  	  id = cp_parser_identifier (parser);
  
  	/* Don't process id if nested name specifier is invalid.  */
! 	if (!scope || scope == error_mark_node)
  	  return error_mark_node;
  	/* If we look up a template-id in a non-dependent qualifying
  	   scope, there's no need to create a dependent type.  */
*************** cp_parser_elaborated_type_specifier (cp_
*** 9871,9882 ****
    /* Look for the nested-name-specifier.  */
    if (tag_type == typename_type)
      {
!       if (cp_parser_nested_name_specifier (parser,
  					   /*typename_keyword_p=*/true,
  					   /*check_dependency_p=*/true,
  					   /*type_p=*/true,
! 					   is_declaration)
! 	  == error_mark_node)
  	return error_mark_node;
      }
    else
--- 9881,9891 ----
    /* Look for the nested-name-specifier.  */
    if (tag_type == typename_type)
      {
!       if (!cp_parser_nested_name_specifier (parser,
  					   /*typename_keyword_p=*/true,
  					   /*check_dependency_p=*/true,
  					   /*type_p=*/true,
! 					    is_declaration))
  	return error_mark_node;
      }
    else
Index: testsuite/g++.dg/init/member1.C
===================================================================
RCS file: testsuite/g++.dg/init/member1.C
diff -N testsuite/g++.dg/init/member1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/member1.C	13 Jun 2005 15:49:11 -0000
***************
*** 0 ****
--- 1,18 ----
+ // Copyright (C) 2005 Free Software Foundation, Inc.
+ // Contributed by Nathan Sidwell 13 Jun 2005 <nathan@codesourcery.com>
+ 
+ // Origin:   Ivan Godard <igodard@pacbell.net>
+ // Bug 20789: ICE on invalid
+ 
+ template<typename> struct A;
+ 
+ template<int> struct B {};
+ 
+ template<typename T> struct C
+ {
+   static const int i = A<T>::i;  // { dg-error "incomplete" }
+   static const int j = i;      // { dg-error "initialized by a non-const" }
+   B<j> b;  // { dg-error "not a valid template arg" }
+ };
+ 
+ C<int> c;
Index: testsuite/g++.dg/parse/crash26.C
===================================================================
RCS file: testsuite/g++.dg/parse/crash26.C
diff -N testsuite/g++.dg/parse/crash26.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/crash26.C	13 Jun 2005 15:49:11 -0000
***************
*** 0 ****
--- 1,12 ----
+ // Copyright (C) 2005 Free Software Foundation, Inc.
+ // Contributed by Nathan Sidwell 13 Jun 2005 <nathan@codesourcery.com>
+ 
+ // Origin:  Volker Reichelt <reichelt@gcc.gnu.org>
+ // Bug 21929: ICE on invalid
+ 
+ template<int> struct A
+ {
+     struct B;
+ };
+ 
+ template<> struct A<void>::B {}; // { dg-error "mismatch|expected|name a type|extra" }

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