OSDN Git Service

2008-01-04 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 458d300..16f5a4e 100644 (file)
@@ -1,13 +1,13 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005  Free Software Foundation, Inc.
+   2005, 2007  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GCC is distributed in the hope that it will be useful, but
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -98,7 +97,7 @@ typedef struct cp_token *cp_token_position;
 DEF_VEC_P (cp_token_position);
 DEF_VEC_ALLOC_P (cp_token_position,heap);
 
-static const cp_token eof_token =
+static cp_token eof_token =
 {
   CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, { NULL },
 #if USE_MAPPED_LOCATION
@@ -278,9 +277,6 @@ cp_lexer_new_main (void)
      allocating any memory.  */
   cp_parser_initial_pragma (&first_token);
 
-  /* Tell c_lex_with_flags not to merge string constants.  */
-  c_lex_return_raw_strings = true;
-
   c_common_no_more_pch ();
 
   /* Allocate the memory.  */
@@ -318,7 +314,7 @@ cp_lexer_new_main (void)
   lexer->buffer = buffer;
   lexer->buffer_length = alloc - space;
   lexer->last_token = pos;
-  lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token;
+  lexer->next_token = lexer->buffer_length ? buffer : &eof_token;
 
   /* Subsequent preprocessor diagnostics should use compiler
      diagnostic functions to get the compiler source location.  */
@@ -342,7 +338,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
   /* We do not own the buffer.  */
   lexer->buffer = NULL;
   lexer->buffer_length = 0;
-  lexer->next_token = first == last ? (cp_token *)&eof_token : first;
+  lexer->next_token = first == last ? &eof_token : first;
   lexer->last_token = last;
 
   lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
@@ -403,17 +399,19 @@ cp_lexer_saving_tokens (const cp_lexer* lexer)
 }
 
 /* Store the next token from the preprocessor in *TOKEN.  Return true
-   if we reach EOF.  */
+   if we reach EOF.  If LEXER is NULL, assume we are handling an
+   initial #pragma pch_preprocess, and thus want the lexer to return
+   processed strings.  */
 
 static void
-cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
-                                cp_token *token)
+cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
 {
   static int is_extern_c = 0;
 
    /* Get a new token from the preprocessor.  */
   token->type
-    = c_lex_with_flags (&token->u.value, &token->location, &token->flags);
+    = c_lex_with_flags (&token->u.value, &token->location, &token->flags,
+                       lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
   token->input_file_stack_index = input_file_stack_tick;
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
@@ -577,6 +575,8 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
       /* GNU extensions.  */ 
     case RID_ATTRIBUTE:
     case RID_TYPEOF:
+      /* C++0x extensions.  */
+    case RID_DECLTYPE:
       return true;
 
     default:
@@ -610,7 +610,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
       ++token;
       if (token == lexer->last_token)
        {
-         token = (cp_token *)&eof_token;
+         token = &eof_token;
          break;
        }
 
@@ -643,7 +643,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
       lexer->next_token++;
       if (lexer->next_token == lexer->last_token)
        {
-         lexer->next_token = (cp_token *)&eof_token;
+         lexer->next_token = &eof_token;
          break;
        }
 
@@ -683,7 +683,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
       tok++;
       if (tok == lexer->last_token)
        {
-         tok = (cp_token *)&eof_token;
+         tok = &eof_token;
          break;
        }
     }
@@ -1582,7 +1582,7 @@ static tree cp_parser_nested_name_specifier
 static tree cp_parser_class_or_namespace_name
   (cp_parser *, bool, bool, bool, bool, bool);
 static tree cp_parser_postfix_expression
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, bool);
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
@@ -1707,6 +1707,8 @@ static void cp_parser_linkage_specification
   (cp_parser *);
 static void cp_parser_static_assert
   (cp_parser *, bool);
+static tree cp_parser_decltype
+  (cp_parser *);
 
 /* Declarators [gram.dcl.decl] */
 
