From: mrs Date: Tue, 17 May 2005 20:05:24 +0000 (+0000) Subject: Yet more Objective-C++... X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=7a4e126b786fe01c58939aeba255b0e2aad7b03b Yet more Objective-C++... * cp-objcp-common.h (cxx_get_alias_set): Move from here... (cxx_warn_unused_global_decl): Likewise. (cp_expr_size): Likewise. (cp_tree_size): Likewise. (cp_var_mod_type_p): Likewise. (cxx_initialize_diagnostics): Likewise. (cxx_types_compatible_p): Likewise. * cp-tree.h: to here. (do_poplevel): Add. * lex.c (D_OBJC): Add. (init_reswords): Add. * Make-lang.in (cp/pt.o): Add cp/cp-objcp-common.h. * parser.c: Add c-common.h include. * pt.c: Add c-common.h and cp-objcp-common.h includes. (template_args_equal): Use objc_comptypes as well. (tsubst_copy_and_build): Use objcp_tsubst_copy_and_build as well. * semantics.c (do_poplevel): Remove static. * decl.c (objc_mark_locals_volatile): Don't change decls that are already ok. * decl2.c (generate_ctor_or_dtor_function): Add code to initialize Objective C++ early enough. * lex.c (struct resword reswords): Add Objective-C++ support. * parser.c (cp_lexer_get_preprocessor_token): Add Objective-C++. (cp_parser_objc_message_receiver): Add. (cp_parser_objc_message_args): Likewise. (cp_parser_objc_message_expression): Likewise. (cp_parser_objc_encode_expression): Likewise. (cp_parser_objc_defs_expression): Likewise. (cp_parser_objc_protocol_expression): Likewise. (cp_parser_objc_selector_expression): Likewise. (cp_parser_objc_expression): Likewise. (cp_parser_objc_visibility_spec): Likewise. (cp_parser_objc_method_type): Likewise. (cp_parser_objc_protocol_qualifiers): Likewise. (cp_parser_objc_typename): Likewise. (cp_parser_objc_selector_p): Likewise. (cp_parser_objc_selector): Likewise. (cp_parser_objc_method_keyword_params): Likewise. (cp_parser_objc_method_tail_params_opt): Likewise. (cp_parser_objc_interstitial_code): Likewise. (cp_parser_objc_method_signature): Likewise. (cp_parser_objc_method_prototype_list): Likewise. (cp_parser_objc_method_definition_list): Likewise. (cp_parser_objc_class_ivars): Likewise. (cp_parser_objc_identifier_list): Likewise. (cp_parser_objc_alias_declaration): Likewise. (cp_parser_objc_class_declaration): Likewise. (cp_parser_objc_protocol_declaration): Likewise. (cp_parser_objc_protocol_refs_opt): Likewise. (cp_parser_objc_superclass_or_category): Likewise. (cp_parser_objc_class_interface): Likewise. (cp_parser_objc_class_implementation): Likewise. (cp_parser_objc_end_implementation): Likewise. (cp_parser_objc_declaration): Likewise. (cp_parser_objc_try_catch_finally_statement): Likewise. (cp_parser_objc_synchronized_statement): Likewise. (cp_parser_objc_throw_statement): Likewise. (cp_parser_objc_statement): Likewise. (cp_parser_primary_expression): Add Objective-C++. (cp_parser_statement): Likewise. (cp_parser_declaration): Likewise. (cp_parser_simple_type_specifier): Likewise. (cp_parser_type_name): Likewise. (cp_parser_parameter_declaration_list): Likewise. (cp_parser_member_declaration) Likewise. * tree.c: Include debug.h. * typeck.c (composite_pointer_type): Add Objective-C++ support. (finish_class_member_access_expr): Likewise. (build_function_call): Allow objc to rewrite FUNCTION_DECLs. (build_modify_expr): Allow objc to generate write barriers. * Make-lang.in (cp/tree.o): Add debug.h. * tree.c (lvalue_p_1, case CONST_DECL): Add. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99855 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d5a88e9d2db..e67d716d007 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,83 @@ +2005-05-17 Mike Stump + + Yet more Objective-C++... + + * cp-objcp-common.h (cxx_get_alias_set): Move from + here... + (cxx_warn_unused_global_decl): Likewise. + (cp_expr_size): Likewise. + (cp_tree_size): Likewise. + (cp_var_mod_type_p): Likewise. + (cxx_initialize_diagnostics): Likewise. + (cxx_types_compatible_p): Likewise. + * cp-tree.h: to here. + (do_poplevel): Add. + * lex.c (D_OBJC): Add. + (init_reswords): Add. + * Make-lang.in (cp/pt.o): Add cp/cp-objcp-common.h. + * parser.c: Add c-common.h include. + * pt.c: Add c-common.h and cp-objcp-common.h includes. + (template_args_equal): Use objc_comptypes as well. + (tsubst_copy_and_build): Use objcp_tsubst_copy_and_build as well. + * semantics.c (do_poplevel): Remove static. + + * decl.c (objc_mark_locals_volatile): Don't change decls that are + already ok. + * decl2.c (generate_ctor_or_dtor_function): Add code to initialize + Objective C++ early enough. + * lex.c (struct resword reswords): Add Objective-C++ support. + * parser.c (cp_lexer_get_preprocessor_token): Add Objective-C++. + (cp_parser_objc_message_receiver): Add. + (cp_parser_objc_message_args): Likewise. + (cp_parser_objc_message_expression): Likewise. + (cp_parser_objc_encode_expression): Likewise. + (cp_parser_objc_defs_expression): Likewise. + (cp_parser_objc_protocol_expression): Likewise. + (cp_parser_objc_selector_expression): Likewise. + (cp_parser_objc_expression): Likewise. + (cp_parser_objc_visibility_spec): Likewise. + (cp_parser_objc_method_type): Likewise. + (cp_parser_objc_protocol_qualifiers): Likewise. + (cp_parser_objc_typename): Likewise. + (cp_parser_objc_selector_p): Likewise. + (cp_parser_objc_selector): Likewise. + (cp_parser_objc_method_keyword_params): Likewise. + (cp_parser_objc_method_tail_params_opt): Likewise. + (cp_parser_objc_interstitial_code): Likewise. + (cp_parser_objc_method_signature): Likewise. + (cp_parser_objc_method_prototype_list): Likewise. + (cp_parser_objc_method_definition_list): Likewise. + (cp_parser_objc_class_ivars): Likewise. + (cp_parser_objc_identifier_list): Likewise. + (cp_parser_objc_alias_declaration): Likewise. + (cp_parser_objc_class_declaration): Likewise. + (cp_parser_objc_protocol_declaration): Likewise. + (cp_parser_objc_protocol_refs_opt): Likewise. + (cp_parser_objc_superclass_or_category): Likewise. + (cp_parser_objc_class_interface): Likewise. + (cp_parser_objc_class_implementation): Likewise. + (cp_parser_objc_end_implementation): Likewise. + (cp_parser_objc_declaration): Likewise. + (cp_parser_objc_try_catch_finally_statement): Likewise. + (cp_parser_objc_synchronized_statement): Likewise. + (cp_parser_objc_throw_statement): Likewise. + (cp_parser_objc_statement): Likewise. + (cp_parser_primary_expression): Add Objective-C++. + (cp_parser_statement): Likewise. + (cp_parser_declaration): Likewise. + (cp_parser_simple_type_specifier): Likewise. + (cp_parser_type_name): Likewise. + (cp_parser_parameter_declaration_list): Likewise. + (cp_parser_member_declaration) Likewise. + * tree.c: Include debug.h. + * typeck.c (composite_pointer_type): Add Objective-C++ support. + (finish_class_member_access_expr): Likewise. + (build_function_call): Allow objc to rewrite FUNCTION_DECLs. + (build_modify_expr): Allow objc to generate write barriers. + + * Make-lang.in (cp/tree.o): Add debug.h. + * tree.c (lvalue_p_1, case CONST_DECL): Add. + 2005-05-17 Jakub Jelinek PR c++/21454 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index eeb41290892..3bef02f3a58 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -255,14 +255,14 @@ cp/method.o: cp/method.c $(CXX_TREE_H) $(TM_H) toplev.h $(RTL_H) $(EXPR_H) \ cp/cvt.o: cp/cvt.c $(CXX_TREE_H) $(TM_H) cp/decl.h flags.h toplev.h convert.h cp/search.o: cp/search.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) cp/tree.o: cp/tree.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) \ - insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H) + insn-config.h integrate.h tree-inline.h real.h gt-cp-tree.h $(TARGET_H) debug.h cp/ptree.o: cp/ptree.c $(CXX_TREE_H) $(TM_H) cp/rtti.o: cp/rtti.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h convert.h cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.h \ cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \ except.h $(TM_P_H) -cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h \ +cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/cp-objcp-common.h \ toplev.h $(RTL_H) except.h tree-inline.h pointer-set.h gt-cp-pt.h cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_H) \ flags.h real.h $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H) diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h index 65a01c367f6..ca27351b02a 100644 --- a/gcc/cp/cp-objcp-common.h +++ b/gcc/cp/cp-objcp-common.h @@ -22,16 +22,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #ifndef GCC_CP_OBJCP_COMMON #define GCC_CP_OBJCP_COMMON -/* In cp/cp-objcp-common.c. */ - -extern HOST_WIDE_INT cxx_get_alias_set (tree); -extern bool cxx_warn_unused_global_decl (tree); -extern tree cp_expr_size (tree); -extern size_t cp_tree_size (enum tree_code); -extern bool cp_var_mod_type_p (tree, tree); -extern void cxx_initialize_diagnostics (struct diagnostic_context *); -extern int cxx_types_compatible_p (tree, tree); - /* In cp/cp-lang.c and objcp/objcp-lang.c. */ extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t, diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 39d472bdc08..1a2399b878f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4063,6 +4063,7 @@ extern void pop_to_parent_deferring_access_checks (void); extern void perform_deferred_access_checks (void); extern void perform_or_defer_access_check (tree, tree); extern void init_cp_semantics (void); +extern tree do_poplevel (tree); extern void add_decl_expr (tree); extern tree finish_expr_stmt (tree); extern tree begin_if_stmt (void); @@ -4329,6 +4330,16 @@ extern tree mangle_ref_init_variable (tree); /* in dump.c */ extern bool cp_dump_tree (void *, tree); +/* In cp/cp-objcp-common.c. */ + +extern HOST_WIDE_INT cxx_get_alias_set (tree); +extern bool cxx_warn_unused_global_decl (tree); +extern tree cp_expr_size (tree); +extern size_t cp_tree_size (enum tree_code); +extern bool cp_var_mod_type_p (tree, tree); +extern void cxx_initialize_diagnostics (struct diagnostic_context *); +extern int cxx_types_compatible_p (tree, tree); + /* in cp-gimplify.c */ extern int cp_gimplify_expr (tree *, tree *, tree *); extern void cp_genericize (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ac7608b76c3..529cfd51b00 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -419,19 +419,32 @@ objc_mark_locals_volatile (void *enclosing_blk) struct cp_binding_level *scope; for (scope = current_binding_level; - scope && scope != enclosing_blk && scope->kind == sk_block; + scope && scope != enclosing_blk; scope = scope->level_chain) { tree decl; for (decl = scope->names; decl; decl = TREE_CHAIN (decl)) { - if (TREE_CODE (decl) == VAR_DECL) + /* Do not mess with variables that are 'static' or (already) + 'volatile'. */ + if (!TREE_THIS_VOLATILE (decl) && !TREE_STATIC (decl) + && (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL)) { - DECL_REGISTER (decl) = 0; - TREE_THIS_VOLATILE (decl) = 1; + TREE_TYPE (decl) + = build_qualified_type (TREE_TYPE (decl), + (TYPE_QUALS (TREE_TYPE (decl)) + | TYPE_QUAL_VOLATILE)); + TREE_THIS_VOLATILE (decl) = 1; + TREE_SIDE_EFFECTS (decl) = 1; + DECL_REGISTER (decl) = 0; } - } + } + + /* Do not climb up past the current function. */ + if (scope->kind == sk_function_parms) + break; } } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index e11338f47c8..206cd6ba400 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2601,6 +2601,15 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority, global constructors and destructors. */ body = NULL_TREE; + /* For Objective-C++, we may need to initialize metadata found in this module. + This must be done _before_ any other static initializations. */ + if (c_dialect_objc () && (priority == DEFAULT_INIT_PRIORITY) + && constructor_p && objc_static_init_needed_p ()) + { + body = start_objects (function_key, priority); + static_ctors = objc_generate_static_init_call (static_ctors); + } + /* Call the static storage duration function with appropriate arguments. */ for (i = 0; VEC_iterate (tree, ssdf_decls, i, fndecl); ++i) diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index dacac18286f..21fe2a13581 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -175,6 +175,7 @@ struct resword _true_. */ #define D_EXT 0x01 /* GCC extension */ #define D_ASM 0x02 /* in C99, but has a switch to turn it off */ +#define D_OBJC 0x04 /* Objective C++ only */ CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT); @@ -279,6 +280,31 @@ static const struct resword reswords[] = { "wchar_t", RID_WCHAR, 0 }, { "while", RID_WHILE, 0 }, + /* The remaining keywords are specific to Objective-C++. NB: + All of them will remain _disabled_, since they are context- + sensitive. */ + + /* These ObjC keywords are recognized only immediately after + an '@'. NB: The following C++ keywords double as + ObjC keywords in this context: RID_CLASS, RID_PRIVATE, + RID_PROTECTED, RID_PUBLIC, RID_THROW, RID_TRY and RID_CATCH. */ + { "compatibility_alias", RID_AT_ALIAS, D_OBJC }, + { "defs", RID_AT_DEFS, D_OBJC }, + { "encode", RID_AT_ENCODE, D_OBJC }, + { "end", RID_AT_END, D_OBJC }, + { "implementation", RID_AT_IMPLEMENTATION, D_OBJC }, + { "interface", RID_AT_INTERFACE, D_OBJC }, + { "protocol", RID_AT_PROTOCOL, D_OBJC }, + { "selector", RID_AT_SELECTOR, D_OBJC }, + { "finally", RID_AT_FINALLY, D_OBJC }, + { "synchronized", RID_AT_SYNCHRONIZED, D_OBJC }, + /* These are recognized only in protocol-qualifier context. */ + { "bycopy", RID_BYCOPY, D_OBJC }, + { "byref", RID_BYREF, D_OBJC }, + { "in", RID_IN, D_OBJC }, + { "inout", RID_INOUT, D_OBJC }, + { "oneway", RID_ONEWAY, D_OBJC }, + { "out", RID_OUT, D_OBJC }, }; void @@ -287,6 +313,7 @@ init_reswords (void) unsigned int i; tree id; int mask = ((flag_no_asm ? D_ASM : 0) + | D_OBJC | (flag_no_gnu_keywords ? D_EXT : 0)); ridpointers = ggc_calloc ((int) RID_MAX, sizeof (tree)); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 56ff04928d4..7b58840cb3d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -36,6 +36,7 @@ #include "toplev.h" #include "output.h" #include "target.h" +#include "c-common.h" /* The lexer. */ @@ -408,6 +409,23 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , mapped to `const'. */ token->value = ridpointers[token->keyword]; } + /* Handle Objective-C++ keywords. */ + else if (token->type == CPP_AT_NAME) + { + token->type = CPP_KEYWORD; + switch (C_RID_CODE (token->value)) + { + /* Map 'class' to '@class', 'private' to '@private', etc. */ + case RID_CLASS: token->keyword = RID_AT_CLASS; break; + case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break; + case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break; + case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break; + case RID_THROW: token->keyword = RID_AT_THROW; break; + case RID_TRY: token->keyword = RID_AT_TRY; break; + case RID_CATCH: token->keyword = RID_AT_CATCH; break; + default: token->keyword = C_RID_CODE (token->value); + } + } else token->keyword = RID_MAX; } @@ -1642,6 +1660,35 @@ static bool cp_parser_extension_opt static void cp_parser_label_declaration (cp_parser *); +/* Objective-C++ Productions */ + +static tree cp_parser_objc_message_receiver + (cp_parser *); +static tree cp_parser_objc_message_args + (cp_parser *); +static tree cp_parser_objc_message_expression + (cp_parser *); +static tree cp_parser_objc_encode_expression + (cp_parser *); +static tree cp_parser_objc_defs_expression + (cp_parser *); +static tree cp_parser_objc_protocol_expression + (cp_parser *); +static tree cp_parser_objc_selector_expression + (cp_parser *); +static tree cp_parser_objc_expression + (cp_parser *); +static bool cp_parser_objc_selector_p + (enum cpp_ttype); +static tree cp_parser_objc_selector + (cp_parser *); +static tree cp_parser_objc_protocol_refs_opt + (cp_parser *); +static void cp_parser_objc_declaration + (cp_parser *); +static tree cp_parser_objc_statement + (cp_parser *); + /* Utility Routines */ static tree cp_parser_lookup_name @@ -2652,6 +2699,11 @@ cp_parser_translation_unit (cp_parser* parser) ( compound-statement ) __builtin_va_arg ( assignment-expression , type-id ) + Objective-C++ Extension: + + primary-expression: + objc-expression + literal: __null @@ -2878,6 +2930,12 @@ cp_parser_primary_expression (cp_parser *parser, case RID_OFFSETOF: return cp_parser_builtin_offsetof (parser); + /* Objective-C++ expressions. */ + case RID_AT_ENCODE: + case RID_AT_PROTOCOL: + case RID_AT_SELECTOR: + return cp_parser_objc_expression (parser); + default: cp_parser_error (parser, "expected primary-expression"); return error_mark_node; @@ -2926,6 +2984,11 @@ cp_parser_primary_expression (cp_parser *parser, been issued. */ if (ambiguous_p) return error_mark_node; + + /* In Objective-C++, an instance variable (ivar) may be preferred + to whatever cp_parser_lookup_name() found. */ + decl = objc_lookup_ivar (decl, id_expression); + /* If name lookup gives us a SCOPE_REF, then the qualifying scope was dependent. Just propagate the name. */ @@ -2976,6 +3039,11 @@ cp_parser_primary_expression (cp_parser *parser, /* Anything else is an error. */ default: + /* ...unless we have an Objective-C++ message or string literal, that is. */ + if (c_dialect_objc () + && (token->type == CPP_OPEN_SQUARE || token->type == CPP_OBJC_STRING)) + return cp_parser_objc_expression (parser); + cp_parser_error (parser, "expected primary-expression"); return error_mark_node; } @@ -5954,6 +6022,15 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr) statement = cp_parser_jump_statement (parser); break; + /* Objective-C++ exception-handling constructs. */ + case RID_AT_TRY: + case RID_AT_CATCH: + case RID_AT_FINALLY: + case RID_AT_SYNCHRONIZED: + case RID_AT_THROW: + statement = cp_parser_objc_statement (parser); + break; + case RID_TRY: statement = cp_parser_try_block (parser); break; @@ -6856,6 +6933,9 @@ cp_parser_declaration (cp_parser* parser) /* An unnamed namespace definition. */ || token2.type == CPP_OPEN_BRACE)) 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); /* We must have either a block declaration or a function definition. */ else @@ -9596,7 +9676,26 @@ cp_parser_simple_type_specifier (cp_parser* parser, followed by a "<". That usually indicates that the user thought that the type was a template. */ if (type && type != error_mark_node) - cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type)); + { + /* 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. */ + if (c_dialect_objc () + && (objc_is_id (type) || objc_is_class_name (type))) + { + tree protos = cp_parser_objc_protocol_refs_opt (parser); + tree qual_type = objc_get_protocol_qualified_type (type, protos); + + /* Clobber the "unqualified" type previously entered into + DECL_SPECS with the new, improved protocol-qualifed version. */ + if (decl_specs) + decl_specs->type = qual_type; + + return qual_type; + } + + cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type)); + } return type; } @@ -9642,6 +9741,17 @@ cp_parser_type_name (cp_parser* parser) /* Look up the type-name. */ type_decl = cp_parser_lookup_name_simple (parser, identifier); + + if (TREE_CODE (type_decl) != TYPE_DECL + && (objc_is_id (identifier) || objc_is_class_name (identifier))) + { + /* See if this is an Objective-C type. */ + tree protos = cp_parser_objc_protocol_refs_opt (parser); + tree type = objc_get_protocol_qualified_type (identifier, protos); + 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) { @@ -11748,7 +11858,10 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) /* Peek at the next token. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN) - || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS) + /* These are for Objective-C++ */ + || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON) + || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) /* The parameter-declaration-list is complete. */ break; else if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) @@ -13091,6 +13204,22 @@ cp_parser_member_declaration (cp_parser* parser) return; } + /* Check for @defs. */ + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS)) + { + tree ivar, member; + tree ivar_chains = cp_parser_objc_defs_expression (parser); + ivar = ivar_chains; + while (ivar) + { + member = ivar; + ivar = TREE_CHAIN (member); + TREE_CHAIN (member) = NULL_TREE; + finish_member_declaration (member); + } + return; + } + /* Parse the decl-specifier-seq. */ cp_parser_decl_specifier_seq (parser, CP_PARSER_FLAGS_OPTIONAL, @@ -16052,7 +16181,1109 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser) { return parser->allow_gnu_extensions_p; } + +/* Objective-C++ Productions */ + + +/* Parse an Objective-C expression, which feeds into a primary-expression + above. + + objc-expression: + objc-message-expression + objc-string-literal + objc-encode-expression + objc-protocol-expression + objc-selector-expression + + Returns a tree representation of the expression. */ + +static tree +cp_parser_objc_expression (cp_parser* parser) +{ + /* Try to figure out what kind of declaration is present. */ + cp_token *kwd = cp_lexer_peek_token (parser->lexer); + + switch (kwd->type) + { + case CPP_OPEN_SQUARE: + return cp_parser_objc_message_expression (parser); + + case CPP_OBJC_STRING: + kwd = cp_lexer_consume_token (parser->lexer); + return objc_build_string_object (kwd->value); + + case CPP_KEYWORD: + switch (kwd->keyword) + { + case RID_AT_ENCODE: + return cp_parser_objc_encode_expression (parser); + + case RID_AT_PROTOCOL: + return cp_parser_objc_protocol_expression (parser); + + case RID_AT_SELECTOR: + return cp_parser_objc_selector_expression (parser); + + default: + break; + } + default: + error ("misplaced `@%D' Objective-C++ construct", kwd->value); + cp_parser_skip_to_end_of_block_or_statement (parser); + } + + return error_mark_node; +} + +/* Parse an Objective-C message expression. + + objc-message-expression: + [ objc-message-receiver objc-message-args ] + + Returns a representation of an Objective-C message. */ + +static tree +cp_parser_objc_message_expression (cp_parser* parser) +{ + tree receiver, messageargs; + + cp_lexer_consume_token (parser->lexer); /* Eat '['. */ + receiver = cp_parser_objc_message_receiver (parser); + messageargs = cp_parser_objc_message_args (parser); + cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); + + return objc_build_message_expr (build_tree_list (receiver, messageargs)); +} + +/* Parse an objc-message-receiver. + + objc-message-receiver: + type-name + expression + + Returns a representation of the type or expression. */ + +static tree +cp_parser_objc_message_receiver (cp_parser* parser) +{ + tree rcv; + bool class_scope_p, template_p; + + /* An Objective-C message receiver may be either (1) a type + or (2) an expression. */ + cp_parser_parse_tentatively (parser); + rcv = cp_parser_expression (parser, false); + + if (cp_parser_parse_definitely (parser)) + return rcv; + + /* Look for the optional `::' operator. */ + cp_parser_global_scope_opt (parser, false); + /* Look for the nested-name-specifier. */ + cp_parser_nested_name_specifier_opt (parser, + /*typename_keyword_p=*/true, + /*check_dependency_p=*/true, + /*type_p=*/true, + /*is_declaration=*/true); + class_scope_p = (parser->scope && TYPE_P (parser->scope)); + template_p = class_scope_p && cp_parser_optional_template_keyword (parser); + /* Finally, look for the class-name. */ + rcv = cp_parser_class_name (parser, + class_scope_p, + template_p, + /*type_p=*/true, + /*check_dependency_p=*/true, + /*class_head_p=*/false, + /*is_declaration=*/true); + + return objc_get_class_reference (rcv); +} + +/* Parse the arguments and selectors comprising an Objective-C message. + + objc-message-args: + objc-selector + objc-selector-args + objc-selector-args , objc-comma-args + + objc-selector-args: + objc-selector [opt] : assignment-expression + objc-selector-args objc-selector [opt] : assignment-expression + + objc-comma-args: + assignment-expression + objc-comma-args , assignment-expression + + Returns a TREE_LIST, with TREE_PURPOSE containing a list of + selector arguments and TREE_VALUE containing a list of comma + arguments. */ + +static tree +cp_parser_objc_message_args (cp_parser* parser) +{ + tree sel_args = NULL_TREE, addl_args = NULL_TREE; + bool maybe_unary_selector_p = true; + cp_token *token = cp_lexer_peek_token (parser->lexer); + + while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) + { + tree selector = NULL_TREE, arg; + + if (token->type != CPP_COLON) + selector = cp_parser_objc_selector (parser); + + /* Detect if we have a unary selector. */ + if (maybe_unary_selector_p + && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) + return build_tree_list (selector, NULL_TREE); + + maybe_unary_selector_p = false; + cp_parser_require (parser, CPP_COLON, "`:'"); + arg = cp_parser_assignment_expression (parser, false); + + sel_args + = chainon (sel_args, + build_tree_list (selector, arg)); + + token = cp_lexer_peek_token (parser->lexer); + } + + /* Handle non-selector arguments, if any. */ + while (token->type == CPP_COMMA) + { + tree arg; + + cp_lexer_consume_token (parser->lexer); + arg = cp_parser_assignment_expression (parser, false); + + addl_args + = chainon (addl_args, + build_tree_list (NULL_TREE, arg)); + + token = cp_lexer_peek_token (parser->lexer); + } + + return build_tree_list (sel_args, addl_args); +} + +/* Parse an Objective-C encode expression. + + objc-encode-expression: + @encode objc-typename + + Returns an encoded representation of the type argument. */ + +static tree +cp_parser_objc_encode_expression (cp_parser* parser) +{ + tree type; + + cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */ + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + type = complete_type (cp_parser_type_id (parser)); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + + if (!type) + { + error ("`@encode' must specify a type as an argument"); + return error_mark_node; + } + + return objc_build_encode_expr (type); +} + +/* Parse an Objective-C @defs expression. */ + +static tree +cp_parser_objc_defs_expression (cp_parser *parser) +{ + tree name; + + cp_lexer_consume_token (parser->lexer); /* Eat '@defs'. */ + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + name = cp_parser_identifier (parser); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + + return objc_get_class_ivars (name); +} + +/* Parse an Objective-C protocol expression. + + objc-protocol-expression: + @protocol ( identifier ) + + Returns a representation of the protocol expression. */ + +static tree +cp_parser_objc_protocol_expression (cp_parser* parser) +{ + tree proto; + + cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */ + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + proto = cp_parser_identifier (parser); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + + return objc_build_protocol_expr (proto); +} + +/* Parse an Objective-C selector expression. + + objc-selector-expression: + @selector ( objc-method-signature ) + + objc-method-signature: + objc-selector + objc-selector-seq + + objc-selector-seq: + objc-selector : + objc-selector-seq objc-selector : + + Returns a representation of the method selector. */ + +static tree +cp_parser_objc_selector_expression (cp_parser* parser) +{ + tree sel_seq = NULL_TREE; + bool maybe_unary_selector_p = true; + cp_token *token; + + cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */ + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + token = cp_lexer_peek_token (parser->lexer); + + while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) + { + tree selector = NULL_TREE; + + if (token->type != CPP_COLON) + selector = cp_parser_objc_selector (parser); + + /* Detect if we have a unary selector. */ + if (maybe_unary_selector_p + && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) + { + sel_seq = selector; + goto finish_selector; + } + + maybe_unary_selector_p = false; + cp_parser_require (parser, CPP_COLON, "`:'"); + + sel_seq + = chainon (sel_seq, + build_tree_list (selector, NULL_TREE)); + + token = cp_lexer_peek_token (parser->lexer); + } + + finish_selector: + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + + return objc_build_selector_expr (sel_seq); +} + +/* Parse a list of identifiers. + + objc-identifier-list: + identifier + objc-identifier-list , identifier + + Returns a TREE_LIST of identifier nodes. */ + +static tree +cp_parser_objc_identifier_list (cp_parser* parser) +{ + tree list = build_tree_list (NULL_TREE, cp_parser_identifier (parser)); + cp_token *sep = cp_lexer_peek_token (parser->lexer); + + while (sep->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); /* Eat ','. */ + list = chainon (list, + build_tree_list (NULL_TREE, + cp_parser_identifier (parser))); + sep = cp_lexer_peek_token (parser->lexer); + } + + return list; +} + +/* Parse an Objective-C alias declaration. + + objc-alias-declaration: + @compatibility_alias identifier identifier ; + + This function registers the alias mapping with the Objective-C front-end. + It returns nothing. */ + +static void +cp_parser_objc_alias_declaration (cp_parser* parser) +{ + tree alias, orig; + + cp_lexer_consume_token (parser->lexer); /* Eat '@compatibility_alias'. */ + alias = cp_parser_identifier (parser); + orig = cp_parser_identifier (parser); + objc_declare_alias (alias, orig); + cp_parser_consume_semicolon_at_end_of_statement (parser); +} + +/* Parse an Objective-C class forward-declaration. + + objc-class-declaration: + @class objc-identifier-list ; + + The function registers the forward declarations with the Objective-C + front-end. It returns nothing. */ + +static void +cp_parser_objc_class_declaration (cp_parser* parser) +{ + cp_lexer_consume_token (parser->lexer); /* Eat '@class'. */ + objc_declare_class (cp_parser_objc_identifier_list (parser)); + cp_parser_consume_semicolon_at_end_of_statement (parser); +} + +/* Parse a list of Objective-C protocol references. + + objc-protocol-refs-opt: + objc-protocol-refs [opt] + + objc-protocol-refs: + < objc-identifier-list > + + Returns a TREE_LIST of identifiers, if any. */ + +static tree +cp_parser_objc_protocol_refs_opt (cp_parser* parser) +{ + tree protorefs = NULL_TREE; + + if(cp_lexer_next_token_is (parser->lexer, CPP_LESS)) + { + cp_lexer_consume_token (parser->lexer); /* Eat '<'. */ + protorefs = cp_parser_objc_identifier_list (parser); + cp_parser_require (parser, CPP_GREATER, "`>'"); + } + + return protorefs; +} + +/* Parse a Objective-C visibility specification. */ + +static void +cp_parser_objc_visibility_spec (cp_parser* parser) +{ + cp_token *vis = cp_lexer_peek_token (parser->lexer); + + switch (vis->keyword) + { + case RID_AT_PRIVATE: + objc_set_visibility (2); + break; + case RID_AT_PROTECTED: + objc_set_visibility (0); + break; + case RID_AT_PUBLIC: + objc_set_visibility (1); + break; + default: + return; + } + /* Eat '@private'/'@protected'/'@public'. */ + cp_lexer_consume_token (parser->lexer); +} + +/* Parse an Objective-C method type. */ + +static void +cp_parser_objc_method_type (cp_parser* parser) +{ + objc_set_method_type + (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS + ? PLUS_EXPR + : MINUS_EXPR); +} + +/* Parse an Objective-C protocol qualifier. */ + +static tree +cp_parser_objc_protocol_qualifiers (cp_parser* parser) +{ + tree quals = NULL_TREE, node; + cp_token *token = cp_lexer_peek_token (parser->lexer); + + node = token->value; + + while (node && TREE_CODE (node) == IDENTIFIER_NODE + && (node == ridpointers [(int) RID_IN] + || node == ridpointers [(int) RID_OUT] + || node == ridpointers [(int) RID_INOUT] + || node == ridpointers [(int) RID_BYCOPY] + || node == ridpointers [(int) RID_BYREF] + || node == ridpointers [(int) RID_ONEWAY])) + { + quals = tree_cons (NULL_TREE, node, quals); + cp_lexer_consume_token (parser->lexer); + token = cp_lexer_peek_token (parser->lexer); + node = token->value; + } + + return quals; +} + +/* Parse an Objective-C typename. */ + +static tree +cp_parser_objc_typename (cp_parser* parser) +{ + tree typename = NULL_TREE; + + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + { + tree proto_quals, cp_type = NULL_TREE; + + cp_lexer_consume_token (parser->lexer); /* Eat '('. */ + proto_quals = cp_parser_objc_protocol_qualifiers (parser); + + /* An ObjC type name may consist of just protocol qualifiers, in which + case the type shall default to 'id'. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) + cp_type = cp_parser_type_id (parser); + + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + typename = build_tree_list (proto_quals, cp_type); + } + + return typename; +} + +/* Check to see if TYPE refers to an Objective-C selector name. */ + +static bool +cp_parser_objc_selector_p (enum cpp_ttype type) +{ + return (type == CPP_NAME || type == CPP_KEYWORD + || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND + || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT + || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ + || type == CPP_XOR || type == CPP_XOR_EQ); +} + +/* Parse an Objective-C selector. */ + +static tree +cp_parser_objc_selector (cp_parser* parser) +{ + cp_token *token = cp_lexer_consume_token (parser->lexer); + + if (!cp_parser_objc_selector_p (token->type)) + { + error ("invalid Objective-C++ selector name"); + return error_mark_node; + } + + /* C++ operator names are allowed to appear in ObjC selectors. */ + switch (token->type) + { + case CPP_AND_AND: return get_identifier ("and"); + case CPP_AND_EQ: return get_identifier ("and_eq"); + case CPP_AND: return get_identifier ("bitand"); + case CPP_OR: return get_identifier ("bitor"); + case CPP_COMPL: return get_identifier ("compl"); + case CPP_NOT: return get_identifier ("not"); + case CPP_NOT_EQ: return get_identifier ("not_eq"); + case CPP_OR_OR: return get_identifier ("or"); + case CPP_OR_EQ: return get_identifier ("or_eq"); + case CPP_XOR: return get_identifier ("xor"); + case CPP_XOR_EQ: return get_identifier ("xor_eq"); + default: return token->value; + } +} + +/* Parse an Objective-C params list. */ + +static tree +cp_parser_objc_method_keyword_params (cp_parser* parser) +{ + tree params = NULL_TREE; + bool maybe_unary_selector_p = true; + cp_token *token = cp_lexer_peek_token (parser->lexer); + + while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) + { + tree selector = NULL_TREE, typename, identifier; + + if (token->type != CPP_COLON) + selector = cp_parser_objc_selector (parser); + + /* Detect if we have a unary selector. */ + if (maybe_unary_selector_p + && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) + return selector; + + maybe_unary_selector_p = false; + cp_parser_require (parser, CPP_COLON, "`:'"); + typename = cp_parser_objc_typename (parser); + identifier = cp_parser_identifier (parser); + + params + = chainon (params, + objc_build_keyword_decl (selector, + typename, + identifier)); + + token = cp_lexer_peek_token (parser->lexer); + } + + return params; +} + +/* Parse the non-keyword Objective-C params. */ + +static tree +cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp) +{ + tree params = make_node (TREE_LIST); + cp_token *token = cp_lexer_peek_token (parser->lexer); + *ellipsisp = false; /* Initially, assume no ellipsis. */ + + while (token->type == CPP_COMMA) + { + cp_parameter_declarator *parmdecl; + tree parm; + + cp_lexer_consume_token (parser->lexer); /* Eat ','. */ + token = cp_lexer_peek_token (parser->lexer); + + if (token->type == CPP_ELLIPSIS) + { + cp_lexer_consume_token (parser->lexer); /* Eat '...'. */ + *ellipsisp = true; + break; + } + + parmdecl = cp_parser_parameter_declaration (parser, false, NULL); + parm = grokdeclarator (parmdecl->declarator, + &parmdecl->decl_specifiers, + PARM, /*initialized=*/0, + /*attrlist=*/NULL); + + chainon (params, build_tree_list (NULL_TREE, parm)); + token = cp_lexer_peek_token (parser->lexer); + } + + return params; +} + +/* Parse a linkage specification, a pragma, an extra semicolon or a block. */ + +static void +cp_parser_objc_interstitial_code (cp_parser* parser) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + + /* If the next token is `extern' and the following token is a string + literal, then we have a linkage specification. */ + if (token->keyword == RID_EXTERN + && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2))) + cp_parser_linkage_specification (parser); + /* Handle #pragma, if any. */ + else if (token->type == CPP_PRAGMA) + cp_lexer_handle_pragma (parser->lexer); + /* Allow stray semicolons. */ + else if (token->type == CPP_SEMICOLON) + cp_lexer_consume_token (parser->lexer); + /* Finally, try to parse a block-declaration, or a function-definition. */ + else + cp_parser_block_declaration (parser, /*statement_p=*/false); +} + +/* Parse a method signature. */ + +static tree +cp_parser_objc_method_signature (cp_parser* parser) +{ + tree rettype, kwdparms, optparms; + bool ellipsis = false; + + cp_parser_objc_method_type (parser); + rettype = cp_parser_objc_typename (parser); + kwdparms = cp_parser_objc_method_keyword_params (parser); + optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis); + + return objc_build_method_signature (rettype, kwdparms, optparms, ellipsis); +} + +/* Pars an Objective-C method prototype list. */ + +static void +cp_parser_objc_method_prototype_list (cp_parser* parser) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + + while (token->keyword != RID_AT_END) + { + if (token->type == CPP_PLUS || token->type == CPP_MINUS) + { + objc_add_method_declaration + (cp_parser_objc_method_signature (parser)); + cp_parser_consume_semicolon_at_end_of_statement (parser); + } + else + /* Allow for interspersed non-ObjC++ code. */ + cp_parser_objc_interstitial_code (parser); + + token = cp_lexer_peek_token (parser->lexer); + } + + cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */ + objc_finish_interface (); +} + +/* Parse an Objective-C method definition list. */ + +static void +cp_parser_objc_method_definition_list (cp_parser* parser) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + + while (token->keyword != RID_AT_END) + { + tree meth; + + if (token->type == CPP_PLUS || token->type == CPP_MINUS) + { + push_deferring_access_checks (dk_deferred); + objc_start_method_definition + (cp_parser_objc_method_signature (parser)); + + /* For historical reasons, we accept an optional semicolon. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + cp_lexer_consume_token (parser->lexer); + + perform_deferred_access_checks (); + stop_deferring_access_checks (); + meth = cp_parser_function_definition_after_declarator (parser, + false); + pop_deferring_access_checks (); + objc_finish_method_definition (meth); + } + else + /* Allow for interspersed non-ObjC++ code. */ + cp_parser_objc_interstitial_code (parser); + + token = cp_lexer_peek_token (parser->lexer); + } + + cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */ + objc_finish_implementation (); +} + +/* Parse Objective-C ivars. */ + +static void +cp_parser_objc_class_ivars (cp_parser* parser) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + + if (token->type != CPP_OPEN_BRACE) + return; /* No ivars specified. */ + + cp_lexer_consume_token (parser->lexer); /* Eat '{'. */ + token = cp_lexer_peek_token (parser->lexer); + + while (token->type != CPP_CLOSE_BRACE) + { + cp_decl_specifier_seq declspecs; + int decl_class_or_enum_p; + tree prefix_attributes; + + cp_parser_objc_visibility_spec (parser); + + if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) + break; + + cp_parser_decl_specifier_seq (parser, + CP_PARSER_FLAGS_OPTIONAL, + &declspecs, + &decl_class_or_enum_p); + prefix_attributes = declspecs.attributes; + declspecs.attributes = NULL_TREE; + + /* Keep going until we hit the `;' at the end of the + declaration. */ + while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + { + tree width = NULL_TREE, attributes, first_attribute, decl; + cp_declarator *declarator = NULL; + int ctor_dtor_or_conv_p; + + /* Check for a (possibly unnamed) bitfield declaration. */ + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_COLON) + goto eat_colon; + + if (token->type == CPP_NAME + && (cp_lexer_peek_nth_token (parser->lexer, 2)->type + == CPP_COLON)) + { + /* Get the name of the bitfield. */ + declarator = make_id_declarator (NULL_TREE, + cp_parser_identifier (parser)); + + eat_colon: + cp_lexer_consume_token (parser->lexer); /* Eat ':'. */ + /* Get the width of the bitfield. */ + width + = cp_parser_constant_expression (parser, + /*allow_non_constant=*/false, + NULL); + } + else + { + /* Parse the declarator. */ + declarator + = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, + &ctor_dtor_or_conv_p, + /*parenthesized_p=*/NULL, + /*member_p=*/false); + } + + /* Look for attributes that apply to the ivar. */ + attributes = cp_parser_attributes_opt (parser); + /* Remember which attributes are prefix attributes and + which are not. */ + first_attribute = attributes; + /* Combine the attributes. */ + attributes = chainon (prefix_attributes, attributes); + + if (width) + { + /* Create the bitfield declaration. */ + decl = grokbitfield (declarator, &declspecs, width); + cplus_decl_attributes (&decl, attributes, /*flags=*/0); + } + else + decl = grokfield (declarator, &declspecs, NULL_TREE, + NULL_TREE, attributes); + + /* Add the instance variable. */ + objc_add_instance_variable (decl); + + /* Reset PREFIX_ATTRIBUTES. */ + while (attributes && TREE_CHAIN (attributes) != first_attribute) + attributes = TREE_CHAIN (attributes); + if (attributes) + TREE_CHAIN (attributes) = NULL_TREE; + + token = cp_lexer_peek_token (parser->lexer); + + if (token->type == CPP_COMMA) + { + cp_lexer_consume_token (parser->lexer); /* Eat ','. */ + continue; + } + break; + } + + cp_parser_consume_semicolon_at_end_of_statement (parser); + token = cp_lexer_peek_token (parser->lexer); + } + + cp_lexer_consume_token (parser->lexer); /* Eat '}'. */ + /* For historical reasons, we accept an optional semicolon. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + cp_lexer_consume_token (parser->lexer); +} + +/* Parse an Objective-C protocol declaration. */ + +static void +cp_parser_objc_protocol_declaration (cp_parser* parser) +{ + tree proto, protorefs; + cp_token *tok; + + cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */ + if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + { + error ("identifier expected after `@protocol'"); + goto finish; + } + + /* See if we have a foward declaration or a definition. */ + tok = cp_lexer_peek_nth_token (parser->lexer, 2); + + /* Try a forward declaration first. */ + if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON) + { + objc_declare_protocols (cp_parser_objc_identifier_list (parser)); + finish: + cp_parser_consume_semicolon_at_end_of_statement (parser); + } + + /* Ok, we got a full-fledged definition (or at least should). */ + else + { + proto = cp_parser_identifier (parser); + protorefs = cp_parser_objc_protocol_refs_opt (parser); + objc_start_protocol (proto, protorefs); + cp_parser_objc_method_prototype_list (parser); + } +} + +/* Parse an Objective-C superclass or category. */ + +static void +cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super, + tree *categ) +{ + cp_token *next = cp_lexer_peek_token (parser->lexer); + + *super = *categ = NULL_TREE; + if (next->type == CPP_COLON) + { + cp_lexer_consume_token (parser->lexer); /* Eat ':'. */ + *super = cp_parser_identifier (parser); + } + else if (next->type == CPP_OPEN_PAREN) + { + cp_lexer_consume_token (parser->lexer); /* Eat '('. */ + *categ = cp_parser_identifier (parser); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + } +} + +/* Parse an Objective-C class interface. */ + +static void +cp_parser_objc_class_interface (cp_parser* parser) +{ + tree name, super, categ, protos; + + cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */ + name = cp_parser_identifier (parser); + cp_parser_objc_superclass_or_category (parser, &super, &categ); + protos = cp_parser_objc_protocol_refs_opt (parser); + + /* We have either a class or a category on our hands. */ + if (categ) + objc_start_category_interface (name, categ, protos); + else + { + objc_start_class_interface (name, super, protos); + /* Handle instance variable declarations, if any. */ + cp_parser_objc_class_ivars (parser); + objc_continue_interface (); + } + + cp_parser_objc_method_prototype_list (parser); +} + +/* Parse an Objective-C class implementation. */ + +static void +cp_parser_objc_class_implementation (cp_parser* parser) +{ + tree name, super, categ; + + cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */ + name = cp_parser_identifier (parser); + cp_parser_objc_superclass_or_category (parser, &super, &categ); + + /* We have either a class or a category on our hands. */ + if (categ) + objc_start_category_implementation (name, categ); + else + { + objc_start_class_implementation (name, super); + /* Handle instance variable declarations, if any. */ + cp_parser_objc_class_ivars (parser); + objc_continue_implementation (); + } + + cp_parser_objc_method_definition_list (parser); +} + +/* Consume the @end token and finish off the implementation. */ + +static void +cp_parser_objc_end_implementation (cp_parser* parser) +{ + cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */ + objc_finish_implementation (); +} + +/* Parse an Objective-C declaration. */ + +static void +cp_parser_objc_declaration (cp_parser* parser) +{ + /* Try to figure out what kind of declaration is present. */ + cp_token *kwd = cp_lexer_peek_token (parser->lexer); + + switch (kwd->keyword) + { + case RID_AT_ALIAS: + cp_parser_objc_alias_declaration (parser); + break; + case RID_AT_CLASS: + cp_parser_objc_class_declaration (parser); + break; + case RID_AT_PROTOCOL: + cp_parser_objc_protocol_declaration (parser); + break; + case RID_AT_INTERFACE: + cp_parser_objc_class_interface (parser); + break; + case RID_AT_IMPLEMENTATION: + cp_parser_objc_class_implementation (parser); + break; + case RID_AT_END: + cp_parser_objc_end_implementation (parser); + break; + default: + error ("misplaced `@%D' Objective-C++ construct", kwd->value); + cp_parser_skip_to_end_of_block_or_statement (parser); + } +} + +/* Parse an Objective-C try-catch-finally statement. + + objc-try-catch-finally-stmt: + @try compound-statement objc-catch-clause-seq [opt] + objc-finally-clause [opt] + + objc-catch-clause-seq: + objc-catch-clause objc-catch-clause-seq [opt] + + objc-catch-clause: + @catch ( exception-declaration ) compound-statement + + objc-finally-clause + @finally compound-statement + + Returns NULL_TREE. */ + +static tree +cp_parser_objc_try_catch_finally_statement (cp_parser *parser) { + location_t location; + tree stmt; + + cp_parser_require_keyword (parser, RID_AT_TRY, "`@try'"); + location = cp_lexer_peek_token (parser->lexer)->location; + /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST + node, lest it get absorbed into the surrounding block. */ + stmt = push_stmt_list (); + cp_parser_compound_statement (parser, NULL, false); + objc_begin_try_stmt (location, pop_stmt_list (stmt)); + + while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH)) + { + cp_parameter_declarator *parmdecl; + tree parm; + + cp_lexer_consume_token (parser->lexer); + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + parmdecl = cp_parser_parameter_declaration (parser, false, NULL); + parm = grokdeclarator (parmdecl->declarator, + &parmdecl->decl_specifiers, + PARM, /*initialized=*/0, + /*attrlist=*/NULL); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + objc_begin_catch_clause (parm); + cp_parser_compound_statement (parser, NULL, false); + objc_finish_catch_clause (); + } + + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY)) + { + cp_lexer_consume_token (parser->lexer); + location = cp_lexer_peek_token (parser->lexer)->location; + /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST + node, lest it get absorbed into the surrounding block. */ + stmt = push_stmt_list (); + cp_parser_compound_statement (parser, NULL, false); + objc_build_finally_clause (location, pop_stmt_list (stmt)); + } + + return objc_finish_try_stmt (); +} + +/* Parse an Objective-C synchronized statement. + + objc-synchronized-stmt: + @synchronized ( expression ) compound-statement + + Returns NULL_TREE. */ + +static tree +cp_parser_objc_synchronized_statement (cp_parser *parser) { + location_t location; + tree lock, stmt; + + cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "`@synchronized'"); + + location = cp_lexer_peek_token (parser->lexer)->location; + cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); + lock = cp_parser_expression (parser, false); + cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); + + /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST + node, lest it get absorbed into the surrounding block. */ + stmt = push_stmt_list (); + cp_parser_compound_statement (parser, NULL, false); + + return objc_build_synchronized (location, lock, pop_stmt_list (stmt)); +} + +/* Parse an Objective-C throw statement. + + objc-throw-stmt: + @throw assignment-expression [opt] ; + + Returns a constructed '@throw' statement. */ + +static tree +cp_parser_objc_throw_statement (cp_parser *parser) { + tree expr = NULL_TREE; + + cp_parser_require_keyword (parser, RID_AT_THROW, "`@throw'"); + + if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + expr = cp_parser_assignment_expression (parser, false); + + cp_parser_consume_semicolon_at_end_of_statement (parser); + + return objc_build_throw_stmt (expr); +} + +/* Parse an Objective-C statement. */ + +static tree +cp_parser_objc_statement (cp_parser * parser) { + /* Try to figure out what kind of declaration is present. */ + cp_token *kwd = cp_lexer_peek_token (parser->lexer); + + switch (kwd->keyword) + { + case RID_AT_TRY: + return cp_parser_objc_try_catch_finally_statement (parser); + case RID_AT_SYNCHRONIZED: + return cp_parser_objc_synchronized_statement (parser); + case RID_AT_THROW: + return cp_parser_objc_throw_statement (parser); + default: + error ("misplaced `@%D' Objective-C++ construct", kwd->value); + cp_parser_skip_to_end_of_block_or_statement (parser); + } + + return error_mark_node; +} /* The parser. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9006ab910f5..f5e3f8a7a32 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -34,7 +34,9 @@ Boston, MA 02111-1307, USA. */ #include "tree.h" #include "pointer-set.h" #include "flags.h" +#include "c-common.h" #include "cp-tree.h" +#include "cp-objcp-common.h" #include "tree-inline.h" #include "decl.h" #include "output.h" @@ -4024,7 +4026,24 @@ template_args_equal (tree ot, tree nt) /* For member templates */ return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt); else if (TYPE_P (nt)) - return TYPE_P (ot) && same_type_p (ot, nt); + { + int c1, c2; + + if (!TYPE_P (ot)) + return 0; + + /* We must handle ObjC types specially because they may differ + only in protocol qualifications (e.g., 'NSObject *' vs. + 'NSObject *') that must be taken into account here. + See also cp/typeck.c:build_c_cast(), where a similar problem + arises. We must call objc_comptypes() twice, since its + comparisons are _not_ symmetric. */ + if ((c1 = objc_comptypes (ot, nt, 0)) >= 0 + && (c2 = objc_comptypes (nt, ot, 0)) >= 0) + return (c1 && c2); + + return same_type_p (ot, nt); + } else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot)) return 0; else @@ -8880,6 +8899,14 @@ tsubst_copy_and_build (tree t, return t; default: + /* Handle Objective-C++ constructs, if appropriate. */ + { + tree subst + = objcp_tsubst_copy_and_build (t, args, complain, + in_decl, /*function_p=*/false); + if (subst) + return subst; + } return tsubst_copy (t, args, complain, in_decl); } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 25286852e65..6955291d536 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -401,7 +401,7 @@ anon_aggr_type_p (tree node) /* Finish a scope. */ -static tree +tree do_poplevel (tree stmt_list) { tree block = NULL; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9f0776a0df4..114275cd419 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */ #include "insn-config.h" #include "integrate.h" #include "tree-inline.h" +#include "debug.h" #include "target.h" static tree bot_manip (tree *, int *, void *); @@ -111,6 +112,7 @@ lvalue_p_1 (tree ref, case STRING_CST: return clk_ordinary; + case CONST_DECL: case VAR_DECL: if (TREE_READONLY (ref) && ! TREE_STATIC (ref) && DECL_LANG_SPECIFIC (ref) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bd73969058e..319e8ad6e35 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -514,10 +514,12 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, class1 = TREE_TYPE (t1); class2 = TREE_TYPE (t2); - if (DERIVED_FROM_P (class1, class2)) + if (DERIVED_FROM_P (class1, class2) || + (c_dialect_objc () && objc_comptypes (class1, class2, 0) == 1)) t2 = (build_pointer_type (cp_build_qualified_type (class1, TYPE_QUALS (class2)))); - else if (DERIVED_FROM_P (class2, class1)) + else if (DERIVED_FROM_P (class2, class1) || + (c_dialect_objc () && objc_comptypes (class2, class1, 0) == 1)) t1 = (build_pointer_type (cp_build_qualified_type (class2, TYPE_QUALS (class1)))); else @@ -1849,6 +1851,10 @@ finish_class_member_access_expr (tree object, tree name) if (object == error_mark_node || name == error_mark_node) return error_mark_node; + /* If OBJECT is an ObjC class instance, we must obey ObjC access rules. */ + if (!objc_is_public (object, name)) + return error_mark_node; + object_type = TREE_TYPE (object); if (processing_template_decl) @@ -2395,6 +2401,10 @@ build_function_call (tree function, tree params) int is_method; tree original = function; + /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF + expressions, like those used for ObjC messenger dispatches. */ + function = objc_rewrite_function_call (function, params); + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context. */ if (TREE_CODE (function) == NOP_EXPR @@ -5441,6 +5451,14 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (newrhs == error_mark_node) return error_mark_node; + if (c_dialect_objc () && flag_objc_gc) + { + result = objc_generate_write_barrier (lhs, modifycode, newrhs); + + if (result) + return result; + } + result = build2 (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR, lhstype, lhs, newrhs);