OSDN Git Service

* toplev.c (finalize): Add no_backend parameter. Don't finish
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 0d28345..3ed0579 100644 (file)
@@ -502,6 +502,29 @@ cp_lexer_token_at (cp_lexer *lexer ATTRIBUTE_UNUSED, cp_token_position pos)
   return pos;
 }
 
+static inline void
+cp_lexer_set_token_position (cp_lexer *lexer, cp_token_position pos)
+{
+  lexer->next_token = cp_lexer_token_at (lexer, pos);
+}
+
+static inline cp_token_position
+cp_lexer_previous_token_position (cp_lexer *lexer)
+{
+  if (lexer->next_token == &eof_token)
+    return lexer->last_token - 1;
+  else
+    return cp_lexer_token_position (lexer, true);
+}
+
+static inline cp_token *
+cp_lexer_previous_token (cp_lexer *lexer)
+{
+  cp_token_position tp = cp_lexer_previous_token_position (lexer);
+
+  return cp_lexer_token_at (lexer, tp);
+}
+
 /* nonzero if we are presently saving tokens.  */
 
 static inline int
@@ -2698,8 +2721,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
           template <typename T> struct B : public A<T> { X x; };
 
         The user should have said "typename A<T>::X".  */
-      if (processing_template_decl && current_class_type
-         && TYPE_BINFO (current_class_type))
+      if (cxx_dialect < cxx0x && id == ridpointers[(int)RID_CONSTEXPR])
+       inform (location, "C++0x %<constexpr%> only available with "
+               "-std=c++0x or -std=gnu++0x");
+      else if (processing_template_decl && current_class_type
+              && TYPE_BINFO (current_class_type))
        {
          tree b;
 
@@ -3814,6 +3840,7 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_IS_STD_LAYOUT:
        case RID_IS_TRIVIAL:
        case RID_IS_UNION:
+       case RID_IS_LITERAL_TYPE:
          return cp_parser_trait_expr (parser, token->keyword);
 
        /* Objective-C++ expressions.  */
@@ -3904,6 +3931,22 @@ cp_parser_primary_expression (cp_parser *parser,
            if (ambiguous_decls)
              return error_mark_node;
 
+           /* In Objective-C++, we may have an Objective-C 2.0
+              dot-syntax for classes here.  */
+           if (c_dialect_objc ()
+               && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
+               && TREE_CODE (decl) == TYPE_DECL
+               && objc_is_class_name (decl))
+             {
+               tree component;
+               cp_lexer_consume_token (parser->lexer);
+               component = cp_parser_identifier (parser);
+               if (component == error_mark_node)
+                 return error_mark_node;
+
+               return objc_build_class_component_ref (id_expression, component);
+             }
+
            /* In Objective-C++, an instance variable (ivar) may be preferred
               to whatever cp_parser_lookup_name() found.  */
            decl = objc_lookup_ivar (decl, id_expression);
@@ -7172,7 +7215,8 @@ cp_parser_constant_expression (cp_parser* parser,
   saved_non_integral_constant_expression_p = parser->non_integral_constant_expression_p;
   /* We are now parsing a constant-expression.  */
   parser->integral_constant_expression_p = true;
-  parser->allow_non_integral_constant_expression_p = allow_non_constant_p;
+  parser->allow_non_integral_constant_expression_p
+    = (allow_non_constant_p || cxx_dialect >= cxx0x);
   parser->non_integral_constant_expression_p = false;
   /* Although the grammar says "conditional-expression", we parse an
      "assignment-expression", which also permits "throw-expression"
@@ -7191,7 +7235,8 @@ cp_parser_constant_expression (cp_parser* parser,
     = saved_allow_non_integral_constant_expression_p;
   if (allow_non_constant_p)
     *non_constant_p = parser->non_integral_constant_expression_p;
-  else if (parser->non_integral_constant_expression_p)
+  else if (parser->non_integral_constant_expression_p
+          && cxx_dialect < cxx0x)
     expression = error_mark_node;
   parser->non_integral_constant_expression_p
     = saved_non_integral_constant_expression_p;
@@ -7365,6 +7410,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_UNION:
       kind = CPTK_IS_UNION;
       break;
+    case RID_IS_LITERAL_TYPE:
+      kind = CPTK_IS_LITERAL_TYPE;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -11036,6 +11084,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -11054,11 +11109,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
                                                parm_loc,
                                                parameter,
                                                is_non_type,
-                                                is_parameter_pack);
+                                               is_parameter_pack,
+                                               0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
@@ -12770,14 +12825,14 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       return error_mark_node;
     }
 
-  /* There is no valid C++ program where a non-template type is
-     followed by a "<".  That usually indicates that the user thought
-     that the type was a template.  */
   if (type && type != error_mark_node)
     {
-      /* As a last-ditch effort, see if TYPE is an Objective-C type.
-        If it is, then the '<'...'>' enclose protocol names rather than
-        template arguments, and so everything is fine.  */
+      /* See if TYPE is an Objective-C type, and if so, parse and
+        accept any protocol references following it.  Do this before
+        the cp_parser_check_for_invalid_template_id() call, because
+        Objective-C types can be followed by '<...>' which would
+        enclose protocol names rather than template arguments, and so
+        everything is fine.  */
       if (c_dialect_objc () && !parser->scope
          && (objc_is_id (type) || objc_is_class_name (type)))
        {
@@ -12792,6 +12847,9 @@ cp_parser_simple_type_specifier (cp_parser* parser,
          return qual_type;
        }
 
+      /* There is no valid C++ program where a non-template type is
+        followed by a "<".  That usually indicates that the user
+        thought that the type was a template.  */
       cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type),
                                               token->location);
     }
@@ -12872,9 +12930,17 @@ cp_parser_nonclass_name (cp_parser* parser)
       if (type)
        type_decl = TYPE_NAME (type);
     }
-  
+
   /* Issue an error if we did not find a type-name.  */
-  if (TREE_CODE (type_decl) != TYPE_DECL)
+  if (TREE_CODE (type_decl) != TYPE_DECL
+      /* In Objective-C, we have the complication that class names are
+        normally type names and start declarations (eg, the
+        "NSObject" in "NSObject *object;"), but can be used in an
+        Objective-C 2.0 dot-syntax (as in "NSObject.version") which
+        is an expression.  So, a classname followed by a dot is not a
+        valid type-name.  */
+      || (objc_is_class_name (TREE_TYPE (type_decl))
+         && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT))
     {
       if (!cp_parser_simulate_error (parser))
        cp_parser_name_lookup_error (parser, identifier, type_decl,
@@ -13772,10 +13838,8 @@ cp_parser_namespace_definition (cp_parser* parser)
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
 
-#ifdef HANDLE_PRAGMA_VISIBILITY
   if (has_visibility)
     pop_visibility (1);
-#endif
 
   /* Finish the namespace.  */
   pop_namespace ();
@@ -14968,8 +15032,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                = cp_parser_constant_expression (parser,
                                                 /*allow_non_constant=*/true,
                                                 &non_constant_p);
-             if (!non_constant_p)
-               bounds = fold_non_dependent_expr (bounds);
+             if (!non_constant_p || cxx_dialect >= cxx0x)
+               /* OK */;
              /* Normally, the array bound must be an integral constant
                 expression.  However, as an extension, we allow VLAs
                 in function scopes as long as they aren't part of a
@@ -16291,14 +16355,8 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser)
     }
   /* Parse the function-body.  */
   cp_parser_function_body (parser);
-  if (check_body_p
-      && (TREE_CODE (list) != STATEMENT_LIST
-         || (last == NULL && STATEMENT_LIST_TAIL (list) != NULL)
-         || (last != NULL && last != STATEMENT_LIST_TAIL (list)->stmt)))
-    {
-      error ("constexpr constructor does not have empty body");
-      DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
-    }
+  if (check_body_p)
+    check_constexpr_ctor_body (last, list);
   /* Finish the function body.  */
   finish_function_body (body);
 
@@ -16401,7 +16459,15 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
                                        /*allow_non_constant_p=*/true,
                                        non_constant_p);
       if (!*non_constant_p)
-       initializer = fold_non_dependent_expr (initializer);
+       {
+         /* We only want to fold if this is really a constant
+            expression.  FIXME Actually, we don't want to fold here, but in
+            cp_finish_decl.  */
+         tree folded = fold_non_dependent_expr (initializer);
+         folded = maybe_constant_value (folded);
+         if (TREE_CONSTANT (folded))
+           initializer = folded;
+       }
     }
   else
     initializer = cp_parser_braced_list (parser, non_constant_p);
@@ -16690,7 +16756,12 @@ cp_parser_class_name (cp_parser *parser,
     }
   else if (TREE_CODE (decl) != TYPE_DECL
           || TREE_TYPE (decl) == error_mark_node
-          || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)))
+          || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
+          /* In Objective-C 2.0, a classname followed by '.' starts a
+             dot-syntax expression, and it's not a type-name.  */
+          || (c_dialect_objc ()
+              && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT 
+              && objc_is_class_name (decl)))
     decl = error_mark_node;
 
   if (decl == error_mark_node)