@@ -2145,8 +2147,9 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
        {
          if (count > 2)
            error ("%<long long long%> is too long for GCC");
-         else if (pedantic && !in_system_header && warn_long_long)
-           pedwarn ("ISO C++ does not support %<long long%>");
+         else if (pedantic && !in_system_header && warn_long_long
+                   && cxx_dialect == cxx98)
+           pedwarn ("ISO C++ 1998 does not support %<long long%>");
        }
       else if (count > 1)
        {
@@ -2896,7 +2899,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
        {
          cp_lexer_consume_token (parser->lexer);
          count++;
-         str.text = (unsigned char *)TREE_STRING_POINTER (tok->u.value);
+         str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
          str.len = TREE_STRING_LENGTH (tok->u.value);
          if (tok->type == CPP_WSTRING)
            wide = true;
@@ -2919,8 +2922,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
   if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
       (parse_in, strs, count, &istr, wide))
     {
-      value = build_string (istr.len, (char *)istr.text);
-      free ((void *)istr.text);
+      value = build_string (istr.len, (const char *)istr.text);
+      free (CONST_CAST (unsigned char *, istr.text));
 
       TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
       value = fix_string_type (value);
@@ -3163,9 +3166,11 @@ cp_parser_primary_expression (cp_parser *parser,
                 int i = ({ int j = 3; j + 1; });
 
               at class or namespace scope.  */
-           if (!parser->in_function_body)
+           if (!parser->in_function_body
+               || parser->in_template_argument_list_p)
              {
-               error ("statement-expressions are allowed only inside functions");
+               error ("statement-expressions are not allowed outside "
+                      "functions nor in template-argument lists");
                cp_parser_skip_to_end_of_block_or_statement (parser);
                expr = error_mark_node;
              }
@@ -4081,7 +4086,15 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
          && !COMPLETE_TYPE_P (new_scope)
          /* Do not try to complete dependent types.  */
          && !dependent_type_p (new_scope))
-       new_scope = complete_type (new_scope);
+       {
+         new_scope = complete_type (new_scope);
+         /* If it is a typedef to current class, use the current
+            class instead, as the typedef won't have any names inside
+            it yet.  */
+         if (!COMPLETE_TYPE_P (new_scope)
+             && currently_open_class (new_scope))
+           new_scope = TYPE_MAIN_VARIANT (new_scope);
+       }
       /* Make sure we look in the right scope the next time through
         the loop.  */
       parser->scope = new_scope;
@@ -4254,15 +4267,20 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
    `&' operator.  CAST_P is true if this expression is the target of a
    cast.
 
+   If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are
+   class member access expressions [expr.ref].
+
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
+                              bool member_access_only_p)
 {
   cp_token *token;
   enum rid keyword;
   cp_id_kind idk = CP_ID_KIND_NONE;
   tree postfix_expression = NULL_TREE;
+  bool is_member_access = false;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -4513,6 +4531,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                                                        postfix_expression,
                                                        false);
          idk = CP_ID_KIND_NONE;
+          is_member_access = false;
          break;
 
        case CPP_OPEN_PAREN:
@@ -4524,6 +4543,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
            bool saved_non_integral_constant_expression_p = false;
            tree args;
 
+            is_member_access = false;
+
            is_builtin_constant_p
              = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
            if (is_builtin_constant_p)
@@ -4669,6 +4690,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
            = cp_parser_postfix_dot_deref_expression (parser, token->type,
                                                      postfix_expression,
                                                      false, &idk);
+
+          is_member_access = true;
          break;
 
        case CPP_PLUS_PLUS:
@@ -4684,6 +4707,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                                                          "an increment"))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
+          is_member_access = false;
          break;
 
        case CPP_MINUS_MINUS:
@@ -4699,10 +4723,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                                                          "a decrement"))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
+          is_member_access = false;
          break;
 
        default:
-         return postfix_expression;
+          if (member_access_only_p)
+            return is_member_access? postfix_expression : error_mark_node;
+          else
+            return postfix_expression;
        }
     }
 
@@ -4831,8 +4859,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
   pseudo_destructor_p = false;
 
   /* If the SCOPE is a scalar type, then, if this is a valid program,
-     we must be looking at a pseudo-destructor-name.  */
-  if (scope && SCALAR_TYPE_P (scope))
+     we must be looking at a pseudo-destructor-name.  If POSTFIX_EXPRESSION
+     is type dependent, it can be pseudo-destructor-name or something else.
+     Try to parse it as pseudo-destructor-name first.  */
+  if ((scope && SCALAR_TYPE_P (scope)) || dependent_p)
     {
       tree s;
       tree type;
@@ -4841,7 +4871,12 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* Parse the pseudo-destructor-name.  */
       s = NULL_TREE;
       cp_parser_pseudo_destructor_name (parser, &s, &type);
-      if (cp_parser_parse_definitely (parser))
+      if (dependent_p
+         && (cp_parser_error_occurred (parser)
+             || TREE_CODE (type) != TYPE_DECL
+             || !SCALAR_TYPE_P (TREE_TYPE (type))))
+       cp_parser_abort_tentative_parse (parser);
+      else if (cp_parser_parse_definitely (parser))
        {
          pseudo_destructor_p = true;
          postfix_expression
@@ -4957,6 +4992,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
   tree expression_list = NULL_TREE;
   bool fold_expr_p = is_attribute_list;
   tree identifier = NULL_TREE;
+  bool saved_greater_than_is_operator_p;
 
   /* Assume all the expressions will be constant.  */
   if (non_constant_p)
@@ -4965,6 +5001,12 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
     return error_mark_node;
 
+  /* Within a parenthesized expression, a `>' token is always
+     the greater-than operator.  */
+  saved_greater_than_is_operator_p
+    = parser->greater_than_is_operator_p;
+  parser->greater_than_is_operator_p = true;
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
@@ -5050,9 +5092,16 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
       if (ending < 0)
        goto get_comma;
       if (!ending)
-       return error_mark_node;
+       {
+         parser->greater_than_is_operator_p
+           = saved_greater_than_is_operator_p;
+         return error_mark_node;
+       }
     }
 
+  parser->greater_than_is_operator_p
+    = saved_greater_than_is_operator_p;
+
   /* We built up the list in reverse order so we must reverse it now.  */
   expression_list = nreverse (expression_list);
   if (identifier)
@@ -5281,13 +5330,18 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
               && token->type == CPP_AND_AND)
        {
          tree identifier;
+         tree expression;
 
          /* Consume the '&&' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Look for the identifier.  */
          identifier = cp_parser_identifier (parser);
          /* Create an expression representing the address.  */
-         return finish_label_address_expr (identifier);
+         expression = finish_label_address_expr (identifier);
+         if (cp_parser_non_integral_constant_expression (parser,
+                                               "the address of a label"))
+           expression = error_mark_node;
+         return expression;
        }
     }
   if (unary_operator != ERROR_MARK)
