re PR c++/20789 (ICE with incomplete type in template)
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 13 Jun 2005 15:58:10 +0000 (15:58 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 13 Jun 2005 15:58:10 +0000 (15:58 +0000)
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

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/member1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/crash26.C [new file with mode: 0644]

index fa37b36f4ee6ad911c30162a134530ef8a83aed2..00a029de5cb6ff8fff4021a13051cf253a529fe1 100644 (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
index 6b278ae2878e61710fbe8a631873e3cdb31d8be0..c17d6f8f3724aacd1c36f10ce1feb18df856358e 100644 (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]
index cb389d24afe9a6112c27b8535da8d85ba8ad108d..f56c9019ce698a57107cded9e43a6298eb847a1f 100644 (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
index af6d1b13266e51c90516360541b409757f5ba87c..8fb457e66516b81615a6c38c7e70a1a51fd14478 100644 (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.
diff --git a/gcc/testsuite/g++.dg/init/member1.C b/gcc/testsuite/g++.dg/init/member1.C
new file mode 100644 (file)
index 0000000..1c89d5a
--- /dev/null
@@ -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 (file)
index 0000000..2b4f165
--- /dev/null
@@ -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" }