diff options
Diffstat (limited to 'contrib/gcc/c-parser.c')
-rw-r--r-- | contrib/gcc/c-parser.c | 1864 |
1 files changed, 1714 insertions, 150 deletions
diff --git a/contrib/gcc/c-parser.c b/contrib/gcc/c-parser.c index a8c8a1e..a86c80c 100644 --- a/contrib/gcc/c-parser.c +++ b/contrib/gcc/c-parser.c @@ -78,6 +78,17 @@ static int objc_need_raw_identifier = 0; objc_need_raw_identifier = VAL; \ } while (0) +/* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 d) */ +/* For checking property attribute keywords */ +static int objc_property_attr_context; +/* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 d) */ +/* APPLE LOCAL radar 3803157 - objc attribute (in 4.2 e) */ +static tree objc_method_attributes; +/* APPLE LOCAL begin C* language (in 4.2 f) */ +/* For checking for 'foreach' context. */ +static int objc_foreach_context; +/* APPLE LOCAL end C* language (in 4.2 f) */ + /* The reserved keyword table. */ struct resword { @@ -179,6 +190,14 @@ static const struct resword reswords[] = { "end", RID_AT_END, D_OBJC }, { "implementation", RID_AT_IMPLEMENTATION, D_OBJC }, { "interface", RID_AT_INTERFACE, D_OBJC }, + /* APPLE LOCAL begin C* language (in 4.2 j) */ + { "optional", RID_AT_OPTIONAL, D_OBJC }, + { "required", RID_AT_REQUIRED, D_OBJC }, + /* APPLE LOCAL end C* language (in 4.2 j) */ + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 k) */ + { "property", RID_AT_PROPERTY, D_OBJC }, + /* APPLE LOCAL radar 4564694 */ + { "package", RID_AT_PACKAGE, D_OBJC }, { "private", RID_AT_PRIVATE, D_OBJC }, { "protected", RID_AT_PROTECTED, D_OBJC }, { "protocol", RID_AT_PROTOCOL, D_OBJC }, @@ -197,6 +216,14 @@ static const struct resword reswords[] = { "inout", RID_INOUT, D_OBJC }, { "oneway", RID_ONEWAY, D_OBJC }, { "out", RID_OUT, D_OBJC }, + /* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 l) */ + /* These are recognized inside a property attribute list */ + { "readonly", RID_READONLY, D_OBJC }, + { "getter", RID_GETTER, D_OBJC }, + { "setter", RID_SETTER, D_OBJC }, + /* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 l) */ + /* APPLE LOCAL radar 4947014 - objc atomic property */ + { "nonatomic", RID_NONATOMIC, D_OBJC }, }; #define N_reswords (sizeof reswords / sizeof (struct resword)) @@ -325,11 +352,13 @@ typedef struct c_parser GTY(()) static GTY (()) c_parser *the_parser; +/* APPLE LOCAL C* language (in 4.2 ae) */ +static c_token * c_parser_peek_2nd_token (c_parser *); /* Read in and lex a single token, storing it in *TOKEN. */ static void -c_lex_one_token (c_token *token) +c_lex_one_token (c_token *token, c_parser *parser) { timevar_push (TV_LEX); @@ -363,6 +392,27 @@ c_lex_one_token (c_token *token) token->keyword = rid_code; break; } + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + else if (objc_foreach_context && rid_code == RID_IN) + { + /* This is dangerous, we assume we don't need 3 input tokens look ahead. */ + c_token *tk = c_parser_peek_2nd_token (parser); + if (tk->type == CPP_NAME + || tk->type == CPP_OPEN_PAREN + || tk->type == CPP_MULT + || tk->type == CPP_PLUS + || tk->type == CPP_PLUS_PLUS + || tk->type == CPP_MINUS + || tk->type == CPP_MINUS_MINUS + /* APPLE LOCAL radar 4529200 (in 4.2 af) */ + || tk->type == CPP_OPEN_SQUARE) + { + token->type = CPP_KEYWORD; + token->keyword = rid_code; + break; + } + } + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ } else { @@ -433,8 +483,11 @@ c_parser_peek_token (c_parser *parser) { if (parser->tokens_avail == 0) { - c_lex_one_token (&parser->tokens[0]); + /* APPLE LOCAL begin switch these two */ parser->tokens_avail = 1; + /* APPLE LOCAL C* language (in 4.2 ae) */ + c_lex_one_token (&parser->tokens[0], parser); + /* APPLE LOCAL end switch these two */ } return &parser->tokens[0]; } @@ -609,7 +662,13 @@ static inline bool c_parser_next_token_starts_declspecs (c_parser *parser) { c_token *token = c_parser_peek_token (parser); - return c_token_starts_declspecs (token); + /* APPLE LOCAL begin radar 5277239 */ + /* Yes, we can have CLASS.method to mean property-style dot-syntax + notation to call a class method (equiv to [CLASS meth]). */ + return c_token_starts_declspecs (token) + && (token->id_kind != C_ID_CLASSNAME + || c_parser_peek_2nd_token (parser)->type != CPP_DOT); + /* APPLE LOCAL end radar 5277239 */ } /* Return a pointer to the next-but-one token from PARSER, reading it @@ -623,8 +682,11 @@ c_parser_peek_2nd_token (c_parser *parser) gcc_assert (parser->tokens_avail == 1); gcc_assert (parser->tokens[0].type != CPP_EOF); gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL); - c_lex_one_token (&parser->tokens[1]); + /* APPLE LOCAL begin switch these two */ parser->tokens_avail = 2; + /* APPLE LOCAL C* language (in 4.2 ae) */ + c_lex_one_token (&parser->tokens[1], parser); + /* APPLE LOCAL end switch these two */ return &parser->tokens[1]; } @@ -965,6 +1027,10 @@ typedef enum c_dtr_syn { C_DTR_NORMAL, /* An abstract declarator (maybe empty). */ C_DTR_ABSTRACT, + /* APPLE LOCAL begin blocks 6339747 */ + /* A block declarator (maybe empty). */ + C_DTR_BLOCK, + /* APPLE LOCAL end blocks 6339747 */ /* A parameter declarator: may be either, but after a type name does not redeclare a typedef name as an identifier if it can alternatively be interpreted as a typedef name; see DR#009, @@ -980,7 +1046,8 @@ typedef enum c_dtr_syn { static void c_parser_external_declaration (c_parser *); static void c_parser_asm_definition (c_parser *); -static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool); +/* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ +static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, bool, tree*); static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, bool); static struct c_typespec c_parser_enum_specifier (c_parser *); @@ -1015,6 +1082,9 @@ static void c_parser_while_statement (c_parser *); static void c_parser_do_statement (c_parser *); static void c_parser_for_statement (c_parser *); static tree c_parser_asm_statement (c_parser *); +/* APPLE LOCAL begin radar 5732232 - blocks (C++ ca) */ +static tree c_parser_block_literal_expr (c_parser *); +/* APPLE LOCAL end radar 5732232 - blocks (C++ ca) */ static tree c_parser_asm_operands (c_parser *, bool); static tree c_parser_asm_clobbers (c_parser *); static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *); @@ -1043,14 +1113,19 @@ static bool c_parser_pragma (c_parser *, enum pragma_context); /* These Objective-C parser functions are only ever called when compiling Objective-C. */ -static void c_parser_objc_class_definition (c_parser *); +/* APPLE LOCAL radar 4548636 - class attributes. */ +static void c_parser_objc_class_definition (c_parser *, tree); static void c_parser_objc_class_instance_variables (c_parser *); static void c_parser_objc_class_declaration (c_parser *); static void c_parser_objc_alias_declaration (c_parser *); -static void c_parser_objc_protocol_definition (c_parser *); +/* APPLE LOCAL radar 4947311 - protocol attributes */ +static void c_parser_objc_protocol_definition (c_parser *, tree); static enum tree_code c_parser_objc_method_type (c_parser *); static void c_parser_objc_method_definition (c_parser *); -static void c_parser_objc_methodprotolist (c_parser *); +/* APPLE LOCAL C* property (Radar 4436866) (in 4.2 b) */ +static void c_parser_objc_interfacedecllist (c_parser *); +/* APPLE LOCAL C* property (Radar 4436866) (in 4.2 x) */ +static void c_parser_objc_property_declaration (c_parser *); static void c_parser_objc_methodproto (c_parser *); static tree c_parser_objc_method_decl (c_parser *); static tree c_parser_objc_type_name (c_parser *); @@ -1144,7 +1219,8 @@ c_parser_external_declaration (c_parser *parser) case RID_AT_INTERFACE: case RID_AT_IMPLEMENTATION: gcc_assert (c_dialect_objc ()); - c_parser_objc_class_definition (parser); + /* APPLE LOCAL radar 4548636 - class attributes. */ + c_parser_objc_class_definition (parser, NULL_TREE); break; case RID_AT_CLASS: gcc_assert (c_dialect_objc ()); @@ -1156,8 +1232,15 @@ c_parser_external_declaration (c_parser *parser) break; case RID_AT_PROTOCOL: gcc_assert (c_dialect_objc ()); - c_parser_objc_protocol_definition (parser); + /* APPLE LOCAL begin radar 4947311 - protocol attributes */ + c_parser_objc_protocol_definition (parser, NULL_TREE); + break; + /* APPLE LOCAL end radar 4947311 - protocol attributes */ + /* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 x) */ + case RID_AT_PROPERTY: + c_parser_objc_property_declaration (parser); break; + /* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 x) */ case RID_AT_END: gcc_assert (c_dialect_objc ()); c_parser_consume_token (parser); @@ -1189,7 +1272,8 @@ c_parser_external_declaration (c_parser *parser) /* A declaration or a function definition. We can only tell which after parsing the declaration specifiers, if any, and the first declarator. */ - c_parser_declaration_or_fndef (parser, true, true, false, true); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, false, true, NULL); break; } } @@ -1254,7 +1338,8 @@ c_parser_external_declaration (c_parser *parser) static void c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, - bool nested, bool start_attr_ok) + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + bool nested, bool start_attr_ok, tree *foreach_elem) { struct c_declspecs *specs; tree prefix_attrs; @@ -1287,6 +1372,29 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, c_parser_consume_token (parser); return; } + /* APPLE LOCAL begin radar 4548636 - class attributes. */ + else if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE) + || c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION)) + { + gcc_assert (c_dialect_objc ()); + if (!specs->declspecs_seen_p || specs->attrs == NULL_TREE + || specs->type_seen_p || specs->non_sc_seen_p) + c_parser_error (parser, "no type or storage class may be specified here"); + c_parser_objc_class_definition (parser, specs->attrs); + return; + } + /* APPLE LOCAL end radar 4548636 - class attributes. */ + /* APPLE LOCAL begin radar 4947311 - protocol attributes */ + else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL)) + { + gcc_assert (c_dialect_objc ()); + if (!specs->declspecs_seen_p || specs->attrs == NULL_TREE + || specs->type_seen_p || specs->non_sc_seen_p) + c_parser_error (parser, "no type or storage class may be specified here"); + c_parser_objc_protocol_definition (parser, specs->attrs); + return; + } + /* APPLE LOCAL end radar 4947311 - protocol attributes */ pending_xref_error (); prefix_attrs = specs->attrs; all_prefix_attrs = prefix_attrs; @@ -1311,6 +1419,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, || c_parser_next_token_is (parser, CPP_COMMA) || c_parser_next_token_is (parser, CPP_SEMICOLON) || c_parser_next_token_is_keyword (parser, RID_ASM) + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + || c_parser_next_token_is_keyword (parser, RID_IN) || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) { tree asm_name = NULL_TREE; @@ -1327,6 +1437,18 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, asm_name = c_parser_simple_asm_expr (parser); if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) postfix_attrs = c_parser_attributes (parser); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + if (c_parser_next_token_is_keyword (parser, RID_IN)) + { + gcc_assert (foreach_elem); + *foreach_elem = start_decl (declarator, specs, true, + chainon (postfix_attrs, all_prefix_attrs)); + if (!*foreach_elem) + *foreach_elem = error_mark_node; + start_init (*foreach_elem, asm_name, global_bindings_p ()); + return; + } + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ if (c_parser_next_token_is (parser, CPP_EQ)) { tree d; @@ -1387,8 +1509,17 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, /* Function definition (nested or otherwise). */ if (nested) { - if (pedantic) + /* APPLE LOCAL begin radar 5985368 */ + if (declarator->declarator && declarator->declarator->kind == cdk_block_pointer) + error ("bad definition of a block"); + else if (pedantic) + /* APPLE LOCAL end radar 5985368 */ pedwarn ("ISO C forbids nested functions"); + /* APPLE LOCAL begin nested functions 4258406 4357979 (in 4.2 m) */ + else if (flag_nested_functions == 0) + error ("nested functions are disabled, use -fnested-functions to re-enable"); + /* APPLE LOCAL end nested functions 4258406 4357979 (in 4.2 m) */ + push_function_context (); } if (!start_function (specs, declarator, all_prefix_attrs)) @@ -1416,7 +1547,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, function definitions either. */ while (c_parser_next_token_is_not (parser, CPP_EOF) && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) - c_parser_declaration_or_fndef (parser, false, false, true, false); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, false, false, true, false, NULL); DECL_SOURCE_LOCATION (current_function_decl) = c_parser_peek_token (parser)->location; store_parm_decls (); @@ -1438,6 +1570,23 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool empty_ok, } } +static tree +finish_parse_foreach_header (c_parser *parser, tree foreach_elem_selector) +{ + tree res; + int save_flag_isoc99 = flag_isoc99; + gcc_assert (foreach_elem_selector); + /* Consume 'in' keyword */ + c_parser_consume_token (parser); + res = build_tree_list (foreach_elem_selector, c_parser_initializer (parser).value); + finish_init (); + flag_isoc99 = 1; + check_for_loop_decls (); + flag_isoc99 = save_flag_isoc99; + return res; +} +/* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ + /* Parse an asm-definition (asm() outside a function body). This is a GNU extension. @@ -2251,6 +2400,18 @@ c_parser_typeof_specifier (c_parser *parser) parameter-list ; parameter-forward-declarations parameter-list ; + APPLE LOCAL begin blocks 6339747 + block-declarator: + pointer + pointer[opt] direct-block-declarator + + direct-block-declarator: + ( attributes[opt] block-declarator ) + direct-block-declarator[opt] array-declarator + direct-block-declarator[opt] + ( parameter-type-list[opt] ) [opt] + APPLE LOCAL end blocks 6339747 + The uses of attributes shown above are GNU extensions. Some forms of array declarator are not included in C99 in the @@ -2277,6 +2438,20 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, else return make_pointer_declarator (quals_attrs, inner); } + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cc) */ + else if (flag_blocks && c_parser_next_token_is (parser, CPP_XOR)) { + struct c_declspecs *quals_attrs = build_null_declspecs (); + struct c_declarator *inner; + c_parser_consume_token (parser); + c_parser_declspecs (parser, quals_attrs, false, false, true); + inner = c_parser_declarator (parser, type_seen_p, kind, seen_id); + if (inner == NULL) + return NULL; + else + /* APPLE LOCAL radar 5814025 (C++ cc) */ + return make_block_pointer_declarator (quals_attrs, inner); + } + /* APPLE LOCAL end radar 5732232 - blocks (C++ cc) */ /* Now we have a direct declarator, direct abstract declarator or nothing (which counts as a direct abstract declarator here). */ return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id); @@ -2323,10 +2498,14 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, ??? Also following the old parser, typedef names may be redeclared in declarators, but not Objective-C class names. */ - if (kind != C_DTR_ABSTRACT + /* APPLE LOCAL blocks 6339747 */ + if ((kind != C_DTR_ABSTRACT && kind != C_DTR_BLOCK) && c_parser_next_token_is (parser, CPP_NAME) && ((type_seen_p - && c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME) + /* APPLE LOCAL begin radar 4281748 */ + && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME + || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)) + /* APPLE LOCAL end radar 4281748 */ || c_parser_peek_token (parser)->id_kind == C_ID_ID)) { struct c_declarator *inner @@ -3379,6 +3558,8 @@ c_parser_compound_statement_nostart (c_parser *parser) { bool last_stmt = false; bool last_label = false; + /* APPLE LOCAL radar 5732232 - blocks (not in C++) */ + bool first_stmt = true; if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) { c_parser_consume_token (parser); @@ -3389,30 +3570,30 @@ c_parser_compound_statement_nostart (c_parser *parser) /* Read zero or more forward-declarations for labels that nested functions can jump to. */ while (c_parser_next_token_is_keyword (parser, RID_LABEL)) + { + c_parser_consume_token (parser); + /* Any identifiers, including those declared as type names, + are OK here. */ + while (true) { - c_parser_consume_token (parser); - /* Any identifiers, including those declared as type names, - are OK here. */ - while (true) - { - tree label; - if (c_parser_next_token_is_not (parser, CPP_NAME)) + tree label; + if (c_parser_next_token_is_not (parser, CPP_NAME)) { - c_parser_error (parser, "expected identifier"); - break; + c_parser_error (parser, "expected identifier"); + break; } - label + label = declare_label (c_parser_peek_token (parser)->value); - C_DECLARED_LABEL_FLAG (label) = 1; - add_stmt (build_stmt (DECL_EXPR, label)); - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_COMMA)) + C_DECLARED_LABEL_FLAG (label) = 1; + add_stmt (build_stmt (DECL_EXPR, label)); c_parser_consume_token (parser); - else - break; - } - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + if (c_parser_next_token_is (parser, CPP_COMMA)) + c_parser_consume_token (parser); + else + break; } + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } /* ??? Locating this diagnostic on the token after the declarations end follows the old parser, but it might be better to locate it where the declarations start instead. */ @@ -3430,81 +3611,85 @@ c_parser_compound_statement_nostart (c_parser *parser) { location_t loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is_keyword (parser, RID_CASE) - || c_parser_next_token_is_keyword (parser, RID_DEFAULT) - || (c_parser_next_token_is (parser, CPP_NAME) - && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) - { - last_label = true; - last_stmt = false; - c_parser_label (parser); - } + || c_parser_next_token_is_keyword (parser, RID_DEFAULT) + || (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + { + last_label = true; + last_stmt = false; + c_parser_label (parser); + } else if (!last_label - && c_parser_next_token_starts_declspecs (parser)) - { - last_label = false; - c_parser_declaration_or_fndef (parser, true, true, true, true); - if (last_stmt - && ((pedantic && !flag_isoc99) - || warn_declaration_after_statement)) - pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", - &loc); - last_stmt = false; - } + && c_parser_next_token_starts_declspecs (parser)) + { + last_label = false; + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, true, true, NULL); + if (last_stmt + && ((pedantic && !flag_isoc99) + || warn_declaration_after_statement)) + pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", + &loc); + last_stmt = false; + } else if (!last_label - && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) + && c_parser_next_token_is_keyword (parser, RID_EXTENSION)) + { + /* __extension__ can start a declaration, but is also an + unary operator that can start an expression. Consume all + but the last of a possible series of __extension__ to + determine which. */ + while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD + && (c_parser_peek_2nd_token (parser)->keyword + == RID_EXTENSION)) + c_parser_consume_token (parser); + if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) { - /* __extension__ can start a declaration, but is also an - unary operator that can start an expression. Consume all - but the last of a possible series of __extension__ to - determine which. */ - while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD - && (c_parser_peek_2nd_token (parser)->keyword - == RID_EXTENSION)) - c_parser_consume_token (parser); - if (c_token_starts_declspecs (c_parser_peek_2nd_token (parser))) - { - int ext; - ext = disable_extension_diagnostics (); - c_parser_consume_token (parser); - last_label = false; - c_parser_declaration_or_fndef (parser, true, true, true, true); - /* Following the old parser, __extension__ does not + int ext; + ext = disable_extension_diagnostics (); + c_parser_consume_token (parser); + last_label = false; + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, true, true, NULL); + /* Following the old parser, __extension__ does not disable this diagnostic. */ - restore_extension_diagnostics (ext); - if (last_stmt - && ((pedantic && !flag_isoc99) - || warn_declaration_after_statement)) - pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", - &loc); - last_stmt = false; - } - else - goto statement; - } + restore_extension_diagnostics (ext); + if (last_stmt + && ((pedantic && !flag_isoc99) + || warn_declaration_after_statement)) + pedwarn_c90 ("%HISO C90 forbids mixed declarations and code", + &loc); + last_stmt = false; + } + else + goto statement; + } else if (c_parser_next_token_is (parser, CPP_PRAGMA)) - { - /* External pragmas, and some omp pragmas, are not associated - with regular c code, and so are not to be considered statements - syntactically. This ensures that the user doesn't put them - places that would turn into syntax errors if the directive - were ignored. */ - if (c_parser_pragma (parser, pragma_compound)) - last_label = false, last_stmt = true; - } + { + /* External pragmas, and some omp pragmas, are not associated + with regular c code, and so are not to be considered statements + syntactically. This ensures that the user doesn't put them + places that would turn into syntax errors if the directive + were ignored. */ + if (c_parser_pragma (parser, pragma_compound)) + last_label = false, last_stmt = true; + } else if (c_parser_next_token_is (parser, CPP_EOF)) - { - c_parser_error (parser, "expected declaration or statement"); - return; - } + { + c_parser_error (parser, "expected declaration or statement"); + return; + } else - { - statement: - last_label = false; - last_stmt = true; - c_parser_statement_after_labels (parser); - } - + { + statement: + last_label = false; + last_stmt = true; + c_parser_statement_after_labels (parser); + } + parser->error = false; + /* APPLE LOCAL radar 5732232 - blocks (not in C++) */ + first_stmt = false; } if (last_label) error ("label at end of compound statement"); @@ -3720,6 +3905,10 @@ c_parser_statement_after_labels (c_parser *parser) c_parser_for_statement (parser); break; case RID_GOTO: + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cb) */ + if (cur_block) + error ("goto not allowed in block literal"); + /* APPLE LOCAL end radar 5732232 - blocks (C++ cb) */ c_parser_consume_token (parser); if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -3817,8 +4006,20 @@ c_parser_statement_after_labels (c_parser *parser) (recursively) all of the component statements should already have line numbers assigned. ??? Can we discard no-op statements earlier? */ + /* APPLE LOCAL begin Radar 6144634 */ + /* Normal expr stmts, including modify exprs, get the location where + the statement began, i.e. 'loc'. Assignments of Blocks to Block + pointer variables get the location of the end of the Block definition, + i.e. 'input_location', which should already be set by this point. */ if (stmt && EXPR_P (stmt)) - SET_EXPR_LOCATION (stmt, loc); + { + if (TREE_CODE (stmt) == MODIFY_EXPR + && TREE_CODE (TREE_TYPE (TREE_OPERAND (stmt, 0))) == BLOCK_POINTER_TYPE) + SET_EXPR_LOCATION (stmt, input_location); + else + SET_EXPR_LOCATION (stmt, loc); + } + /* APPLE LOCAL end Radar 6144634 */ } /* Parse a parenthesized condition from an if, do or while statement. @@ -4048,6 +4249,8 @@ c_parser_for_statement (c_parser *parser) tree block, cond, incr, save_break, save_cont, body, attrs; /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ location_t loc; + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + bool foreach_p = false; gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR)); loc = c_parser_peek_token (parser)->location; c_parser_consume_token (parser); @@ -4065,8 +4268,18 @@ c_parser_for_statement (c_parser *parser) } else if (c_parser_next_token_starts_declspecs (parser)) { - c_parser_declaration_or_fndef (parser, true, true, true, true); - check_for_loop_decls (); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + cond = NULL_TREE; + c_parser_declaration_or_fndef (parser, true, true, true, true, &cond); + /* APPLE LOCAL radar 5925639 */ + if (c_parser_next_token_is_keyword (parser, RID_IN) && cond) + { + cond = finish_parse_foreach_header (parser, cond); + foreach_p = true; + } + else + check_for_loop_decls (); + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ } else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) { @@ -4083,9 +4296,19 @@ c_parser_for_statement (c_parser *parser) int ext; ext = disable_extension_diagnostics (); c_parser_consume_token (parser); - c_parser_declaration_or_fndef (parser, true, true, true, true); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + cond = NULL_TREE; + c_parser_declaration_or_fndef (parser, true, true, true, true, &cond); restore_extension_diagnostics (ext); - check_for_loop_decls (); + /* APPLE LOCAL radar 5925639 */ + if (c_parser_next_token_is_keyword (parser, RID_IN) && cond) + { + cond = finish_parse_foreach_header (parser, cond); + foreach_p = true; + } + else + check_for_loop_decls (); + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ } else goto init_expr; @@ -4093,9 +4316,22 @@ c_parser_for_statement (c_parser *parser) else { init_expr: - c_finish_expr_stmt (c_parser_expression (parser).value); - c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + cond = c_parser_expression (parser).value; + if (c_parser_next_token_is_keyword (parser, RID_IN)) + { + c_parser_consume_token (parser); /* IN */ + cond = build_tree_list (cond, c_parser_initializer (parser).value); + foreach_p = true; + } + else + { + c_finish_expr_stmt (cond); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + } } + objc_foreach_context = 0; + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ /* Parse the loop condition. */ loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_SEMICOLON)) @@ -4103,6 +4339,10 @@ c_parser_for_statement (c_parser *parser) c_parser_consume_token (parser); cond = NULL_TREE; } + /* APPLE LOCAL begin radar 4708210 (for_objc_collection in 4.2) */ + else if (foreach_p) + ; + /* APPLE LOCAL end radar 4708210 (for_objc_collection in 4.2) */ else { tree ocond = c_parser_expression_conv (parser).value; @@ -4607,6 +4847,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) } while (0) gcc_assert (!after || c_dialect_objc ()); stack[0].expr = c_parser_cast_expression (parser, after); + /* APPLE LOCAL begin radar 4426814 */ + if (c_dialect_objc() && flag_objc_gc) + /* APPLE LOCAL radar 5276085 */ + stack[0].expr.value = objc_build_weak_reference_tree (stack[0].expr.value); + /* APPLE LOCAL end radar 4426814 */ stack[0].prec = PREC_NONE; sp = 0; while (true) @@ -4718,6 +4963,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after) } sp++; stack[sp].expr = c_parser_cast_expression (parser, NULL); + /* APPLE LOCAL begin radar 4426814 */ + if (c_dialect_objc() && flag_objc_gc) + /* APPLE LOCAL radar 5276085 */ + stack[sp].expr.value = objc_build_weak_reference_tree (stack[sp].expr.value); + /* APPLE LOCAL end radar 4426814 */ stack[sp].prec = oprec; stack[sp].op = ocode; } @@ -5054,6 +5304,8 @@ c_parser_alignof_expression (c_parser *parser) assignment-expression , assignment-expression ) __builtin_types_compatible_p ( type-name , type-name ) + APPLE LOCAL blocks (C++ cf) + block-literal-expr offsetof-member-designator: identifier @@ -5098,6 +5350,21 @@ c_parser_postfix_expression (c_parser *parser) c_parser_consume_token (parser); break; case CPP_NAME: + /* APPLE LOCAL begin radar 5277239 */ + if (c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME + && c_parser_peek_2nd_token (parser)->type == CPP_DOT) + { + /* CLASS.class_method expression. */ + tree receiver, component; + receiver = c_parser_objc_receiver (parser); + /* consume '.' operator */ + c_parser_consume_token (parser); + component = c_parser_objc_message_args (parser); + expr.value = objc_build_property_reference_expr (receiver, component); + expr.original_code = ERROR_MARK; + break; + } + /* APPLE LOCAL end radar 5277239 */ if (c_parser_peek_token (parser)->id_kind != C_ID_ID) { c_parser_error (parser, "expected expression"); @@ -5112,6 +5379,34 @@ c_parser_postfix_expression (c_parser *parser) expr.value = build_external_ref (id, (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN), loc); + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cd) */ + /* If a variabled declared as referenced variable, using |...| syntax, + is used in the block, it has to be derefrenced because this + variable holds address of the outside variable referenced in. */ + + /* APPLE LOCAL begin radar 5932809 - copyable byref blocks (C++ cd) */ + if (TREE_CODE (expr.value) == VAR_DECL) + { + if (BLOCK_DECL_BYREF (expr.value)) + { + tree orig_decl = expr.value; + expr.value = build_indirect_ref (expr.value, "unary *"); + if (COPYABLE_BYREF_LOCAL_VAR (orig_decl)) { + /* What we have is an expression which is of type + struct __Block_byref_X. Must get to the value of the variable + embedded in this structure. It is at: + __Block_byref_X.__forwarding->x */ + expr.value = build_byref_local_var_access (expr.value, + DECL_NAME (orig_decl)); + } + } + else if (COPYABLE_BYREF_LOCAL_VAR (expr.value)) + expr.value = build_byref_local_var_access (expr.value, + DECL_NAME (expr.value)); + } + /* APPLE LOCAL end radar 5932809 - copyable byref blocks */ + + /* APPLE LOCAL end radar 5732232 - blocks (C++ cd) */ expr.original_code = ERROR_MARK; } break; @@ -5447,6 +5742,18 @@ c_parser_postfix_expression (c_parser *parser) break; } break; + /* APPLE LOCAL begin radar 5732232 - blocks (C++ cf) */ + case CPP_XOR: + if (flag_blocks) { + expr.value = c_parser_block_literal_expr (parser); + expr.original_code = ERROR_MARK; + break; + } + c_parser_error (parser, "expected expression"); + expr.value = error_mark_node; + expr.original_code = ERROR_MARK; + break; + /* APPLE LOCAL end radar 5732232 - blocks (C++ cf) */ case CPP_OPEN_SQUARE: if (c_dialect_objc ()) { @@ -5680,7 +5987,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p) objc-protocol-refs and objc-class-instance-variables are omitted. */ static void -c_parser_objc_class_definition (c_parser *parser) +/* APPLE LOCAL radar 4548636 - class attributes. */ +c_parser_objc_class_definition (c_parser *parser, tree prefix_attrs) { bool iface_p; tree id1; @@ -5688,40 +5996,60 @@ c_parser_objc_class_definition (c_parser *parser) if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE)) iface_p = true; else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION)) - iface_p = false; + /* APPLE LOCAL begin radar 4548636 - class attributes. */ + { + if (prefix_attrs) + { + error ("attributes may not be specified on an implementation"); + prefix_attrs = NULL_TREE; + } + iface_p = false; + } + /* APPLE LOCAL end radar 4548636 - class attributes. */ else gcc_unreachable (); c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_NAME)) { - c_parser_error (parser, "expected identifier"); - return; - } - id1 = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) - { - tree id2; + /* APPLE LOCAL radar 4965989 */ + tree id2 = NULL_TREE; tree proto = NULL_TREE; c_parser_consume_token (parser); - if (c_parser_next_token_is_not (parser, CPP_NAME)) + /* APPLE LOCAL begin radar 4965989 */ + if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN)) { - c_parser_error (parser, "expected identifier"); - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - return; + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return; + } + id2 = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); } - id2 = c_parser_peek_token (parser)->value; - c_parser_consume_token (parser); + /* APPLE LOCAL end radar 4965989 */ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); if (!iface_p) { + /* APPLE LOCAL begin radar 4965989 */ + if (id2 == NULL_TREE) + { + error ("cannot implement anonymous category"); + return; + } + /* APPLE LOCAL end radar 4965989 */ objc_start_category_implementation (id1, id2); return; } if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); + /* APPLE LOCAL begin radar 4548636 - class attributes. */ + if (prefix_attrs) + error ("attributes may not be specified on a category"); + /* APPLE LOCAL end radar 4548636 - class attributes. */ objc_start_category_interface (id1, id2, proto); - c_parser_objc_methodprotolist (parser); + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 q) */ + c_parser_objc_interfacedecllist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); objc_finish_interface (); return; @@ -5744,7 +6072,8 @@ c_parser_objc_class_definition (c_parser *parser) tree proto = NULL_TREE; if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); - objc_start_class_interface (id1, superclass, proto); + /* APPLE LOCAL radar 4548636 - class attributes. */ + objc_start_class_interface (id1, superclass, proto, prefix_attrs); } else objc_start_class_implementation (id1, superclass); @@ -5753,7 +6082,8 @@ c_parser_objc_class_definition (c_parser *parser) if (iface_p) { objc_continue_interface (); - c_parser_objc_methodprotolist (parser); + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 q) */ + c_parser_objc_interfacedecllist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); objc_finish_interface (); } @@ -5764,6 +6094,129 @@ c_parser_objc_class_definition (c_parser *parser) } } +/* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 s) */ +static tree +c_parser_objc_eq_identifier (c_parser *parser) +{ + tree id; + if (c_parser_next_token_is_not (parser, CPP_EQ)) + { + c_parser_error (parser, "expected %<=%>"); + return NULL_TREE; + } + /* Consume '=' */ + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_NAME)) + { + c_parser_error (parser, "expected identifier"); + return NULL_TREE; + } + id = c_parser_peek_token (parser)->value; + c_parser_consume_token (parser); + return id; +} + +/* Parse obj-property-attribute. +*/ +static void +c_parser_objc_property_attribute (c_parser *parser) +{ + tree id; + if (c_parser_peek_token (parser)->type != CPP_KEYWORD) + { + c_parser_error (parser, "expected a property attribute"); + c_parser_consume_token (parser); + return; + } + switch (c_parser_peek_token (parser)->keyword) + { + case RID_READONLY: + c_parser_consume_token (parser); + objc_set_property_attr (1, NULL_TREE); + break; + case RID_GETTER: + c_parser_consume_token (parser); + id = c_parser_objc_eq_identifier (parser); + if (id) + objc_set_property_attr (2, id); + break; + case RID_SETTER: + c_parser_consume_token (parser); + id = c_parser_objc_eq_identifier (parser); + if (id) + objc_set_property_attr (3, id); + /* Consume the ':' which must always follow the setter name. */ + if (c_parser_next_token_is (parser, CPP_COLON)) + c_parser_consume_token (parser); + break; + /* APPLE LOCAL begin radar 4947014 - objc atomic property */ + case RID_NONATOMIC: + c_parser_consume_token (parser); + objc_set_property_attr (13, NULL_TREE); + break; + /* APPLE LOCAL end radar 4947014 - objc atomic property */ + default: + c_parser_error (parser, "expected a property attribute"); + c_parser_consume_token (parser); + } +} + +static void +c_parser_objc_property_attrlist (c_parser *parser) +{ + while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN) + && c_parser_next_token_is_not (parser, CPP_EOF)) + { + c_parser_objc_property_attribute (parser); + /* APPLE LOCAL begin radar 6302949 */ + if (c_parser_next_token_is_not (parser, CPP_COMMA) + && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN) + && c_parser_next_token_is_not (parser, CPP_EOF)) + warning (0, "property attributes must be separated by a comma"); + /* APPLE LOCAL end radar 6302949 */ + if (c_parser_next_token_is (parser, CPP_COMMA) + || c_parser_next_token_is (parser, CPP_NAME) /* error */) + c_parser_consume_token (parser); + } +} + +static void +c_parser_objc_property_attr_decl (c_parser *parser) +{ + if (!c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + return; + c_parser_consume_token (parser); + c_parser_objc_property_attrlist (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); +} + +static tree +c_parser_component_decl (c_parser *parser) +{ + tree decl = c_parser_struct_declaration (parser); + return decl; +} + +static void +c_parser_objc_property_declaration (c_parser *parser) +{ + tree prop; + c_parser_require_keyword (parser, RID_AT_PROPERTY, "expected %<@property%>"); + objc_property_attr_context = 1; + objc_set_property_attr (0, NULL_TREE); + c_parser_objc_property_attr_decl (parser); + objc_property_attr_context = 0; + prop = c_parser_component_decl (parser); + /* Comma-separated properties are chained together in + reverse order; add them one by one. */ + prop = nreverse (prop); + + for (; prop; prop = TREE_CHAIN (prop)) + objc_add_property_variable (copy_node (prop)); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); +} +/* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 s) */ + /* Parse objc-class-instance-variables. objc-class-instance-variables: @@ -5827,6 +6280,14 @@ c_parser_objc_class_instance_variables (c_parser *parser) objc_set_visibility (1); continue; } + /* APPLE LOCAL begin radar 4564694 */ + else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE)) + { + c_parser_consume_token (parser); + objc_set_visibility (3); + continue; + } + /* APPLE LOCAL end radar 4564694 */ else if (c_parser_next_token_is (parser, CPP_PRAGMA)) { c_parser_pragma (parser, pragma_external); @@ -5924,7 +6385,8 @@ c_parser_objc_alias_declaration (c_parser *parser) omitted. */ static void -c_parser_objc_protocol_definition (c_parser *parser) +/* APPLE LOCAL radar 4947311 - protocol attributes */ +c_parser_objc_protocol_definition (c_parser *parser, tree attributes) { gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL)); c_parser_consume_token (parser); @@ -5956,7 +6418,8 @@ c_parser_objc_protocol_definition (c_parser *parser) break; } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); - objc_declare_protocols (list); + /* APPLE LOCAL radar 4947311 - protocol attributes */ + objc_declare_protocols (list, attributes); } else { @@ -5966,8 +6429,10 @@ c_parser_objc_protocol_definition (c_parser *parser) if (c_parser_next_token_is (parser, CPP_LESS)) proto = c_parser_objc_protocol_refs (parser); objc_pq_context = 1; - objc_start_protocol (id, proto); - c_parser_objc_methodprotolist (parser); + /* APPLE LOCAL radar 4947311 - protocol attributes */ + objc_start_protocol (id, proto, attributes); + /* APPLE LOCAL C* property (Radar 4436866) (in 4.2 r) */ + c_parser_objc_interfacedecllist (parser); c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>"); objc_pq_context = 0; objc_finish_interface (); @@ -6023,11 +6488,28 @@ c_parser_objc_method_definition (c_parser *parser) return; } objc_pq_context = 0; - objc_start_method_definition (decl); + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 a) */ + objc_start_method_definition (decl, objc_method_attributes); + objc_method_attributes = NULL_TREE; + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 a) */ add_stmt (c_parser_compound_statement (parser)); objc_finish_method_definition (current_function_decl); } +/* APPLE LOCAL begin C* language (in 4.2 w) */ +/* True iff the gioven TOKEN starts a methodproto. */ + +static bool +c_token_starts_methodproto (c_token *token) +{ + return token->type == CPP_PLUS + || token->type == CPP_MINUS + || (token->type == CPP_KEYWORD + && (token->keyword == RID_AT_REQUIRED + || token->keyword == RID_AT_OPTIONAL)); +} +/* APPLE LOCAL end C* language (in 4.2 w) */ + /* Parse an objc-methodprotolist. objc-methodprotolist: @@ -6043,10 +6525,29 @@ c_parser_objc_method_definition (c_parser *parser) function. */ static void -c_parser_objc_methodprotolist (c_parser *parser) +/* APPLE LOCAL C* property (Radar 4436866) (in 4.2 b) */ +c_parser_objc_interfacedecllist (c_parser *parser) { while (true) { + /* APPLE LOCAL begin C* property (Radar 4436866) (in 4.2 b) */ + c_token *token; + token = c_parser_peek_token (parser); + if (token->type == CPP_KEYWORD + && token->keyword == RID_AT_PROPERTY) + { + c_parser_objc_property_declaration (parser); + continue; + } + /* APPLE LOCAL end C* property (Radar 4436866) (in 4.2 b) */ + /* APPLE LOCAL begin C* language (in 4.2 w) */ + if (c_token_starts_methodproto (token)) + { + c_parser_objc_methodproto (parser); + continue; + } + /* APPLE LOCAL end C* language (in 4.2 w) */ + /* The list is terminated by @end. */ switch (c_parser_peek_token (parser)->type) { @@ -6055,10 +6556,9 @@ c_parser_objc_methodprotolist (c_parser *parser) pedwarn ("ISO C does not allow extra %<;%> outside of a function"); c_parser_consume_token (parser); break; - case CPP_PLUS: - case CPP_MINUS: - c_parser_objc_methodproto (parser); - break; + /* APPLE LOCAL begin C* language (in 4.2 w) */ + /* CPP_PLUS and CPP_MINUS deleted */ + /* APPLE LOCAL end C* language (in 4.2 w) */ case CPP_PRAGMA: c_parser_pragma (parser, pragma_external); break; @@ -6067,7 +6567,8 @@ c_parser_objc_methodprotolist (c_parser *parser) default: if (c_parser_next_token_is_keyword (parser, RID_AT_END)) return; - c_parser_declaration_or_fndef (parser, false, true, false, true); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, false, true, false, true, NULL); break; } } @@ -6082,15 +6583,35 @@ c_parser_objc_methodprotolist (c_parser *parser) static void c_parser_objc_methodproto (c_parser *parser) { - enum tree_code type = c_parser_objc_method_type (parser); + /* APPLE LOCAL C* language */ + enum tree_code type; tree decl; + /* APPLE LOCAL begin C* language */ + if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED)) + { + objc_set_method_opt (0); + c_parser_consume_token (parser); + return; + } + if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL)) + { + objc_set_method_opt (1); + c_parser_consume_token (parser); + return; + } + /* APPLE LOCAL begin C* language */ + /* APPLE LOCAL C* language */ + type = c_parser_objc_method_type (parser); objc_set_method_type (type); /* Remember protocol qualifiers in prototypes. */ objc_pq_context = 1; decl = c_parser_objc_method_decl (parser); /* Forget protocol qualifiers here. */ objc_pq_context = 0; - objc_add_method_declaration (decl); + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 c) */ + objc_add_method_declaration (decl, objc_method_attributes); + objc_method_attributes = NULL_TREE; + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 c) */ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } @@ -6148,6 +6669,8 @@ c_parser_objc_method_decl (c_parser *parser) tree list = NULL_TREE; while (true) { + /* APPLE LOCAL radar 4157812 */ + tree attr = NULL_TREE; tree atype = NULL_TREE, id, keyworddecl; if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")) break; @@ -6158,6 +6681,10 @@ c_parser_objc_method_decl (c_parser *parser) c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } + /* APPLE LOCAL begin radar 4157812 */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + attr = c_parser_attributes (parser); + /* APPLE LOCAL end radar 4157812 */ if (c_parser_next_token_is_not (parser, CPP_NAME)) { c_parser_error (parser, "expected identifier"); @@ -6165,12 +6692,17 @@ c_parser_objc_method_decl (c_parser *parser) } id = c_parser_peek_token (parser)->value; c_parser_consume_token (parser); - keyworddecl = objc_build_keyword_decl (tsel, atype, id); + /* APPLE LOCAL radar 4157812 */ + keyworddecl = objc_build_keyword_decl (tsel, atype, id, attr); list = chainon (list, keyworddecl); tsel = c_parser_objc_selector (parser); if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON)) break; } + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 y) */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + objc_method_attributes = c_parser_attributes (parser); + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ /* Parse the optional parameter list. Optional Objective-C method parameters follow the C syntax, and may include '...' to denote a variable number of arguments. */ @@ -6183,6 +6715,12 @@ c_parser_objc_method_decl (c_parser *parser) { ellipsis = true; c_parser_consume_token (parser); + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ + if (objc_method_attributes) + error ("method attributes must be specified at the end only"); + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + objc_method_attributes = c_parser_attributes (parser); + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ break; } parm = c_parser_parameter_declaration (parser, NULL_TREE); @@ -6193,6 +6731,21 @@ c_parser_objc_method_decl (c_parser *parser) } sel = list; } + /* APPLE LOCAL begin radar 3803157 - objc attribute (in 4.2 y) */ + else + { + gcc_assert (objc_method_attributes == NULL_TREE); + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + objc_method_attributes = c_parser_attributes (parser); + } + /* APPLE LOCAL end radar 3803157 - objc attribute (in 4.2 y) */ + /* APPLE LOCAL begin radar 4157812 */ + if (sel == NULL) + { + c_parser_error (parser, "objective-c method declaration is expected"); + return error_mark_node; + } + /* APPLE LOCAL end radar 4157812 */ return objc_build_method_signature (type, sel, parms, ellipsis); } @@ -6227,7 +6780,8 @@ c_parser_objc_type_name (c_parser *parser) || token->keyword == RID_BYREF || token->keyword == RID_ONEWAY)) { - quals = chainon (quals, build_tree_list (NULL_TREE, token->value)); + /* APPLE LOCAL radar 4301047 (in 4.2 z) */ + quals = chainon (build_tree_list (NULL_TREE, token->value), quals); c_parser_consume_token (parser); } else @@ -6301,14 +6855,26 @@ c_parser_objc_try_catch_statement (c_parser *parser) c_parser_consume_token (parser); if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) break; - parm = c_parser_parameter_declaration (parser, NULL_TREE); - if (parm == NULL) + /* APPLE LOCAL begin radar 2848255 */ + if (c_parser_next_token_is (parser, CPP_ELLIPSIS)) { - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); - break; + /* @catch (...) */ + c_parser_consume_token (parser); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + objc_begin_catch_clause (NULL_TREE); } - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); - objc_begin_catch_clause (grokparm (parm)); + else + { + parm = c_parser_parameter_declaration (parser, NULL_TREE); + if (parm == NULL) + { + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + break; + } + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + objc_begin_catch_clause (grokparm (parm)); + } + /* APPLE LOCAL end radar 2848255 */ if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) c_parser_compound_statement_nostart (parser); objc_finish_catch_clause (); @@ -6325,6 +6891,26 @@ c_parser_objc_try_catch_statement (c_parser *parser) objc_finish_try_stmt (); } +/* APPLE LOCAL begin radar 5982990 */ +/* This routine is called from c_parser_objc_synchronized_statement + and is identical to c_parser_compound_statement with + the addition of volatizing local variables seen in the scope + of @synchroniz block. +*/ +static tree +c_parser_objc_synch_compound_statement (c_parser *parser) +{ + tree stmt; + if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + return error_mark_node; + stmt = c_begin_compound_stmt (true); + c_parser_compound_statement_nostart (parser); + if (flag_objc_sjlj_exceptions) + objc_mark_locals_volatile (NULL); + return c_end_compound_stmt (stmt, true); +} +/* APPLE LOCAL end radar 5982990 */ + /* Parse an objc-synchronized-statement. objc-synchronized-statement: @@ -6346,7 +6932,8 @@ c_parser_objc_synchronized_statement (c_parser *parser) } else expr = error_mark_node; - stmt = c_parser_compound_statement (parser); + /* APPLE LOCAL radar 5982990 */ + stmt = c_parser_objc_synch_compound_statement (parser); objc_build_synchronized (loc, expr, stmt); } @@ -7433,7 +8020,8 @@ c_parser_omp_for_loop (c_parser *parser) /* Parse the initialization declaration or expression. */ if (c_parser_next_token_starts_declspecs (parser)) { - c_parser_declaration_or_fndef (parser, true, true, true, true); + /* APPLE LOCAL radar 4708210 (for_objc_collection in 4.2) */ + c_parser_declaration_or_fndef (parser, true, true, true, true, NULL); decl = check_for_loop_decls (); if (decl == NULL) goto error_init; @@ -7902,4 +8490,980 @@ c_parse_file (void) the_parser = NULL; } +/* APPLE LOCAL begin radar 5732232 - blocks (C++ ce) */ + +/* APPLE LOCAL begin radar 6300081 */ + +/* This function builds a "generic" block struct type, to be passed + into the debug information for blocks pointers, to allow gdb to + find the actual function pointer for the block. Any time the Blocks + structure layout changes, this may also need to change. + + Currently a block pointer is a pointer to a __block_literal_n struct, + the third field of which is a pointer to a __block_descriptor struct, + whose third field is the function pointer. There are other fields as + well, but these are the ones gdb needs to know about to find the + function pointer. Therefore a generic block struct currently looks + like this: + + struct __block_literal_generic + { + void * __isa; + int __flags; + int __reserved; + void (*__FuncPtr)(void *); + struct __block_descriptor + { + unsigned long int reserved; + unsigned long int Size; + } *__descriptor; + }; + + IF AT ANY TIME THE STRUCTURE OF A __BLOCK_LITERAL_N CHANGES, THIS + MUST BE CHANGED ALSO!! + +*/ + +tree +/* APPLE LOCAL radar 6353006 */ +c_build_generic_block_struct_type (void) +{ + tree field_decl_chain; + tree field_decl; + tree block_struct_type; + + push_to_top_level (); + block_struct_type = start_struct (RECORD_TYPE, + get_identifier ("__block_literal_generic")); + + field_decl = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + field_decl_chain = field_decl; + + field_decl = build_decl (FIELD_DECL, get_identifier ("__flags"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + field_decl = build_decl (FIELD_DECL, get_identifier ("__reserved"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + /* void *__FuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"), ptr_type_node); + chainon (field_decl_chain, field_decl); + + field_decl = build_decl (FIELD_DECL, get_identifier ("__descriptor"), + build_block_descriptor_type (false)); + chainon (field_decl_chain, field_decl); + + TYPE_BLOCK_IMPL_STRUCT (block_struct_type) = 1; + finish_struct (block_struct_type, field_decl_chain, NULL_TREE); + pop_from_top_level (); + return block_struct_type; +} +/* APPLE LOCAL end radar 6300081 */ + +/* APPLE LOCAL begin radar 5847213 - radar 6329245 */ +/** build_block_struct_type - + struct __block_literal_n { + void *__isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int __flags; + int __reserved; + void *__FuncPtr; + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct __block_literal_n) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + } *__descriptor; + + // imported variables + int x; // ref variable list ... + int *y; // byref variable list + }; +*/ +static tree +build_block_struct_type (struct block_sema_info * block_impl) +{ + tree field_decl_chain, field_decl, chain; + char buffer[32]; + static int unique_count; + tree block_struct_type; + + /* Check and see if this block is required to have a Copy/Dispose + helper function. If yes, set BlockHasCopyDispose to TRUE. */ + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (block_requires_copying (TREE_VALUE (chain))) + { + block_impl->BlockHasCopyDispose = TRUE; + break; + } + + /* Further check to see that we have __block variables which require + Copy/Dispose helpers. */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + block_impl->BlockHasCopyDispose = TRUE; + break; + } + + sprintf(buffer, "__block_literal_%d", ++unique_count); + push_to_top_level (); + block_struct_type = start_struct (RECORD_TYPE, get_identifier (buffer)); + + /* void *__isa; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node); + field_decl_chain = field_decl; + + /* int __flags */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__flags"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + /* int __reserved */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__reserved"), + integer_type_node); + chainon (field_decl_chain, field_decl); + + /* void *__FuncPtr; */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"), ptr_type_node); + chainon (field_decl_chain, field_decl); + + /* struct __block_descriptor *__descriptor */ + field_decl = build_decl (FIELD_DECL, get_identifier ("__descriptor"), + build_block_descriptor_type (block_impl->BlockHasCopyDispose)); + chainon (field_decl_chain, field_decl); + + if (block_impl->BlockHasCopyDispose) + { + /* If inner block of a nested block has BlockHasCopyDispose, so + does its outer block. */ + if (block_impl->prev_block_info) + block_impl->prev_block_info->BlockHasCopyDispose = TRUE; + } + + /* int x; // ref variable list ... */ + for (chain = block_impl->block_ref_decl_list; chain; chain = TREE_CHAIN (chain)) + { + tree p = TREE_VALUE (chain); + /* Note! const-ness of copied in variable must not be carried over to the + type of the synthesized struct field. It prevents to assign to this + field when copy constructor is synthesized. */ + field_decl = build_decl (FIELD_DECL, DECL_NAME (p), + c_build_qualified_type (TREE_TYPE (p), + TYPE_UNQUALIFIED)); + chainon (field_decl_chain, field_decl); + } + + /* int *y; // byref variable list */ + for (chain = block_impl->block_byref_decl_list; chain; chain = TREE_CHAIN (chain)) + { + tree p = TREE_VALUE (chain); + field_decl = build_decl (FIELD_DECL, DECL_NAME (p), + TREE_TYPE (p)); + chainon (field_decl_chain, field_decl); + } + pop_from_top_level (); + finish_struct (block_struct_type, field_decl_chain, NULL_TREE); + return block_struct_type; +} + +/** build_descriptor_block_decl - + This routine builds a static block_descriptior variable of type: + struct __block_descriptor; and initializes it to: + {0, sizeof(struct literal_block_n), + copy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + destroy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE + } +*/ +static tree +build_descriptor_block_decl (tree block_struct_type, struct block_sema_info *block_impl) +{ + extern tree create_tmp_var_raw (tree, const char *); + static int desc_unique_count; + int size; + tree helper_addr, fields; + tree decl, constructor, initlist; + tree exp, bind; + char name [32]; + tree descriptor_type = + TREE_TYPE (build_block_descriptor_type (block_impl->BlockHasCopyDispose)); + + sprintf (name, "__block_descriptor_tmp_%d", ++desc_unique_count); + decl = create_tmp_var_raw (descriptor_type, name); + DECL_CONTEXT (decl) = NULL_TREE; + DECL_ARTIFICIAL (decl) = 1; + + /* Initialize "reserved" field to 0 for now. */ + fields = TYPE_FIELDS (descriptor_type); + initlist = build_tree_list (fields, build_int_cst (long_unsigned_type_node, 0)); + fields = TREE_CHAIN (fields); + + /* Initialize "Size" field. */ + size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_struct_type)); + initlist = tree_cons (fields, + build_int_cst (long_unsigned_type_node, size), + initlist); + + if (block_impl->BlockHasCopyDispose) + { + /* Initialize "CopyFuncPtr" and "DestroyFuncPtr" fields. */ + /* Helpers were previously generated completeley as a nested + function (and context was required for code gen.) But they are not, + so context must be set to NULL so initialization logic does not complain. */ + DECL_CONTEXT (block_impl->copy_helper_func_decl) = NULL_TREE; + fields = TREE_CHAIN (fields); + helper_addr = build_fold_addr_expr (block_impl->copy_helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + initlist = tree_cons (fields, helper_addr, initlist); + DECL_CONTEXT (block_impl->destroy_helper_func_decl) = NULL_TREE; + fields = TREE_CHAIN (fields); + helper_addr = build_fold_addr_expr (block_impl->destroy_helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + initlist = tree_cons (fields, helper_addr, initlist); + } + constructor = build_constructor_from_list (descriptor_type, + nreverse (initlist)); + TREE_CONSTANT (constructor) = 1; + TREE_STATIC (constructor) = 1; + TREE_READONLY (constructor) = 1; + DECL_INITIAL (decl) = constructor; + exp = build_stmt (DECL_EXPR, decl); + bind = build3 (BIND_EXPR, void_type_node, decl, exp, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + TREE_PUBLIC (decl) = 0; + TREE_STATIC (decl) = 1; + finish_decl (decl, constructor, NULL_TREE); + return decl; +} + +/** + build_block_struct_initlist - builds the initializer list: + { &_NSConcreteStackBlock or &_NSConcreteGlobalBlock // __isa, + BLOCK_USE_STRET | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL // __flags, + 0, // __reserved + &helper_1, // __FuncPtr, + &static_descriptor_variable // __descriptor, + x, // user variables. + &y + ... + } +*/ +static tree +build_block_struct_initlist (tree block_struct_type, + struct block_sema_info *block_impl) +{ + tree initlist, helper_addr; + tree chain, fields; + /* APPLE LOCAL radar 7735196 */ + unsigned int flags = 0; + static tree NSConcreteStackBlock_decl = NULL_TREE; + static tree NSConcreteGlobalBlock_decl = NULL_TREE; + tree descriptor_block_decl = build_descriptor_block_decl (block_struct_type, block_impl); + + if (block_impl->BlockHasCopyDispose) + /* Note! setting of this flag merely indicates to the runtime that + we have destroy_helper_block/copy_helper_block helper + routines. */ + flags |= BLOCK_HAS_COPY_DISPOSE; + /* APPLE LOCAL begin radar 7735196 */ + if (block_impl->return_type && aggregate_value_p(block_impl->return_type, 0)) + flags |= BLOCK_USE_STRET; + /* APPLE LOCAL end 7735196 */ + + fields = TYPE_FIELDS (block_struct_type); + /* APPLE LOCAL begin radar 6230297 */ + if (!current_function_decl || + (block_impl->block_ref_decl_list == NULL_TREE && + block_impl->block_byref_decl_list == NULL_TREE)) + /* APPLE LOCAL end radar 6230297 */ + { + /* This is a global block. */ + /* Find an existing declaration for _NSConcreteGlobalBlock or declare + extern void *_NSConcreteGlobalBlock; */ + if (NSConcreteGlobalBlock_decl == NULL_TREE) + { + tree name_id = get_identifier("_NSConcreteGlobalBlock"); + NSConcreteGlobalBlock_decl = lookup_name (name_id); + if (!NSConcreteGlobalBlock_decl) + { + NSConcreteGlobalBlock_decl = build_decl (VAR_DECL, name_id, ptr_type_node); + DECL_EXTERNAL (NSConcreteGlobalBlock_decl) = 1; + TREE_PUBLIC (NSConcreteGlobalBlock_decl) = 1; + pushdecl_top_level (NSConcreteGlobalBlock_decl); + rest_of_decl_compilation (NSConcreteGlobalBlock_decl, 0, 0); + } + } + /* APPLE LOCAL begin radar 6457359 */ + initlist = build_tree_list (fields, + convert (ptr_type_node, + build_fold_addr_expr (NSConcreteGlobalBlock_decl))); + /* APPLE LOCAL end radar 6457359 */ + flags |= BLOCK_IS_GLOBAL; + } + else + { + /* Find an existing declaration for _NSConcreteStackBlock or declare + extern void *_NSConcreteStackBlock; */ + if (NSConcreteStackBlock_decl == NULL_TREE) + { + tree name_id = get_identifier("_NSConcreteStackBlock"); + NSConcreteStackBlock_decl = lookup_name (name_id); + if (!NSConcreteStackBlock_decl) + { + NSConcreteStackBlock_decl = build_decl (VAR_DECL, name_id, ptr_type_node); + DECL_EXTERNAL (NSConcreteStackBlock_decl) = 1; + TREE_PUBLIC (NSConcreteStackBlock_decl) = 1; + pushdecl_top_level (NSConcreteStackBlock_decl); + rest_of_decl_compilation (NSConcreteStackBlock_decl, 0, 0); + } + } + /* APPLE LOCAL begin radar 6457359 */ + initlist = build_tree_list (fields, + convert (ptr_type_node, + build_fold_addr_expr (NSConcreteStackBlock_decl))); + /* APPLE LOCAL end radar 6457359 */ + } + fields = TREE_CHAIN (fields); + + /* __flags */ + initlist = tree_cons (fields, + build_int_cst (integer_type_node, flags), + initlist); + fields = TREE_CHAIN (fields); + + /* __reserved */ + initlist = tree_cons (fields, + build_int_cst (integer_type_node, 0), + initlist); + fields = TREE_CHAIN (fields); + + /* __FuncPtr */ + helper_addr = build_fold_addr_expr (block_impl->helper_func_decl); + helper_addr = convert (ptr_type_node, helper_addr); + initlist = tree_cons (fields, helper_addr, initlist); + fields = TREE_CHAIN (fields); + + /* __descriptor */ + /* APPLE LOCAL begin radar 6457359 */ + initlist = tree_cons (fields, + build_fold_addr_expr (descriptor_block_decl), + initlist); + /* APPLE LOCAL end radar 6457359 */ + for (chain = block_impl->block_original_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + { + tree y = TREE_VALUE (chain); + TREE_USED (y) = 1; + fields = TREE_CHAIN (fields); + initlist = tree_cons (fields, y, initlist); + } + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + { + tree y = lookup_name (DECL_NAME (TREE_VALUE (chain))); + tree forwarding_expr; + gcc_assert (y); + TREE_USED (y) = 1; + if (COPYABLE_BYREF_LOCAL_VAR (y)) + { + /* For variables declared __block, either the original one + at the point of declaration or the imported version (which is + initialized in the helper function's prologue) is used to + initilize the byref variable field in the temporary. */ + if (TREE_CODE (TREE_TYPE (y)) != RECORD_TYPE) + y = build_indirect_ref (y, "unary *"); + /* We will be using the __block_struct_variable.__forwarding as the + initializer. */ + forwarding_expr = build_component_ref (y, get_identifier ("__forwarding")); + } + else + /* Global variable is always assumed passed by its address. */ + forwarding_expr = build_fold_addr_expr (y); + fields = TREE_CHAIN (fields); + initlist = tree_cons (fields, forwarding_expr, initlist); + } + return initlist; +} + +/** + build_block_literal_tmp - This routine: + + 1) builds block type: + struct __block_literal_n { + void *__isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock + int __flags; + int __reserved; + void *__FuncPtr + struct __block_descriptor { + unsigned long int reserved; // NULL + unsigned long int Size; // sizeof(struct Block_literal_1) + + // optional helper functions + void *CopyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE + } *__descriptor; + + // imported variables + int x; // ref variable list ... + int *y; // byref variable list + }; + + 2) build function prototype: + double helper_1(struct __block_literal_n *ii, int z); + + 3) build the temporary initialization: + struct __block_literal_n I = { + &_NSConcreteStackBlock or &_NSConcreteGlobalBlock // __isa, + BLOCK_USE_STRET | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL // __flags, + 0, // __reserved + &helper_1, // __FuncPtr + &static_descriptor_variable // __descriptor, + x, // user variables. + &y + ... + }; +It return the temporary. +*/ + +static tree +build_block_literal_tmp (const char *name, + struct block_sema_info * block_impl) +{ + extern tree create_tmp_var_raw (tree, const char *); + tree block_holder_tmp_decl; + tree constructor, initlist; + tree exp, bind; + tree block_struct_type = TREE_TYPE (block_impl->block_arg_ptr_type); + /* APPLE LOCAL begin radar 6230297 */ + bool staticBlockTmp = (block_impl->block_ref_decl_list == NULL_TREE && + block_impl->block_byref_decl_list == NULL_TREE); + + + block_holder_tmp_decl = create_tmp_var_raw (block_struct_type, name); + /* Context will not be known until when the literal is synthesized. + This is more so in the case of nested block literal blocks. */ + DECL_CONTEXT (block_holder_tmp_decl) = staticBlockTmp ? NULL_TREE + : current_function_decl; + /* In the new ABI, helper function decl. is the initializer for the + descriptor variable which is always declared static. So, it must + have no context; otherwise, gcc thinks that it requires trampoline! when + address of this function is used as initializer. */ + DECL_CONTEXT (block_impl->helper_func_decl) = NULL_TREE; + /* APPLE LOCAL end radar 6230297 */ + DECL_ARTIFICIAL (block_holder_tmp_decl) = 1; + + initlist = build_block_struct_initlist (block_struct_type, + block_impl); + initlist = nreverse (initlist); + constructor = build_constructor_from_list (block_struct_type, + initlist); + TREE_CONSTANT (constructor) = 1; + TREE_STATIC (constructor) = 1; + TREE_READONLY (constructor) = 1; + DECL_INITIAL (block_holder_tmp_decl) = constructor; + exp = build_stmt (DECL_EXPR, block_holder_tmp_decl); + bind = build3 (BIND_EXPR, void_type_node, block_holder_tmp_decl, exp, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + /* Temporary representing a global block is made global static. */ + /* APPLE LOCAL radar 6230297 */ + if (staticBlockTmp || global_bindings_p ()) { + TREE_PUBLIC (block_holder_tmp_decl) = 0; + TREE_STATIC (block_holder_tmp_decl) = 1; + finish_decl (block_holder_tmp_decl, constructor, NULL_TREE); + } + return block_holder_tmp_decl; +} +/* APPLE LOCAL end radar 5847213 - radar 6329245 */ + +static tree +clean_and_exit (tree block) +{ + pop_function_context (); + free (finish_block (block)); + return error_mark_node; +} + +/** synth_copy_helper_block_func - This function synthesizes + void copy_helper_block (struct block* _dest, struct block *_src) function. +*/ + +static void +synth_copy_helper_block_func (struct block_sema_info * block_impl) +{ + tree stmt, chain, fnbody; + tree dst_arg, src_arg; + struct c_arg_info * arg_info; + /* Set up: (struct block* _dest, struct block *_src) parameters. */ + dst_arg = build_decl (PARM_DECL, get_identifier ("_dst"), + block_impl->block_arg_ptr_type); + DECL_CONTEXT (dst_arg) = cur_block->copy_helper_func_decl; + TREE_USED (dst_arg) = 1; + DECL_ARG_TYPE (dst_arg) = block_impl->block_arg_ptr_type; + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + block_impl->block_arg_ptr_type); + /* APPLE LOCAL radar 5847213 */ + DECL_CONTEXT (src_arg) = cur_block->copy_helper_func_decl; + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = block_impl->block_arg_ptr_type; + arg_info = xcalloc (1, sizeof (struct c_arg_info)); + TREE_CHAIN (dst_arg) = src_arg; + arg_info->parms = dst_arg; + arg_info->types = tree_cons (NULL_TREE, block_impl->block_arg_ptr_type, + tree_cons (NULL_TREE, + block_impl->block_arg_ptr_type, + NULL_TREE)); + /* function header synthesis. */ + push_function_context (); + start_block_helper_function (cur_block->copy_helper_func_decl); + store_parm_decls_from (arg_info); + + /* Body of the function. */ + stmt = c_begin_compound_stmt (true); + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (block_requires_copying (TREE_VALUE (chain))) + { + /* APPLE LOCAL begin radar 6175959 */ + int flag; + tree call_exp; + tree p = TREE_VALUE (chain); + tree dst_block_component, src_block_component; + dst_block_component = build_component_ref (build_indirect_ref (dst_arg, "->"), + DECL_NAME (p)); + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + if (TREE_CODE (TREE_TYPE (p)) == BLOCK_POINTER_TYPE) + /* _Block_object_assign(&_dest->myImportedBlock, _src->myImportedClosure, BLOCK_FIELD_IS_BLOCK) */ + flag = BLOCK_FIELD_IS_BLOCK; + else + /* _Block_object_assign(&_dest->myImportedBlock, _src->myImportedClosure, BLOCK_FIELD_IS_OBJECT) */ + flag = BLOCK_FIELD_IS_OBJECT; + dst_block_component = build_fold_addr_expr (dst_block_component); + call_exp = build_block_object_assign_call_exp (dst_block_component, src_block_component, flag); + add_stmt (call_exp); + /* APPLE LOCAL end radar 6175959 */ + } + + /* For each __block declared variable must generate call to: + _Block_object_assign(&_dest->myImportedBlock, _src->myImportedBlock, BLOCK_FIELD_IS_BYREF [|BLOCK_FIELD_IS_WEAK]) + */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + int flag = BLOCK_FIELD_IS_BYREF; + tree call_exp; + tree p = TREE_VALUE (chain); + tree dst_block_component, src_block_component; + dst_block_component = build_component_ref (build_indirect_ref (dst_arg, "->"), + DECL_NAME (p)); + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + /* _Block_object_assign(&_dest->myImportedClosure, _src->myImportedClosure, BLOCK_FIELD_IS_BYREF [|BLOCK_FIELD_IS_WEAK]) */ + if (COPYABLE_WEAK_BLOCK (p)) + flag |= BLOCK_FIELD_IS_WEAK; + + dst_block_component = build_fold_addr_expr (dst_block_component); + call_exp = build_block_object_assign_call_exp (dst_block_component, src_block_component, flag); + add_stmt (call_exp); + } + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + finish_function (); + pop_function_context (); + free (arg_info); +} + +static void +synth_destroy_helper_block_func (struct block_sema_info * block_impl) +{ + tree stmt, chain, fnbody; + tree src_arg; + struct c_arg_info * arg_info; + /* Set up: (struct block *_src) parameter. */ + src_arg = build_decl (PARM_DECL, get_identifier ("_src"), + block_impl->block_arg_ptr_type); + TREE_USED (src_arg) = 1; + DECL_ARG_TYPE (src_arg) = block_impl->block_arg_ptr_type; + arg_info = xcalloc (1, sizeof (struct c_arg_info)); + arg_info->parms = src_arg; + arg_info->types = tree_cons (NULL_TREE, block_impl->block_arg_ptr_type, + NULL_TREE); + + /* function header synthesis. */ + push_function_context (); + start_block_helper_function (cur_block->destroy_helper_func_decl); + store_parm_decls_from (arg_info); + + /* Body of the function. */ + stmt = c_begin_compound_stmt (true); + for (chain = block_impl->block_ref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (block_requires_copying (TREE_VALUE (chain))) + { + int flag; + tree rel_exp; + tree p = TREE_VALUE (chain); + tree src_block_component; + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + + if (TREE_CODE (TREE_TYPE (p)) == BLOCK_POINTER_TYPE) + /* _Block_object_dispose(_src->imported_object_0, BLOCK_FIELD_IS_BLOCK); */ + flag = BLOCK_FIELD_IS_BLOCK; + else + /* _Block_object_dispose(_src->imported_object_0, BLOCK_FIELD_IS_OBJECT); */ + flag = BLOCK_FIELD_IS_OBJECT; + rel_exp = build_block_object_dispose_call_exp (src_block_component, flag); + add_stmt (rel_exp); + } + + /* For each __block declared variable must generate call to: + _Block_object_dispose(_src->myImportedClosure, BLOCK_FIELD_IS_BYREF[|BLOCK_FIELD_IS_WEAK]) + */ + for (chain = block_impl->block_byref_decl_list; chain; + chain = TREE_CHAIN (chain)) + if (COPYABLE_BYREF_LOCAL_VAR (TREE_VALUE (chain))) + { + tree call_exp; + int flag = BLOCK_FIELD_IS_BYREF; + tree p = TREE_VALUE (chain); + tree src_block_component; + + src_block_component = build_component_ref (build_indirect_ref (src_arg, "->"), + DECL_NAME (p)); + if (COPYABLE_WEAK_BLOCK (p)) + flag |= BLOCK_FIELD_IS_WEAK; + /* _Block_object_dispose(_src->myImportedClosure, BLOCK_FIELD_IS_BYREF[|BLOCK_FIELD_IS_WEAK]) */ + call_exp = build_block_object_dispose_call_exp (src_block_component, flag); + add_stmt (call_exp); + } + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + finish_function (); + pop_function_context (); + free (arg_info); +} + +/* Parse a block-id. + + GNU Extension: + + block-id: + specifier-qualifier-list block-declarator + + Returns the DECL specified or implied. */ + +static tree +c_parser_block_id (c_parser* parser) +{ + struct c_declspecs *specs = build_null_declspecs (); + struct c_declarator *declarator; + bool dummy = false; + + c_parser_declspecs (parser, specs, false, true, true); + if (!specs->declspecs_seen_p) + { + c_parser_error (parser, "expected specifier-qualifier-list"); + return NULL; + } + pending_xref_error (); + finish_declspecs (specs); + declarator = c_parser_declarator (parser, specs->type_seen_p, + C_DTR_BLOCK, &dummy); + if (declarator == NULL) + return NULL; + + return grokblockdecl (specs, declarator); +} + +/* Parse a block-literal-expr. + + GNU Extension: + + block-literal-expr: + ^ parameter-declation-clause exception-specification [opt] compound-statement + ^ block-id compound-statement + + It synthesizes the helper function for later generation and builds + the necessary data to represent the block literal where it is + declared. */ +static tree +c_parser_block_literal_expr (c_parser* parser) +{ + char name [32]; + static int global_unique_count; + int unique_count = ++global_unique_count; + tree block_helper_function_decl; + tree expr, body, type, arglist = void_list_node, ftype; + tree self_arg, stmt; + struct c_arg_info *args = NULL; + tree arg_type = void_list_node; + struct block_sema_info *block_impl; + tree tmp; + bool open_paren_seen = false; + tree restype; + tree fnbody, typelist; + tree helper_function_type; + tree block; + /* APPLE LOCAL radar 6185344 */ + tree declared_block_return_type = NULL_TREE; + /* APPLE LOCAL radar 6237713 */ + tree attributes = NULL_TREE; + + c_parser_consume_token (parser); /* eat '^' */ + + /* APPLE LOCAL begin radar 6237713 */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + attributes = c_parser_attributes (parser); + /* APPLE LOCAL end radar 6237713 */ + + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + /* Parse the optional argument list */ + c_parser_consume_token (parser); + /* Open the scope to collect parameter decls */ + push_scope (); + args = c_parser_parms_declarator (parser, true, NULL_TREE); + /* Check for args as it might be NULL due to error. */ + if (args) + { + arglist = args->parms; + arg_type = args->types; + } + else + { + pop_scope (); + return error_mark_node; + } + open_paren_seen = true; + pop_scope (); + } + else if (c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) + { + /* Parse user declared return type. */ + tree decl; + + /* APPLE LOCAL begin radar 6237713 */ + if (attributes) + { + warning (0, "attributes before block type are ignored"); + attributes = NULL_TREE; + } + /* APPLE LOCAL end radar 6237713 */ + + decl = c_parser_block_id (parser); + + if (decl && decl != error_mark_node) + { + arg_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); + arglist = DECL_ARGUMENTS (decl); + declared_block_return_type = TREE_TYPE (TREE_TYPE (decl)); + } + } + + block = begin_block (); + + cur_block->arg_info = NULL; + if (declared_block_return_type) + { + cur_block->return_type = TYPE_MAIN_VARIANT (declared_block_return_type); + cur_block->block_has_return_type = true; + } + else + cur_block->return_type = NULL_TREE; + + if (args) + cur_block->arg_info = args; + else + cur_block->arg_info = xcalloc (1, sizeof (struct c_arg_info)); + + if (declared_block_return_type) + { + cur_block->arg_info->parms = arglist; + cur_block->arg_info->types = arg_type; + } + + /* Must also build hidden parameter .block_descriptor added to the helper + function, even though we do not know its type yet. */ + /* APPLE LOCAL radar 6404979 */ + self_arg = build_decl (PARM_DECL, get_identifier (".block_descriptor"), + ptr_type_node); + TREE_USED (self_arg) = 1; /* Prevent unused parameter '.block_descriptor' warning. */ + TREE_CHAIN (self_arg) = cur_block->arg_info->parms; + cur_block->arg_info->types = tree_cons (NULL_TREE, ptr_type_node, arg_type); + cur_block->arg_info->parms = self_arg; + + /* APPLE LOCAL begin radar 6185344 */ + /* Build the declaration of the helper function (if we do not know its result + type yet, assume it is 'void'. If user provided it, use it). + Treat this as a nested function and use nested function infrastructure for + its generation. */ + + ftype = build_function_type ((!cur_block->block_has_return_type + ? void_type_node : cur_block->return_type), + cur_block->arg_info->types); + /* APPLE LOCAL end radar 6185344 */ + /* APPLE LOCAL radar 6160536 - radar 6411649 */ + block_helper_function_decl = build_helper_func_decl (build_block_helper_name (0), + ftype); + DECL_CONTEXT (block_helper_function_decl) = current_function_decl; + cur_block->helper_func_decl = block_helper_function_decl; + + push_function_context (); + start_block_helper_function (cur_block->helper_func_decl); + /* Set block's scope to the scope of the helper function's main body. + This is primarily used when nested blocks are declared. */ + /* FIXME: Name of objc_get_current_scope needs to get changed. */ + cur_block->the_scope = (struct c_scope*)objc_get_current_scope (); + + /* Enter parameter list to the scope of the helper function. */ + store_parm_decls_from (cur_block->arg_info); + + /* APPLE LOCAL begin radar 6237713 */ + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + attributes = c_parser_attributes (parser); + /* APPLE LOCAL radar 6246527 */ + any_recognized_block_attribute (attributes); + decl_attributes (&cur_block->helper_func_decl, attributes, 0); + /* APPLE LOCAL end radar 6237713 */ + + /* Start parsing body or expression part of the block literal. */ + if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) { + tree save_c_break_label = c_break_label; + tree save_c_cont_label = c_cont_label; + /* Indicate no valid break/continue context by setting these variables + to some non-null, non-label value. We'll notice and emit the proper + error message in c_finish_bc_stmt. */ + c_break_label = c_cont_label = size_zero_node; + c_parser_consume_token (parser); /* Consure '{'. */ + stmt = c_begin_compound_stmt (true); + c_parser_compound_statement_nostart (parser); + c_cont_label = save_c_cont_label; + c_break_label = save_c_break_label; + } + else + { + struct c_expr expr; + stmt = c_begin_compound_stmt (true); + error ("blocks require { }"); + expr = c_parser_cast_expression (parser, NULL); + body = expr.value; + if (body == error_mark_node) + return clean_and_exit (block); + + if (cur_block->return_type) + { + error ("return not allowed in block expression literal"); + return clean_and_exit (block); + } + else if (!open_paren_seen) + { + error ("argument list is required for block expression literals"); + return clean_and_exit (block); + } + else + { + tree restype = TYPE_MAIN_VARIANT (TREE_TYPE (body)); + + add_stmt (body); + TREE_TYPE (current_function_decl) + = build_function_type (restype, + TYPE_ARG_TYPES (TREE_TYPE (current_function_decl))); + TREE_TYPE (DECL_RESULT (current_function_decl)) = restype; + relayout_decl (DECL_RESULT (current_function_decl)); + cur_block->return_type = restype; + } + } + + cur_block->block_arg_ptr_type = + build_pointer_type (build_block_struct_type (cur_block)); + + restype = !cur_block->return_type ? void_type_node + : cur_block->return_type; + if (restype == error_mark_node) + return clean_and_exit (block); + + /* Now that we know type of the hidden .block_descriptor argument, fix its type. */ + TREE_TYPE (self_arg) = cur_block->block_arg_ptr_type; + DECL_ARG_TYPE (self_arg) = cur_block->block_arg_ptr_type; + + /* The DECL_RESULT should already have the correct type by now. */ + gcc_assert (TREE_TYPE (DECL_RESULT (current_function_decl)) + == restype); + + cur_block->block_body = stmt; + block_build_prologue (cur_block); + + fnbody = c_end_compound_stmt (stmt, true); + add_stmt (fnbody); + + /* We are done parsing of the block body. Return type of block is now known. + We also know all we need to know about the helper function. So, fix its + type here. */ + /* We moved this here because for global blocks, helper function body is + not nested and is gimplified in call to finish_function() and return type + of the function must be correct. */ + ftype = build_function_type (restype, arg_type); + /* Declare helper function; as in: + double helper_1(struct block_1 *ii, int z); */ + typelist = TYPE_ARG_TYPES (ftype); + /* (struct block_1 *ii, int z, ...) */ + typelist = tree_cons (NULL_TREE, cur_block->block_arg_ptr_type, + typelist); + helper_function_type = build_function_type (TREE_TYPE (ftype), typelist); + TREE_TYPE (cur_block->helper_func_decl) = helper_function_type; + finish_function (); + pop_function_context (); + + /* Build the declaration for copy_helper_block and destroy_helper_block + helper functions for later use. */ + + if (cur_block->BlockHasCopyDispose) + { + /* void copy_helper_block (struct block*, struct block *); */ + tree s_ftype = build_function_type (void_type_node, + tree_cons (NULL_TREE, cur_block->block_arg_ptr_type, + tree_cons (NULL_TREE, + cur_block->block_arg_ptr_type, + void_list_node))); + sprintf (name, "__copy_helper_block_%d", unique_count); + cur_block->copy_helper_func_decl = + build_helper_func_decl (get_identifier (name), s_ftype); + synth_copy_helper_block_func (cur_block); + + /* void destroy_helper_block (struct block*); */ + s_ftype = build_function_type (void_type_node, + tree_cons (NULL_TREE, + cur_block->block_arg_ptr_type, void_list_node)); + sprintf (name, "__destroy_helper_block_%d", unique_count); + cur_block->destroy_helper_func_decl = + build_helper_func_decl (get_identifier (name), s_ftype); + synth_destroy_helper_block_func (cur_block); + } + + block_impl = finish_block (block); + + /* Build unqiue name of the temporary used in code gen. */ + sprintf (name, "__block_holder_tmp_%d", unique_count); + tmp = build_block_literal_tmp (name, block_impl); + tmp = build_fold_addr_expr (tmp); + type = build_block_pointer_type (ftype); + expr = convert (type, convert (ptr_type_node, tmp)); + free (block_impl); + return expr; +} +/* APPLE LOCAL end radar 5732232 - blocks (C++ ce) */ + #include "gt-c-parser.h" |