@@ -5341,7 +5395,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
       return expression;
     }
 
-  return cp_parser_postfix_expression (parser, address_p, cast_p);
+  return cp_parser_postfix_expression (parser, address_p, cast_p,
+                                       /*member_access_only_p=*/false);
 }
 
 /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
@@ -6483,6 +6538,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
   type1 = cp_parser_type_id (parser);
 
+  if (type1 == error_mark_node)
+    return error_mark_node;
+
   /* Build a trivial decl-specifier-seq.  */
   clear_decl_specs (&decl_specs);
   decl_specs.type = type1;
@@ -6497,6 +6555,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
  
       type2 = cp_parser_type_id (parser);
 
+      if (type2 == error_mark_node)
+       return error_mark_node;
+
       /* Build a trivial decl-specifier-seq.  */
       clear_decl_specs (&decl_specs);
       decl_specs.type = type2;
@@ -6508,8 +6569,8 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
   cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
-  /* Complete the trait expr, which may mean either processing the
-     static assert now or saving it for template instantiation.  */
+  /* Complete the trait expression, which may mean either processing
+     the trait expr now or saving it for template instantiation.  */
   return finish_trait_expr (kind, type1, type2);
 }
 
@@ -6795,6 +6856,15 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
    compound-statement:
      { statement-seq [opt] }
 
+   GNU extension:
+
+   compound-statement:
+     { label-declaration-seq [opt] statement-seq [opt] }
+
+   label-declaration-seq:
+     label-declaration
+     label-declaration-seq label-declaration
+
    Returns a tree representing the statement.  */
 
 static tree
@@ -6808,6 +6878,9 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
     return error_mark_node;
   /* Begin the compound-statement.  */
   compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
+  /* If the next keyword is `__label__' we have a label declaration.  */
+  while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
+    cp_parser_label_declaration (parser);
   /* Parse an (optional) statement-seq.  */
   cp_parser_statement_seq_opt (parser, in_statement_expr);
   /* Finish the compound-statement.  */
