This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix 20789 & 21929
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 13 Jun 2005 17:00:35 +0100
- Subject: [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" }