aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2005-06-13 15:58:10 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2005-06-13 15:58:10 +0000
commit8fe4d24bebd6df659ab43ad5dd065a29c473f815 (patch)
tree80df738d7463c3986a421395691d3add01541ee2 /gcc
parent56fc483e31987c2936dfee9e141702c848da7a50 (diff)
downloadgcc-8fe4d24bebd6df659ab43ad5dd065a29c473f815.zip
gcc-8fe4d24bebd6df659ab43ad5dd065a29c473f815.tar.gz
gcc-8fe4d24bebd6df659ab43ad5dd065a29c473f815.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog19
-rw-r--r--gcc/cp/decl.c10
-rw-r--r--gcc/cp/parser.c75
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/init/member1.C18
-rw-r--r--gcc/testsuite/g++.dg/parse/crash26.C12
6 files changed, 109 insertions, 33 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fa37b36..00a029d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6b278ae..c17d6f8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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]
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cb389d2..f56c901 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index af6d1b1..8fb457e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/init/member1.C b/gcc/testsuite/g++.dg/init/member1.C
new file mode 100644
index 0000000..1c89d5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/member1.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/parse/crash26.C b/gcc/testsuite/g++.dg/parse/crash26.C
new file mode 100644
index 0000000..2b4f165
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash26.C
@@ -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" }