@@ -7685,7 +7758,6 @@ cp_parser_declaration (cp_parser* parser)
 
    block-declaration:
      __extension__ block-declaration
-     label-declaration
 
    C++0x Extension:
 
@@ -7746,12 +7818,16 @@ cp_parser_block_declaration (cp_parser *parser,
        cp_parser_using_declaration (parser,
                                     /*access_declaration_p=*/false);
     }
-  /* If the next keyword is `__label__' we have a label declaration.  */
+  /* If the next keyword is `__label__' we have a misplaced label
+     declaration.  */
   else if (token1->keyword == RID_LABEL)
     {
-      if (statement_p)
-       cp_parser_commit_to_tentative_parse (parser);
-      cp_parser_label_declaration (parser);
+      cp_lexer_consume_token (parser->lexer);
+      error ("%<__label__%> not at the beginning of a block");
+      cp_parser_skip_to_end_of_statement (parser);
+      /* If the next token is now a `;', consume it.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+       cp_lexer_consume_token (parser->lexer);
     }
   /* If the next token is `static_assert' we have a static assertion.  */
   else if (token1->keyword == RID_STATIC_ASSERT)
@@ -8371,6 +8447,171 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
   finish_static_assert (condition, message, saved_loc, member_p);
 }
 
+/* Parse a `decltype' type. Returns the type. 
+
+   simple-type-specifier:
+     decltype ( expression )  */
+
+static tree
+cp_parser_decltype (cp_parser *parser)
+{
+  tree expr;
+  bool id_expression_or_member_access_p = false;
+  const char *saved_message;
+  bool saved_integral_constant_expression_p;
+  bool saved_non_integral_constant_expression_p;
+
+  /* Look for the `decltype' token.  */
+  if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "`decltype'"))
+    return error_mark_node;
+
+  /* Types cannot be defined in a `decltype' expression.  Save away the
+     old message.  */
+  saved_message = parser->type_definition_forbidden_message;
+
+  /* And create the new one.  */
+  parser->type_definition_forbidden_message
+    = "types may not be defined in `decltype' expressions";
+
+  /* The restrictions on constant-expressions do not apply inside
+     decltype expressions.  */
+  saved_integral_constant_expression_p
+    = parser->integral_constant_expression_p;
+  saved_non_integral_constant_expression_p
+    = parser->non_integral_constant_expression_p;
+  parser->integral_constant_expression_p = false;
+
+  /* Do not actually evaluate the expression.  */
+  ++skip_evaluation;
+
+  /* Parse the opening `('.  */
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return error_mark_node;
+  
+  /* First, try parsing an id-expression.  */
+  cp_parser_parse_tentatively (parser);
+  expr = cp_parser_id_expression (parser,
+                                  /*template_keyword_p=*/false,
+                                  /*check_dependency_p=*/true,
+                                  /*template_p=*/NULL,
+                                  /*declarator_p=*/false,
+                                  /*optional_p=*/false);
+
+  if (!cp_parser_error_occurred (parser) && expr != error_mark_node)
+    {
+      bool non_integral_constant_expression_p = false;
+      tree id_expression = expr;
+      cp_id_kind idk;
+      const char *error_msg;
+
+      if (TREE_CODE (expr) == IDENTIFIER_NODE)
+       /* Lookup the name we got back from the id-expression.  */
+       expr = cp_parser_lookup_name (parser, expr,
+                                     none_type,
+                                     /*is_template=*/false,
+                                     /*is_namespace=*/false,
+                                     /*check_dependency=*/true,
+                                     /*ambiguous_decls=*/NULL);
+
+      if (expr
+          && expr != error_mark_node
+          && TREE_CODE (expr) != TEMPLATE_ID_EXPR
+          && TREE_CODE (expr) != TYPE_DECL
+         && (TREE_CODE (expr) != BIT_NOT_EXPR
+             || !TYPE_P (TREE_OPERAND (expr, 0)))
+          && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+        {
+          /* Complete lookup of the id-expression.  */
+          expr = (finish_id_expression
+                  (id_expression, expr, parser->scope, &idk,
+                   /*integral_constant_expression_p=*/false,
+                   /*allow_non_integral_constant_expression_p=*/true,
+                   &non_integral_constant_expression_p,
+                   /*template_p=*/false,
+                   /*done=*/true,
+                   /*address_p=*/false,
+                   /*template_arg_p=*/false,
+                   &error_msg));
+
+          if (expr == error_mark_node)
+            /* We found an id-expression, but it was something that we
+               should not have found. This is an error, not something
+               we can recover from, so note that we found an
+               id-expression and we'll recover as gracefully as
+               possible.  */
+            id_expression_or_member_access_p = true;
+        }
+
+      if (expr 
+          && expr != error_mark_node
+          && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+        /* We have an id-expression.  */
+        id_expression_or_member_access_p = true;
+    }
+
+  if (!id_expression_or_member_access_p)
+    {
+      /* Abort the id-expression parse.  */
+      cp_parser_abort_tentative_parse (parser);
+
+      /* Parsing tentatively, again.  */
+      cp_parser_parse_tentatively (parser);
+
+      /* Parse a class member access.  */
+      expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
+                                           /*cast_p=*/false,
+                                           /*member_access_only_p=*/true);
+
+      if (expr 
+          && expr != error_mark_node
+          && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+        /* We have an id-expression.  */
+        id_expression_or_member_access_p = true;
+    }
+
+  if (id_expression_or_member_access_p)
+    /* We have parsed the complete id-expression or member access.  */
+    cp_parser_parse_definitely (parser);
+  else
+    {
+      /* Abort our attempt to parse an id-expression or member access
+         expression.  */
+      cp_parser_abort_tentative_parse (parser);
+
+      /* Parse a full expression.  */
+      expr = cp_parser_expression (parser, /*cast_p=*/false);
+    }
+
+  /* Go back to evaluating expressions.  */
+  --skip_evaluation;
+
+  /* Restore the old message and the integral constant expression
+     flags.  */
+  parser->type_definition_forbidden_message = saved_message;
+  parser->integral_constant_expression_p
+    = saved_integral_constant_expression_p;
+  parser->non_integral_constant_expression_p
+    = saved_non_integral_constant_expression_p;
+
+  if (expr == error_mark_node)
+    {
+      /* Skip everything up to the closing `)'.  */
+      cp_parser_skip_to_closing_parenthesis (parser, true, false,
+                                             /*consume_paren=*/true);
+      return error_mark_node;
+    }
+  
+  /* Parse to the closing `)'.  */
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+    {
+      cp_parser_skip_to_closing_parenthesis (parser, true, false,
+                                            /*consume_paren=*/true);
+      return error_mark_node;
+    }
+
+  return finish_decltype_type (expr, id_expression_or_member_access_p);
+}
+
 /* Special member functions [gram.special] */
 
 /* Parse a conversion-function-id.
@@ -10438,6 +10679,11 @@ cp_parser_type_specifier (cp_parser* parser,
      double
      void
 
+   C++0x Extension:
+
+   simple-type-specifier:
+     decltype ( expression )   
+
    GNU Extension:
 
    simple-type-specifier:
@@ -10507,6 +10753,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       type = void_type_node;
       break;
 
+    case RID_DECLTYPE:
+      /* Parse the `decltype' type.  */
+      type = cp_parser_decltype (parser);
+
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     /*user_defined_p=*/true);
+
+      return type;
+
     case RID_TYPEOF:
       /* Consume the `typeof' token.  */
       cp_lexer_consume_token (parser->lexer);
