Commit 8fe4d24b by Nathan Sidwell Committed by Nathan Sidwell

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
parent 56fc483e
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> 2005-06-12 Roger Sayle <roger@eyesopen.com>
PR c++/21930 PR c++/21930
......
...@@ -4834,6 +4834,16 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) ...@@ -4834,6 +4834,16 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
"initialized", decl); "initialized", decl);
init = NULL_TREE; 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: /* Handle:
[dcl.init] [dcl.init]
......
...@@ -1217,7 +1217,8 @@ typedef struct cp_parser GTY(()) ...@@ -1217,7 +1217,8 @@ typedef struct cp_parser GTY(())
/* The scope in which names should be looked up. If NULL_TREE, then /* 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 we look up names in the scope that is currently open in the
source program. If non-NULL, this is either a TYPE or 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 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 up, so we must be careful to clear it before starting a new look
...@@ -2045,7 +2046,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) ...@@ -2045,7 +2046,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
if (TREE_CODE (decl) == TEMPLATE_DECL) if (TREE_CODE (decl) == TEMPLATE_DECL)
error ("invalid use of template-name %qE without an argument list", error ("invalid use of template-name %qE without an argument list",
decl); decl);
else if (!parser->scope) else if (!parser->scope || parser->scope == error_mark_node)
{ {
/* Issue an error message. */ /* Issue an error message. */
error ("%qE does not name a type", id); error ("%qE does not name a type", id);
...@@ -2313,36 +2314,48 @@ cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser) ...@@ -2313,36 +2314,48 @@ cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
static void static void
cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser) 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; cp_token *token = cp_lexer_peek_token (parser->lexer);
/* 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) if (token->type == CPP_EOF)
break; break;
/* If the next token is a `;', we have reached the end of the
statement. */ switch (token->type)
if (token->type == CPP_SEMICOLON && !nesting_depth)
{ {
/* Consume the `;'. */ case CPP_EOF:
cp_lexer_consume_token (parser->lexer); /* 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; break;
} }
/* Consume the token. */ /* Consume the token. */
token = cp_lexer_consume_token (parser->lexer); 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;
} }
} }
...@@ -3664,9 +3677,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, ...@@ -3664,9 +3677,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
/* Parse a nested-name-specifier. See /* Parse a nested-name-specifier. See
cp_parser_nested_name_specifier_opt for details. This function cp_parser_nested_name_specifier_opt for details. This function
behaves identically, except that it will an issue an error if no behaves identically, except that it will an issue an error if no
nested-name-specifier is present, and it will return nested-name-specifier is present. */
ERROR_MARK_NODE, rather than NULL_TREE, if no nested-name-specifier
is present. */
static tree static tree
cp_parser_nested_name_specifier (cp_parser *parser, cp_parser_nested_name_specifier (cp_parser *parser,
...@@ -3688,7 +3699,6 @@ 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"); cp_parser_error (parser, "expected nested-name-specifier");
parser->scope = NULL_TREE; parser->scope = NULL_TREE;
return error_mark_node;
} }
return scope; return scope;
...@@ -3973,7 +3983,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) ...@@ -3973,7 +3983,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
id = cp_parser_identifier (parser); id = cp_parser_identifier (parser);
/* Don't process id if nested name specifier is invalid. */ /* 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; return error_mark_node;
/* If we look up a template-id in a non-dependent qualifying /* If we look up a template-id in a non-dependent qualifying
scope, there's no need to create a dependent type. */ scope, there's no need to create a dependent type. */
...@@ -9871,12 +9881,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, ...@@ -9871,12 +9881,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
/* Look for the nested-name-specifier. */ /* Look for the nested-name-specifier. */
if (tag_type == typename_type) if (tag_type == typename_type)
{ {
if (cp_parser_nested_name_specifier (parser, if (!cp_parser_nested_name_specifier (parser,
/*typename_keyword_p=*/true, /*typename_keyword_p=*/true,
/*check_dependency_p=*/true, /*check_dependency_p=*/true,
/*type_p=*/true, /*type_p=*/true,
is_declaration) is_declaration))
== error_mark_node)
return error_mark_node; return error_mark_node;
} }
else else
......
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> 2005-06-13 Jakub Jelinek <jakub@redhat.com>
* gfortran.dg/altreturn_1.f90: New test. * gfortran.dg/altreturn_1.f90: New test.
......
// 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;
// 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" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment