diff options
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 9385344..8f6ea25 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2086,9 +2086,11 @@ static tree cp_parser_objc_selector static tree cp_parser_objc_protocol_refs_opt (cp_parser *); static void cp_parser_objc_declaration - (cp_parser *); + (cp_parser *, tree); static tree cp_parser_objc_statement (cp_parser *); +static bool cp_parser_objc_valid_prefix_attributes + (cp_parser* parser, tree *attrib); /* Utility Routines */ @@ -9285,6 +9287,7 @@ cp_parser_declaration (cp_parser* parser) cp_token token2; int saved_pedantic; void *p; + tree attributes = NULL_TREE; /* Check for the `__extension__' keyword. */ if (cp_parser_extension_opt (parser, &saved_pedantic)) @@ -9362,7 +9365,11 @@ cp_parser_declaration (cp_parser* parser) cp_parser_namespace_definition (parser); /* Objective-C++ declaration/definition. */ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword)) - cp_parser_objc_declaration (parser); + cp_parser_objc_declaration (parser, NULL_TREE); + else if (c_dialect_objc () + && token1.keyword == RID_ATTRIBUTE + && cp_parser_objc_valid_prefix_attributes (parser, &attributes)) + cp_parser_objc_declaration (parser, attributes); /* We must have either a block declaration or a function definition. */ else @@ -21739,7 +21746,7 @@ cp_parser_objc_class_ivars (cp_parser* parser) /* Parse an Objective-C protocol declaration. */ static void -cp_parser_objc_protocol_declaration (cp_parser* parser) +cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) { tree proto, protorefs; cp_token *tok; @@ -21768,7 +21775,7 @@ cp_parser_objc_protocol_declaration (cp_parser* parser) { proto = cp_parser_identifier (parser); protorefs = cp_parser_objc_protocol_refs_opt (parser); - objc_start_protocol (proto, protorefs); + objc_start_protocol (proto, protorefs, attributes); cp_parser_objc_method_prototype_list (parser); } } @@ -21798,7 +21805,7 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super, /* Parse an Objective-C class interface. */ static void -cp_parser_objc_class_interface (cp_parser* parser) +cp_parser_objc_class_interface (cp_parser* parser, tree attributes) { tree name, super, categ, protos; @@ -21809,10 +21816,10 @@ cp_parser_objc_class_interface (cp_parser* parser) /* We have either a class or a category on our hands. */ if (categ) - objc_start_category_interface (name, categ, protos); + objc_start_category_interface (name, categ, protos, attributes); else { - objc_start_class_interface (name, super, protos); + objc_start_class_interface (name, super, protos, attributes); /* Handle instance variable declarations, if any. */ cp_parser_objc_class_ivars (parser); objc_continue_interface (); @@ -21858,11 +21865,31 @@ cp_parser_objc_end_implementation (cp_parser* parser) /* Parse an Objective-C declaration. */ static void -cp_parser_objc_declaration (cp_parser* parser) +cp_parser_objc_declaration (cp_parser* parser, tree attributes) { /* Try to figure out what kind of declaration is present. */ cp_token *kwd = cp_lexer_peek_token (parser->lexer); + if (attributes) + switch (kwd->keyword) + { + case RID_AT_ALIAS: + case RID_AT_CLASS: + case RID_AT_END: + error_at (kwd->location, "attributes may not be specified before" + " the %<@%D%> Objective-C++ keyword", + kwd->u.value); + attributes = NULL; + break; + case RID_AT_IMPLEMENTATION: + warning_at (kwd->location, OPT_Wattributes, + "prefix attributes are ignored before %<@%D%>", + kwd->u.value); + attributes = NULL; + default: + break; + } + switch (kwd->keyword) { case RID_AT_ALIAS: @@ -21872,10 +21899,10 @@ cp_parser_objc_declaration (cp_parser* parser) cp_parser_objc_class_declaration (parser); break; case RID_AT_PROTOCOL: - cp_parser_objc_protocol_declaration (parser); + cp_parser_objc_protocol_declaration (parser, attributes); break; case RID_AT_INTERFACE: - cp_parser_objc_class_interface (parser); + cp_parser_objc_class_interface (parser, attributes); break; case RID_AT_IMPLEMENTATION: cp_parser_objc_class_implementation (parser); @@ -22024,6 +22051,26 @@ cp_parser_objc_statement (cp_parser * parser) { return error_mark_node; } + +/* If we are compiling ObjC++ and we see an __attribute__ we neeed to + look ahead to see if an objc keyword follows the attributes. This + is to detect the use of prefix attributes on ObjC @interface and + @protocol. */ + +static bool +cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib) +{ + cp_lexer_save_tokens (parser->lexer); + *attrib = cp_parser_attributes_opt (parser); + gcc_assert (*attrib); + if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword)) + { + cp_lexer_commit_tokens (parser->lexer); + return true; + } + cp_lexer_rollback_tokens (parser->lexer); + return false; +} /* OpenMP 2.5 parsing routines. */ |