@@ -11276,6 +11532,7 @@ static void
 cp_parser_namespace_definition (cp_parser* parser)
 {
   tree identifier, attribs;
+  bool has_visibility;
 
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
@@ -11295,9 +11552,18 @@ cp_parser_namespace_definition (cp_parser* parser)
   /* Look for the `{' to start the namespace.  */
   cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
   /* Start the namespace.  */
-  push_namespace_with_attribs (identifier, attribs);
+  push_namespace (identifier);
+
+  has_visibility = handle_namespace_attrs (current_namespace, attribs);
+
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
+
+#ifdef HANDLE_PRAGMA_VISIBILITY
+  if (has_visibility)
+    pop_visibility ();
+#endif
+
   /* Finish the namespace.  */
   pop_namespace ();
   /* Look for the final `}'.  */
@@ -11563,6 +11829,8 @@ cp_parser_asm_definition (cp_parser* parser)
   tree asm_stmt;
   bool volatile_p = false;
   bool extended_p = false;
+  bool invalid_inputs_p = false;
+  bool invalid_outputs_p = false;
 
   /* Look for the `asm' keyword.  */
   cp_parser_require_keyword (parser, RID_ASM, "`asm'");
@@ -11616,6 +11884,9 @@ cp_parser_asm_definition (cp_parser* parser)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            outputs = cp_parser_asm_operand_list (parser);
+
+           if (outputs == error_mark_node)
+             invalid_outputs_p = true;
        }
       /* If the next token is `::', there are no outputs, and the
         next token is the beginning of the inputs.  */