@@ -16797,6 +16868,100 @@ cp_parser_class_specifier (cp_parser* parser)
     type = finish_struct (type, attributes);
   if (nested_name_specifier_p)
     pop_inner_scope (old_scope, scope);
+
+  /* We've finished a type definition.  Check for the common syntax
+     error of forgetting a semicolon after the definition.  We need to
+     be careful, as we can't just check for not-a-semicolon and be done
+     with it; the user might have typed:
+
+     class X { } c = ...;
+     class X { } *p = ...;
+
+     and so forth.  Instead, enumerate all the possible tokens that
+     might follow this production; if we don't see one of them, then
+     complain and silently insert the semicolon.  */
+  {
+    cp_token *token = cp_lexer_peek_token (parser->lexer);
+    bool want_semicolon = true;
+
+    switch (token->type)
+      {
+      case CPP_NAME:
+      case CPP_SEMICOLON:
+      case CPP_MULT:
+      case CPP_AND:
+      case CPP_OPEN_PAREN:
+      case CPP_CLOSE_PAREN:
+      case CPP_COMMA:
+        want_semicolon = false;
+        break;
+
+        /* While it's legal for type qualifiers and storage class
+           specifiers to follow type definitions in the grammar, only
+           compiler testsuites contain code like that.  Assume that if
+           we see such code, then what we're really seeing is a case
+           like:
+
+           class X { }
+           const <type> var = ...;
+
+           or
+
+           class Y { }
+           static <type> func (...) ...
+
+           i.e. the qualifier or specifier applies to the next
+           declaration.  To do so, however, we need to look ahead one
+           more token to see if *that* token is a type specifier.
+
+          This code could be improved to handle:
+
+          class Z { }
+          static const <type> var = ...;  */
+      case CPP_KEYWORD:
+       if (keyword_is_storage_class_specifier (token->keyword)
+           || keyword_is_type_qualifier (token->keyword))
+         {
+           cp_token *lookahead = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+           if (lookahead->type == CPP_KEYWORD
+               && !keyword_begins_type_specifier (lookahead->keyword))
+             want_semicolon = false;
+           else if (lookahead->type == CPP_NAME)
+             /* Handling user-defined types here would be nice, but
+                very tricky.  */
+             want_semicolon = false;
+         }
+       break;
+      default:
+       break;
+      }
+
+    if (want_semicolon)
+      {
+       cp_token_position prev
+         = cp_lexer_previous_token_position (parser->lexer);
+       cp_token *prev_token = cp_lexer_token_at (parser->lexer, prev);
+       location_t loc = prev_token->location;
+
+       if (CLASSTYPE_DECLARED_CLASS (type))
+         error_at (loc, "expected %<;%> after class definition");
+       else if (TREE_CODE (type) == RECORD_TYPE)
+         error_at (loc, "expected %<;%> after struct definition");
+       else if (TREE_CODE (type) == UNION_TYPE)
+         error_at (loc, "expected %<;%> after union definition");
+       else
+         gcc_unreachable ();
+
+       /* Unget one token and smash it to look as though we encountered
+          a semicolon in the input stream.  */
+       cp_lexer_set_token_position (parser->lexer, prev);
+       token = cp_lexer_peek_token (parser->lexer);
+       token->type = CPP_SEMICOLON;
+       token->keyword = RID_MAX;
+      }
+  }
+
   /* If this class is not itself within the scope of another class,
      then we need to parse the bodies of all of the queued function
      definitions.  Note that the queued functions defined in a class
@@ -17571,6 +17736,8 @@ cp_parser_member_declaration (cp_parser* parser)
     }
   else
     {
+      bool assume_semicolon = false;
+
       /* See if these declarations will be friends.  */
       friend_p = cp_parser_friend_p (&decl_specifiers);
 
