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:
parent
56fc483e31
commit
8fe4d24beb
6 changed files with 109 additions and 33 deletions
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
18
gcc/testsuite/g++.dg/init/member1.C
Normal file
18
gcc/testsuite/g++.dg/init/member1.C
Normal 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;
|
12
gcc/testsuite/g++.dg/parse/crash26.C
Normal file
12
gcc/testsuite/g++.dg/parse/crash26.C
Normal 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" }
|
Loading…
Add table
Reference in a new issue