@@ -11635,6 +11906,9 @@ cp_parser_asm_definition (cp_parser* parser)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            inputs = cp_parser_asm_operand_list (parser);
+
+           if (inputs == error_mark_node)
+             invalid_inputs_p = true;
        }
       else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
        /* The clobbers are coming next.  */
@@ -11658,23 +11932,26 @@ cp_parser_asm_definition (cp_parser* parser)
                                           /*consume_paren=*/true);
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
 
-  /* Create the ASM_EXPR.  */
-  if (parser->in_function_body)
+  if (!invalid_inputs_p && !invalid_outputs_p)
     {
-      asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
-                                 inputs, clobbers);
-      /* If the extended syntax was not used, mark the ASM_EXPR.  */
-      if (!extended_p)
+      /* Create the ASM_EXPR.  */
+      if (parser->in_function_body)
        {
-         tree temp = asm_stmt;
-         if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
-           temp = TREE_OPERAND (temp, 0);
+         asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
+                                     inputs, clobbers);
+         /* If the extended syntax was not used, mark the ASM_EXPR.  */
+         if (!extended_p)
+           {
+             tree temp = asm_stmt;
+             if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
+               temp = TREE_OPERAND (temp, 0);
 
-         ASM_INPUT_P (temp) = 1;
+             ASM_INPUT_P (temp) = 1;
+           }
        }
+      else
+       cgraph_add_asm_node (string);
     }
-  else
-    cgraph_add_asm_node (string);
 }
 
 /* Declarators [gram.dcl.decl] */
@@ -13353,7 +13630,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
              token = cp_lexer_consume_token (parser->lexer);
            }
 
-         /* Create a DEFAULT_ARG to represented the unparsed default
+         /* Create a DEFAULT_ARG to represent the unparsed default
             argument.  */
          default_argument = make_node (DEFAULT_ARG);
          DEFARG_TOKENS (default_argument)