@@ -17764,11 +17931,18 @@ cp_parser_member_declaration (cp_parser* parser)
          else if (cp_lexer_next_token_is_not (parser->lexer,
                                               CPP_SEMICOLON))
            {
-             cp_parser_error (parser, "expected %<;%>");
-             /* Skip tokens until we find a `;'.  */
-             cp_parser_skip_to_end_of_statement (parser);
+             /* The next token might be a ways away from where the
+                actual semicolon is missing.  Find the previous token
+                and use that for our error position.  */
+             cp_token *token = cp_lexer_previous_token (parser->lexer);
+             error_at (token->location,
+                       "expected %<;%> at end of member declaration");
 
-             break;
+             /* Assume that the user meant to provide a semicolon.  If
+                we were to cp_parser_skip_to_end_of_statement, we might
+                skip to a semicolon inside a member function definition
+                and issue nonsensical error messages.  */
+             assume_semicolon = true;
            }
 
          if (decl)
@@ -17780,6 +17954,9 @@ cp_parser_member_declaration (cp_parser* parser)
              if (TREE_CODE (decl) == FUNCTION_DECL)
                cp_parser_save_default_args (parser, decl);
            }
+
+         if (assume_semicolon)
+           return;
        }
     }
 
@@ -18137,7 +18314,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
   /* Enable this once a lot of code has transitioned to noexcept?  */
   if (cxx_dialect == cxx0x && !in_system_header)
     warning (OPT_Wdeprecated, "dynamic exception specifications are "
-            "deprecated in C++0x; use %<noexcept%> instead.");
+            "deprecated in C++0x; use %<noexcept%> instead");
 #endif
 
   /* Consume the `throw'.  */
