re PR c++/20789 (ICE with incomplete type in template)

cp:
	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.
testsuite:
	PR c++/21929
	* g++.dg/parse/crash26.C: New.

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

From-SVN: r100880
This commit is contained in:
Nathan Sidwell 2005-06-13 15:58:10 +00:00 committed by Nathan Sidwell
parent 56fc483e31
commit 8fe4d24beb
6 changed files with 109 additions and 33 deletions

View file

@ -1,3 +1,22 @@
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-12 Roger Sayle <roger@eyesopen.com>
PR c++/21930

View file

@ -4834,6 +4834,16 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
"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]

View file

@ -1217,7 +1217,8 @@ typedef struct cp_parser GTY(())
/* 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.
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
@ -1225,7 +1226,7 @@ typedef struct cp_parser GTY(())
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. */
and then decide not to consume it. */
tree scope;
/* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the
@ -2045,7 +2046,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
if (TREE_CODE (decl) == TEMPLATE_DECL)
error ("invalid use of template-name %qE without an argument list",
decl);
else if (!parser->scope)
else if (!parser->scope || parser->scope == error_mark_node)
{
/* Issue an error message. */
error ("%qE does not name a type", id);
@ -2313,36 +2314,48 @@ cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
static void
cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
{
unsigned nesting_depth = 0;
int nesting_depth = 0;
while (true)
while (nesting_depth >= 0)
{
cp_token *token;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* If we've run out of tokens, stop. */
cp_token *token = cp_lexer_peek_token (parser->lexer);
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)
switch (token->type)
{
/* Consume the `;'. */
cp_lexer_consume_token (parser->lexer);
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. */
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;
cp_lexer_consume_token (parser->lexer);
}
}
@ -3664,9 +3677,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
/* 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. */
nested-name-specifier is present. */
static tree
cp_parser_nested_name_specifier (cp_parser *parser,
@ -3688,7 +3699,6 @@ cp_parser_nested_name_specifier (cp_parser *parser,
{
cp_parser_error (parser, "expected nested-name-specifier");
parser->scope = NULL_TREE;
return error_mark_node;
}
return scope;
@ -3973,7 +3983,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
id = cp_parser_identifier (parser);
/* Don't process id if nested name specifier is invalid. */
if (scope == error_mark_node)
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. */
@ -9871,12 +9881,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
/* Look for the nested-name-specifier. */
if (tag_type == typename_type)
{
if (cp_parser_nested_name_specifier (parser,
if (!cp_parser_nested_name_specifier (parser,
/*typename_keyword_p=*/true,
/*check_dependency_p=*/true,
/*type_p=*/true,
is_declaration)
== error_mark_node)
is_declaration))
return error_mark_node;
}
else

View file

@ -1,3 +1,11 @@
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.
2005-06-13 Jakub Jelinek <jakub@redhat.com>
* gfortran.dg/altreturn_1.f90: New test.

View file

@ -0,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;

View file

@ -0,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" }