@@ -14214,8 +14491,12 @@ cp_parser_class_head (cp_parser* parser,
         class was originally declared, the program is invalid.  */
       if (scope && !is_ancestor (scope, nested_name_specifier))
        {
-         error ("declaration of %qD in %qD which does not enclose %qD",
-                type, scope, nested_name_specifier);
+         if (at_namespace_scope_p ())
+           error ("declaration of %qD in namespace %qD which does not "
+                  "enclose %qD", type, scope, nested_name_specifier);
+         else
+           error ("declaration of %qD in %qD which does not enclose %qD",
+                  type, scope, nested_name_specifier);
          type = NULL_TREE;
          goto done;
        }
@@ -14261,8 +14542,18 @@ cp_parser_class_head (cp_parser* parser,
   /* Look up the type.  */
   if (template_id_p)
     {
-      type = TREE_TYPE (id);
-      type = maybe_process_partial_specialization (type);
+      if (TREE_CODE (id) == TEMPLATE_ID_EXPR
+         && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
+             || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
+       {
+         error ("function template %qD redeclared as a class template", id);
+         type = error_mark_node;
+       }
+      else
+       {
+         type = TREE_TYPE (id);
+         type = maybe_process_partial_specialization (type);
+       }
       if (nested_name_specifier)
        pushed_scope = push_scope (nested_name_specifier);
     }
@@ -14798,11 +15089,7 @@ cp_parser_member_declaration (cp_parser* parser)
                  token = cp_lexer_peek_token (parser->lexer);
                  /* If the next token is a semicolon, consume it.  */
                  if (token->type == CPP_SEMICOLON)
-                   {
-                     if (pedantic && !in_system_header)
-                       pedwarn ("extra %<;%>");
-                     cp_lexer_consume_token (parser->lexer);
-                   }
+                   cp_lexer_consume_token (parser->lexer);
                  return;
                }
              else
@@ -14977,7 +15264,7 @@ cp_parser_base_clause (cp_parser* parser)
             /* Make this a pack expansion type. */
             TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
           else
-            check_for_bare_parameter_packs (TREE_VALUE (base));
+            check_for_bare_parameter_packs (&TREE_VALUE (base));
 
          TREE_CHAIN (base) = bases;
          bases = base;
@@ -15453,12 +15740,14 @@ cp_parser_asm_specification_opt (cp_parser* parser)
    each node is the expression.  The TREE_PURPOSE is itself a
    TREE_LIST whose TREE_PURPOSE is a STRING_CST for the bracketed
    string-literal (or NULL_TREE if not present) and whose TREE_VALUE
-   is a STRING_CST for the string literal before the parenthesis.  */
+   is a STRING_CST for the string literal before the parenthesis. Returns
+   ERROR_MARK_NODE if any of the operands are invalid.  */
 
 static tree
 cp_parser_asm_operand_list (cp_parser* parser)
 {
   tree asm_operands = NULL_TREE;
+  bool invalid_operands = false;
 
   while (true)
     {
@@ -15490,6 +15779,11 @@ cp_parser_asm_operand_list (cp_parser* parser)
       /* Look for the `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
+      if (name == error_mark_node 
+         || string_literal == error_mark_node 
+         || expression == error_mark_node)
+        invalid_operands = true;
+
       /* Add this operand to the list.  */
       asm_operands = tree_cons (build_tree_list (name, string_literal),
                                expression,
@@ -15502,7 +15796,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
 
-  return nreverse (asm_operands);
+  return invalid_operands ? error_mark_node : nreverse (asm_operands);
 }
 
 /* Parse an asm-clobber-list.
@@ -17111,6 +17405,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   static const char *format;
   tree expr = NULL_TREE;
   const char *saved_message;
+  char *tmp;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
   bool pack_expansion_p = false;
@@ -17123,12 +17418,11 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
      old message.  */
   saved_message = parser->type_definition_forbidden_message;
   /* And create the new one.  */
-  parser->type_definition_forbidden_message
-    = XNEWVEC (const char, strlen (format)
+  parser->type_definition_forbidden_message = tmp
+    = XNEWVEC (char, strlen (format)
               + strlen (IDENTIFIER_POINTER (ridpointers[keyword]))
               + 1 /* `\0' */);
-  sprintf ((char *) parser->type_definition_forbidden_message,
-          format, IDENTIFIER_POINTER (ridpointers[keyword]));
+  sprintf (tmp, format, IDENTIFIER_POINTER (ridpointers[keyword]));
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
@@ -17204,7 +17498,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   --skip_evaluation;
 
   /* Free the message we created.  */
-  free ((char *) parser->type_definition_forbidden_message);
+  free (tmp);
   /* And restore the old one.  */
   parser->type_definition_forbidden_message = saved_message;
   parser->integral_constant_expression_p
@@ -17580,7 +17874,7 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
 static void
 cp_parser_check_access_in_redeclaration (tree decl)
 {
-  if (!CLASS_TYPE_P (TREE_TYPE (decl)))
+  if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
     return;
 
   if ((TREE_PRIVATE (decl)
@@ -19378,13 +19672,20 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
                           const char *where, cp_token *pragma_tok)
 {
   tree clauses = NULL;
+  bool first = true;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
-      pragma_omp_clause c_kind = cp_parser_omp_clause_name (parser);
+      pragma_omp_clause c_kind;
       const char *c_name;
       tree prev = clauses;
 
+      if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+
+      c_kind = cp_parser_omp_clause_name (parser);
+      first = false;
+
       switch (c_kind)
        {
        case PRAGMA_OMP_CLAUSE_COPYIN:
@@ -19971,7 +20272,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
   switch (p_kind)
     {
     case PRAGMA_OMP_PARALLEL:
-      cp_parser_already_scoped_statement (parser);
+      cp_parser_statement (parser, NULL_TREE, false, NULL);
       par_clause = clauses;
       break;