@@ -21897,7 +22074,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
   else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
     {
       cp_lexer_consume_token (parser->lexer);
-      error ("stray `%s' between Objective-C++ methods",
+      error ("stray %qs between Objective-C++ methods",
             token->type == CPP_OPEN_BRACE ? "{" : "}");
     }
   /* Finally, try to parse a block-declaration, or a function-definition.  */
@@ -22239,7 +22416,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
   /* Try a forward declaration first.  */
   if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
     {
-      objc_declare_protocols (cp_parser_objc_identifier_list (parser));
+      objc_declare_protocols (cp_parser_objc_identifier_list (parser), 
+                             attributes);
      finish:
       cp_parser_consume_semicolon_at_end_of_statement (parser);
     }
@@ -22713,10 +22891,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
   bool property_readwrite = false;
   bool property_retain = false;
   tree property_setter_ident = NULL_TREE;
-  /* The following two will be removed once @synthesize is
-     implemented.  */
-  bool property_copies = false;
-  tree property_ivar_ident = NULL_TREE;
 
   /* 'properties' is the list of properties that we read.  Usually a
      single one, but maybe more (eg, in "@property int a, b, c;" there
@@ -22750,7 +22924,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
          switch (keyword)
            {
            case RID_ASSIGN:    property_assign = true;    break;
-           case RID_COPIES:    property_copies = true;    break;
            case RID_COPY:      property_copy = true;      break;
            case RID_NONATOMIC: property_nonatomic = true; break;
            case RID_READONLY:  property_readonly = true;  break;
@@ -22759,7 +22932,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
 
            case RID_GETTER:
            case RID_SETTER:
-           case RID_IVAR:
              if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
                {
                  cp_parser_error (parser,
@@ -22786,7 +22958,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                  else
                    cp_lexer_consume_token (parser->lexer);
                }
-             else if (keyword == RID_GETTER)
+             else
                {
                  if (property_getter_ident != NULL_TREE)
                    cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
@@ -22794,14 +22966,6 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                    property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
                  cp_lexer_consume_token (parser->lexer);
                }
-             else /* RID_IVAR, this case will go away.  */
-               {
-                 if (property_ivar_ident != NULL_TREE)
-                   cp_parser_error (parser, "the %<ivar%> attribute may only be specified once");
-                 else
-                   property_ivar_ident = cp_lexer_peek_token (parser->lexer)->u.value;
-                 cp_lexer_consume_token (parser->lexer);
-               }
              break;
            default:
              cp_parser_error (parser, "unknown property attribute");
@@ -22852,9 +23016,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                                       property_readonly, property_readwrite,
                                       property_assign, property_retain,
                                       property_copy, property_nonatomic,
-                                      property_getter_ident, property_setter_ident,
-                                      /* The following two will be removed.  */
-                                      property_copies, property_ivar_ident);
+                                      property_getter_ident, property_setter_ident);
     }
   
   cp_parser_consume_semicolon_at_end_of_statement (parser);