summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/parser.c')
-rw-r--r--contrib/gcc/cp/parser.c2479
1 files changed, 2401 insertions, 78 deletions
diff --git a/contrib/gcc/cp/parser.c b/contrib/gcc/cp/parser.c
index 94f9078..90e49f0 100644
--- a/contrib/gcc/cp/parser.c
+++ b/contrib/gcc/cp/parser.c
@@ -38,6 +38,8 @@
#include "target.h"
#include "cgraph.h"
#include "c-common.h"
+/* APPLE LOCAL C* language */
+#include "tree-iterator.h"
/* The lexer. */
@@ -1120,6 +1122,10 @@ typedef enum cp_parser_flags
typedef enum cp_parser_declarator_kind
{
+ /* APPLE LOCAL begin blocks 6339747 */
+ /* We want a block declarator. */
+ CP_PARSER_DECLARATOR_BLOCK,
+ /* APPLE LOCAL end blocks 6339747 */
/* We want an abstract declarator. */
CP_PARSER_DECLARATOR_ABSTRACT,
/* We want a named declarator. */
@@ -1539,6 +1545,23 @@ static tree cp_parser_constant_expression
(cp_parser *, bool, bool *);
static tree cp_parser_builtin_offsetof
(cp_parser *);
+/* APPLE LOCAL begin blocks 6040305 (ca) */
+static tree cp_parser_block_literal_expr (cp_parser *);
+/* APPLE LOCAL end blocks 6040305 (ca) */
+/* APPLE LOCAL begin C* language */
+static void objc_foreach_stmt
+ (cp_parser *, tree);
+/* APPLE LOCAL end C* language */
+/* APPLE LOCAL begin C* property (Radar 4436866) */
+static void objc_cp_parser_at_property
+ (cp_parser *);
+static void objc_cp_parse_property_decl
+ (cp_parser *);
+/* APPLE LOCAL end C* property (Radar 4436866) */
+/* APPLE LOCAL begin radar 4548636 */
+static bool objc_attr_follwed_by_at_keyword
+ (cp_parser *);
+/* APPLE LOCAL end radar 4548636 */
/* Statements [gram.stmt.stmt] */
@@ -1549,7 +1572,8 @@ static void cp_parser_label_for_labeled_statement
static tree cp_parser_expression_statement
(cp_parser *, tree);
static tree cp_parser_compound_statement
- (cp_parser *, tree, bool);
+ /* APPLE LOCAL radar 5982990 */
+ (cp_parser *, tree, bool, bool);
static void cp_parser_statement_seq_opt
(cp_parser *, tree);
static tree cp_parser_selection_statement
@@ -1777,6 +1801,10 @@ static tree cp_parser_objc_message_args
(cp_parser *);
static tree cp_parser_objc_message_expression
(cp_parser *);
+/* APPLE LOCAL begin radar 5277239 */
+static tree cp_parser_objc_reference_expression
+ (cp_parser *, tree);
+/* APPLE LOCAL end radar 5277239 */
static tree cp_parser_objc_encode_expression
(cp_parser *);
static tree cp_parser_objc_defs_expression
@@ -1791,8 +1819,18 @@ static bool cp_parser_objc_selector_p
(enum cpp_ttype);
static tree cp_parser_objc_selector
(cp_parser *);
+/* APPLE LOCAL begin radar 3803157 - objc attribute */
+static void cp_parser_objc_maybe_attributes
+(cp_parser *, tree *);
+static tree cp_parser_objc_identifier_list
+(cp_parser *);
+/* APPLE LOCAL end radar 3803157 - objc attribute */
static tree cp_parser_objc_protocol_refs_opt
(cp_parser *);
+/* APPLE LOCAL begin radar 5355344 */
+static bool cp_parser_objc_tentative_protocol_refs_opt
+ (cp_parser *, tree *);
+/* APPLE LOCAL end radar 5355344 */
static void cp_parser_objc_declaration
(cp_parser *);
static tree cp_parser_objc_statement
@@ -2443,6 +2481,141 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
}
}
+/* APPLE LOCAL begin radar 5277239 */
+/* This routine checks that type_decl is a class or class object followed by a '.'
+ which is an alternative syntax to class-method messaging [class-name class-method]
+ */
+
+static bool
+cp_objc_property_reference_prefix (cp_parser *parser, tree type)
+{
+ return c_dialect_objc () && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
+ && (objc_is_id (type) || objc_is_class_name (type));
+}
+/* APPLE LOCAL end radar 5277239 */
+/* APPLE LOCAL begin C* property (Radar 4436866, 4591909) */
+/* This routine parses the propery declarations. */
+
+static void
+objc_cp_parse_property_decl (cp_parser *parser)
+{
+ int declares_class_or_enum;
+ cp_decl_specifier_seq declspecs;
+
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_NONE,
+ &declspecs,
+ &declares_class_or_enum);
+ /* Keep going until we hit the `;' at the end of the declaration. */
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ {
+ tree property;
+ cp_token *token;
+ cp_declarator *declarator
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ NULL, NULL, false);
+ property = grokdeclarator (declarator, &declspecs, NORMAL,0, NULL);
+ /* Revover from any kind of error in property declaration. */
+ if (property == error_mark_node || property == NULL_TREE)
+ return;
+ /* Add to property list. */
+ objc_add_property_variable (copy_node (property));
+ if (token->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ continue;
+ }
+ else if (token->type == CPP_EOF)
+ return;
+ }
+ cp_lexer_consume_token (parser->lexer); /* Eat ';'. */
+}
+
+/* This function parses a @property declaration inside an objective class
+ or its implementation. */
+
+static void
+objc_cp_parser_at_property (cp_parser *parser)
+{
+ cp_token *token;
+
+ objc_set_property_attr (0, NULL_TREE);
+ /* Consume @property */
+ cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_OPEN_PAREN)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ while (token->type != CPP_CLOSE_PAREN && token->type != CPP_EOF)
+ {
+ tree node;
+ /* property has attribute list. */
+ /* Consume '(' */
+ node = cp_parser_identifier (parser);
+ if (node == ridpointers [(int) RID_READONLY])
+ {
+ /* Do the readyonly thing. */
+ objc_set_property_attr (1, NULL_TREE);
+ }
+ else if (node == ridpointers [(int) RID_GETTER]
+ || node == ridpointers [(int) RID_SETTER])
+ {
+ /* Do the getter/setter attribute. */
+ token = cp_lexer_consume_token (parser->lexer);
+ if (token->type == CPP_EQ)
+ {
+ /* APPLE LOCAL radar 4675792 */
+ tree attr_ident = cp_parser_objc_selector (parser);
+ int num;
+ if (node == ridpointers [(int) RID_GETTER])
+ num = 2;
+ else
+ {
+ num = 3;
+ /* Consume the ':' which must always follow the setter name. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ objc_set_property_attr (num, attr_ident);
+ }
+ else
+ {
+ error ("getter/setter attribute must be followed by '='");
+ break;
+ }
+ }
+ /* APPLE LOCAL begin radar 4947014 - objc atomic property */
+ else if (node == ridpointers [(int) RID_NONATOMIC])
+ {
+ objc_set_property_attr (13, NULL_TREE);
+ }
+ /* APPLE LOCAL end radar 4947014 - objc atomic property */
+ else
+ {
+ error ("unknown property attribute");
+ break;
+ }
+ /* APPLE LOCAL begin radar 6302949 */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
+ warning (0, "property attributes must be separated by a comma");
+ /* APPLE LOCAL end radar 6302949 */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+ if (token->type != CPP_CLOSE_PAREN)
+ {
+ error ("syntax error in @property's attribute declaration");
+ }
+ /* Consume ')' */
+ cp_lexer_consume_token (parser->lexer);
+ }
+ objc_cp_parse_property_decl (parser);
+}
+/* APPLE LOCAL end C* property (Radar 4436866, 4591909) */
+
/* This function is called at the end of a statement or declaration.
If the next token is a semicolon, it is consumed; otherwise, error
recovery is attempted. */
@@ -2901,6 +3074,8 @@ cp_parser_translation_unit (cp_parser* parser)
( compound-statement )
__builtin_va_arg ( assignment-expression , type-id )
__builtin_offsetof ( type-id , offsetof-expression )
+ APPLE LOCAL blocks 6040305 (cf)
+ block-literal-expr
Objective-C++ Extension:
@@ -2934,6 +3109,16 @@ cp_parser_primary_expression (cp_parser *parser,
token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
{
+ /* APPLE LOCAL begin blocks 6040305 (cf) */
+ case CPP_XOR:
+ if (flag_blocks)
+ {
+ tree expr = cp_parser_block_literal_expr (parser);
+ return expr;
+ }
+ cp_parser_error (parser, "expected primary-expression");
+ return error_mark_node;
+ /* APPLE LOCAL end blocks 6040305 (cf) */
/* literal:
integer-literal
character-literal
@@ -3027,7 +3212,8 @@ cp_parser_primary_expression (cp_parser *parser,
/* Start the statement-expression. */
expr = begin_stmt_expr ();
/* Parse the compound-statement. */
- cp_parser_compound_statement (parser, expr, false);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, expr, false, false);
/* Finish up. */
expr = finish_stmt_expr (expr, false);
}
@@ -3197,6 +3383,11 @@ cp_parser_primary_expression (cp_parser *parser,
if (ambiguous_decls)
return error_mark_node;
+ /* APPLE LOCAL begin radar 5277239 */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && cp_objc_property_reference_prefix (parser, TREE_TYPE (decl)))
+ return cp_parser_objc_reference_expression (parser, decl);
+ /* APPLE LOCAL end radar 5277239 */
/* In Objective-C++, an instance variable (ivar) may be preferred
to whatever cp_parser_lookup_name() found. */
decl = objc_lookup_ivar (decl, id_expression);
@@ -6329,7 +6520,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
}
/* Anything that starts with a `{' must be a compound-statement. */
else if (token->type == CPP_OPEN_BRACE)
- statement = cp_parser_compound_statement (parser, NULL, false);
+ /* APPLE LOCAL radar 5982990 */
+ statement = cp_parser_compound_statement (parser, NULL, false, false);
/* CPP_PRAGMA is a #pragma inside a function body, which constitutes
a statement all its own. */
else if (token->type == CPP_PRAGMA)
@@ -6503,7 +6695,8 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
static tree
cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
- bool in_try)
+ /* APPLE LOCAL radar 5982990 */
+ bool in_try, bool objc_sjlj_exceptions)
{
tree compound_stmt;
@@ -6514,6 +6707,10 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
/* Parse an (optional) statement-seq. */
cp_parser_statement_seq_opt (parser, in_statement_expr);
+ /* APPLE LOCAL begin radar 5982990 */
+ if (objc_sjlj_exceptions)
+ objc_mark_locals_volatile (NULL);
+ /* APPLE LOCAL end radar 5982990 */
/* Finish the compound-statement. */
finish_compound_stmt (compound_stmt);
/* Consume the `}'. */
@@ -6531,17 +6728,45 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
static void
cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
{
+ /* APPLE LOCAL begin omit calls to empty destructors 5559195 */
+ tree class_type = DECL_CONTEXT (current_function_decl);
+
+ bool determine_destructor_triviality =
+ DECL_DESTRUCTOR_P (current_function_decl) && class_type != NULL_TREE
+ && !CLASSTYPE_DESTRUCTOR_TRIVIALITY_FINAL (class_type);
+
+ /* Assume that the destructor is trivial at first, and mark nontrivial if
+ any statement is parsed. */
+ if (determine_destructor_triviality)
+ {
+ CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (class_type) = 0;
+ CLASSTYPE_DESTRUCTOR_TRIVIALITY_FINAL (class_type) = 1;
+ }
+ /* APPLE LOCAL end omit calls to empty destructors 5559195 */
+
/* Scan statements until there aren't any more. */
while (true)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- /* If we're looking at a `}', then we've run out of statements. */
+ /* APPLE LOCAL begin ObjC++ 4185810 */
+ /* If we're looking at a `}', then we've run out of
+ statements; the same is true if we have reached the end
+ of file, or have stumbled upon a stray 'else' or '@end'. */
if (token->type == CPP_CLOSE_BRACE
|| token->type == CPP_EOF
- || token->type == CPP_PRAGMA_EOL)
+ || token->type == CPP_PRAGMA_EOL
+ || (token->type == CPP_KEYWORD
+ && (token->keyword == RID_ELSE
+ || token->keyword == RID_AT_END)))
+ /* APPLE LOCAL end ObjC++ 4185810 */
break;
+ /* APPLE LOCAL begin omit calls to empty destructors 5559195 */
+ if (determine_destructor_triviality)
+ CLASSTYPE_HAS_NONTRIVIAL_DESTRUCTOR_BODY (class_type) = 1;
+ /* APPLE LOCAL end omit calls to empty destructors 5559195 */
+
/* Parse the statement. */
cp_parser_statement (parser, in_statement_expr, true, NULL);
}
@@ -6779,11 +7004,119 @@ cp_parser_condition (cp_parser* parser)
return cp_parser_expression (parser, /*cast_p=*/false);
}
+/* APPLE LOCAL begin radar 4631818 */
+/* This routine looks for objective-c++'s foreach statement by scanning for-loop
+ header looking for either 1) 'for (type selector in...)' or 2) 'for (selector in...)'
+ where selector is already declared in outer scope. If it failed, it undoes the lexical
+ look-ahead and returns false. If it succeeded, it adds the 'selector' to the statement
+ list and returns true. At success, lexer points to token following the 'in' keyword.
+*/
+
+static bool
+cp_parser_parse_foreach_stmt (cp_parser *parser)
+{
+ int decl_spec_declares_class_or_enum;
+ bool is_cv_qualifier;
+ tree type_spec;
+ cp_decl_specifier_seq decl_specs;
+ tree node;
+ cp_token *token;
+ bool is_legit_foreach = false;
+ cp_declarator *declarator;
+
+ /* Exclude class/struct/enum type definition in for-loop header, which is
+ aparently legal in c++. Otherwise, it causes side-effect (type is enterred
+ in function's scope) when type is re-parsed. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (cp_parser_token_is_class_key (token) || token->keyword == RID_ENUM)
+ return false;
+
+ cp_parser_parse_tentatively (parser);
+ clear_decl_specs (&decl_specs);
+ type_spec
+ = cp_parser_type_specifier (parser, CP_PARSER_FLAGS_OPTIONAL,
+ &decl_specs,
+ /*is_declaration=*/true,
+ &decl_spec_declares_class_or_enum,
+ &is_cv_qualifier);
+ declarator
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ NULL,
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
+ if (declarator == cp_error_declarator)
+ {
+ cp_parser_abort_tentative_parse (parser);
+ return false;
+ }
+
+ token = cp_lexer_peek_token (parser->lexer);
+
+ node = token->u.value;
+ if (node && TREE_CODE (node) == IDENTIFIER_NODE
+ && node == ridpointers [(int) RID_IN])
+ {
+ enum cpp_ttype nt = cp_lexer_peek_nth_token (parser->lexer, 2)->type;
+ switch (nt)
+ {
+ case CPP_NAME:
+ case CPP_OPEN_PAREN:
+ case CPP_MULT:
+ case CPP_PLUS: case CPP_PLUS_PLUS:
+ case CPP_MINUS: case CPP_MINUS_MINUS:
+ case CPP_OPEN_SQUARE:
+ is_legit_foreach = true;
+ default:
+ break;
+ }
+ }
+ if (is_legit_foreach)
+ {
+ tree pushed_scope = NULL;
+ tree decl;
+ if (type_spec)
+ {
+ /* we have: 'for (type selector in...)' */
+ cp_parser_commit_to_tentative_parse (parser);
+ decl = start_decl (declarator, &decl_specs,
+ false /*is_initialized*/,
+ NULL_TREE /*attributes*/,
+ NULL_TREE /*prefix_attributes*/,
+ &pushed_scope);
+ /* APPLE LOCAL begin radar 5130983 */
+ if (!decl || decl == error_mark_node)
+ {
+ error ("selector is undeclared");
+ is_legit_foreach = false;
+ }
+ else
+ cp_finish_decl (decl,
+ NULL_TREE /*initializer*/,
+ false /*init_const_expr_p=*/,
+ NULL_TREE /*asm_specification*/,
+ 0 /*flags */);
+ }
+ else {
+ tree statement;
+ /* we have: 'for (selector in...)' */
+ /* Parse it as an expression. */
+ cp_parser_abort_tentative_parse (parser);
+ statement = cp_parser_expression (parser, /*cast_p=*/false);
+ add_stmt (statement);
+ }
+ /* APPLE LOCAL end radar 5130983 */
+ /* Consume the 'in' token */
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ cp_parser_abort_tentative_parse (parser);
+ return is_legit_foreach;
+}
+/* APPLE LOCAL end radar 4631818 */
+
/* Parse an iteration-statement.
iteration-statement:
- while ( condition ) statement
- do statement while ( expression ) ;
for ( for-init-statement condition [opt] ; expression [opt] )
statement
@@ -7050,6 +7383,10 @@ cp_parser_jump_statement (cp_parser* parser)
break;
case RID_GOTO:
+ /* APPLE LOCAL begin blocks 6040305 (cb) */
+ if (cur_block)
+ error ("goto not allowed in block literal");
+ /* APPLE LOCAL end blocks 6040305 (cb) */
/* Create the goto-statement. */
if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
{
@@ -7130,7 +7467,8 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p)
}
/* if a compound is opened, we simply parse the statement directly. */
else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
- statement = cp_parser_compound_statement (parser, NULL, false);
+ /* APPLE LOCAL radar 5982990 */
+ statement = cp_parser_compound_statement (parser, NULL, false, false);
/* If the token is not a `{', then we must take special action. */
else
{
@@ -11453,6 +11791,37 @@ cp_parser_init_declarator (cp_parser* parser,
return decl;
}
+/* APPLE LOCAL begin blocks 6040305 (cc) */
+static cp_cv_quals
+cp_parser_cv_qualifier_or_attribute_seq_opt (cp_parser *parser, tree *attrs_p)
+{
+ cp_cv_quals quals = TYPE_UNQUALIFIED;
+ cp_cv_quals q;
+ cp_token *token;
+
+ *attrs_p = NULL_TREE;
+ while (true)
+ {
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* Handle attributes. */
+ if (token->keyword == RID_ATTRIBUTE)
+ {
+ /* Parse the attributes. */
+ *attrs_p = chainon (*attrs_p,
+ cp_parser_attributes_opt (parser));
+ continue;
+ }
+
+ q = cp_parser_cv_qualifier_seq_opt (parser);
+ if (q == TYPE_UNQUALIFIED)
+ break;
+ quals |= q;
+ }
+ return quals;
+}
+/* APPLE LOCAL end blocks 6040305 (cc) */
+
/* Parse a declarator.
declarator:
@@ -11473,6 +11842,12 @@ cp_parser_init_declarator (cp_parser* parser,
attributes [opt] ptr-operator abstract-declarator [opt]
attributes [opt] direct-abstract-declarator
+ APPLE LOCAL begin blocks 6339747
+ block-declarator:
+ attributes [opt] ptr-operator block-declarator [opt]
+ attributes [opt] direct-block-declarator
+ APPLE LOCAL end blocks 6339747
+
If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
detect constructor, destructor or conversion operators. It is set
to -1 if the declarator is a name, and +1 if it is a
@@ -11517,6 +11892,28 @@ cp_parser_declarator (cp_parser* parser,
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
+ /* APPLE LOCAL begin blocks 6040305 (cc) */
+ if (flag_blocks && token->type == CPP_XOR)
+ {
+ cp_cv_quals quals;
+ cp_declarator *inner;
+ tree attrs;
+
+ cp_lexer_consume_token (parser->lexer);
+
+ /* cp_parse_declspecs (parser, quals_attrs, false, false, true); */
+ quals = cp_parser_cv_qualifier_or_attribute_seq_opt (parser, &attrs);
+
+ inner = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
+ /*ctor_dtor_or_conv_p=*/NULL,
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
+ if (inner == cp_error_declarator)
+ return inner;
+ return make_block_pointer_declarator (attrs, quals, inner);
+ }
+ /* APPLE LOCAL end blocks 6040305 (cc) */
+
/* Check for the ptr-operator production. */
cp_parser_parse_tentatively (parser);
/* Parse the ptr-operator. */
@@ -11592,6 +11989,17 @@ cp_parser_declarator (cp_parser* parser,
direct-abstract-declarator [opt] [ constant-expression [opt] ]
( abstract-declarator )
+ APPLE LOCAL begin blocks 6339747
+ GNU Extensions:
+
+ direct-block-declarator:
+ direct-block-declarator [opt]
+ ( parameter-declaration-clause ) [opt]
+ exception-specification [opt]
+ direct-block-declarator [opt] [ constant-expression [opt] ]
+ ( block-declarator )
+ APPLE LOCAL end blocks 6339747
+
Returns a representation of the declarator. DCL_KIND is
CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a
direct-abstract-declarator. It is CP_PARSER_DECLARATOR_NAMED, if
@@ -11708,8 +12116,16 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Consume the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- /* Parse the cv-qualifier-seq. */
- cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+ /* APPLE LOCAL begin blocks 6339747 */
+ if (dcl_kind != BLOCKDEF)
+ {
+ /* Parse the cv-qualifier-seq. */
+ cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+ }
+ else
+ cv_quals = TYPE_UNQUALIFIED;
+ /* APPLE LOCAL end blocks 6339747 */
+
/* And the exception-specification. */
exception_specification
= cp_parser_exception_specification_opt (parser);
@@ -11809,7 +12225,10 @@ cp_parser_direct_declarator (cp_parser* parser,
declarator = make_array_declarator (declarator, bounds);
}
- else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
+ /* APPLE LOCAL begin blocks 6339747 */
+ else if (first && (dcl_kind == CP_PARSER_DECLARATOR_NAMED
+ || dcl_kind == CP_PARSER_DECLARATOR_EITHER))
+ /* APPLE LOCAL end blocks 6339747 */
{
tree qualifying_scope;
tree unqualified_name;
@@ -11970,7 +12389,8 @@ cp_parser_direct_declarator (cp_parser* parser,
/* For an abstract declarator, we might wind up with nothing at this
point. That's an error; the declarator is not optional. */
- if (!declarator)
+ /* APPLE LOCAL blocks 6339747 */
+ if (!declarator && dcl_kind != CP_PARSER_DECLARATOR_BLOCK)
cp_parser_error (parser, "expected declarator");
/* If we entered a scope, we must exit it now. */
@@ -11994,6 +12414,8 @@ cp_parser_direct_declarator (cp_parser* parser,
ptr-operator:
& cv-qualifier-seq [opt]
+ APPLE LOCAL blocks 6040305 (cc)
+ ^
Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
Returns ADDR_EXPR if a reference was used. In the case of a
@@ -12776,7 +13198,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
static void
cp_parser_function_body (cp_parser *parser)
{
- cp_parser_compound_statement (parser, NULL, false);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, NULL, false, false);
}
/* Parse a ctor-initializer-opt followed by a function-body. Return
@@ -14533,7 +14956,8 @@ cp_parser_try_block (cp_parser* parser)
cp_parser_require_keyword (parser, RID_TRY, "`try'");
try_block = begin_try_block ();
- cp_parser_compound_statement (parser, NULL, true);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, NULL, true, false);
finish_try_block (try_block);
cp_parser_handler_seq (parser);
finish_handler_sequence (try_block);
@@ -14610,7 +15034,8 @@ cp_parser_handler (cp_parser* parser)
declaration = cp_parser_exception_declaration (parser);
finish_handler_parms (declaration, handler);
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- cp_parser_compound_statement (parser, NULL, false);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, NULL, false, false);
finish_handler (handler);
}
@@ -15395,6 +15820,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
case cdk_pointer:
case cdk_reference:
case cdk_ptrmem:
+ /* APPLE LOCAL blocks 6040305 */
+ case cdk_block_pointer:
return (cp_parser_check_declarator_template_parameters
(parser, declarator->declarator));
@@ -17103,6 +17530,25 @@ cp_parser_objc_message_expression (cp_parser* parser)
return objc_build_message_expr (build_tree_list (receiver, messageargs));
}
+/* APPLE LOCAL begin radar 5277239 */
+/* Parse an Objective-C dot-syntax class expression.
+
+ objc-message-expression:
+ class-name '.' class-method-name
+
+ Returns an objc_property_reference expression. */
+
+static tree
+cp_parser_objc_reference_expression (cp_parser* parser, tree type_decl)
+{
+ tree receiver, component;
+ receiver = objc_get_class_reference (TREE_TYPE (type_decl));
+ cp_lexer_consume_token (parser->lexer); /* Eact '.' */
+ component = cp_parser_objc_message_args (parser);
+ return objc_build_property_reference_expr (receiver, TREE_PURPOSE (component));
+}
+/* APPLE LOCAL end radar 5277239 */
+
/* Parse an objc-message-receiver.
objc-message-receiver:
@@ -17421,6 +17867,32 @@ cp_parser_objc_protocol_refs_opt (cp_parser* parser)
return protorefs;
}
+/* APPLE LOCAL begin radar 5355344 */
+/* This routine also parses a list of Objective-C protocol references; except that
+ if list is not valid, it returns FALSE and back-tracks parsing. */
+
+static bool
+cp_parser_objc_tentative_protocol_refs_opt (cp_parser* parser, tree *protorefs)
+{
+ *protorefs = NULL_TREE;
+ if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ {
+ cp_parser_parse_tentatively (parser);
+ cp_lexer_consume_token (parser->lexer); /* Eat '<'. */
+ *protorefs = cp_parser_objc_identifier_list (parser);
+ if (!cp_objc_protocol_id_list (*protorefs))
+ {
+ cp_parser_abort_tentative_parse (parser);
+ return false;
+ }
+ if (cp_parser_parse_definitely (parser))
+ cp_parser_require (parser, CPP_GREATER, "`>'");
+ }
+
+ return true;
+}
+/* APPLE LOCAL end radar 5355344 */
+
/* Parse a Objective-C visibility specification. */
static void
@@ -17554,10 +18026,25 @@ cp_parser_objc_selector (cp_parser* parser)
}
}
+/* APPLE LOCAL begin radar 3803157 - objc attribute */
+static void
+cp_parser_objc_maybe_attributes (cp_parser* parser, tree* attributes)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ if (*attributes != NULL_TREE)
+ {
+ error ("method attributes must be specified at the end only");
+ *attributes = NULL_TREE;
+ }
+ if (token->keyword == RID_ATTRIBUTE)
+ *attributes = cp_parser_attributes_opt (parser);
+}
+
/* Parse an Objective-C params list. */
static tree
-cp_parser_objc_method_keyword_params (cp_parser* parser)
+cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
+/* APPLE LOCAL end radar 3803157 - objc attribute */
{
tree params = NULL_TREE;
bool maybe_unary_selector_p = true;
@@ -17566,36 +18053,58 @@ cp_parser_objc_method_keyword_params (cp_parser* parser)
while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
{
tree selector = NULL_TREE, typename, identifier;
+ /* APPLE LOCAL radar 4157812 */
+ tree attr = 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))
- return selector;
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ /* APPLE LOCAL begin radar 3803157 - objc attribute */
+ {
+ cp_parser_objc_maybe_attributes (parser, attributes);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ return selector;
+ }
+ /* APPLE LOCAL end radar 3803157 - objc attribute */
maybe_unary_selector_p = false;
cp_parser_require (parser, CPP_COLON, "`:'");
typename = cp_parser_objc_typename (parser);
+ /* APPLE LOCAL radar 4157812 */
+ cp_parser_objc_maybe_attributes (parser, &attr);
identifier = cp_parser_identifier (parser);
+ /* APPLE LOCAL radar 3803157 - objc attribute */
+ cp_parser_objc_maybe_attributes (parser, attributes);
params
= chainon (params,
objc_build_keyword_decl (selector,
typename,
- identifier));
+ /* APPLE LOCAL radar 4157812 */
+ identifier, attr));
token = cp_lexer_peek_token (parser->lexer);
}
+ /* APPLE LOCAL begin radar 4290840 */
+ if (params == NULL_TREE)
+ {
+ cp_parser_error (parser, "objective-c++ method declaration is expected");
+ return error_mark_node;
+ }
+ /* APPLE LOCAL end radar 4290840 */
+
return params;
}
/* Parse the non-keyword Objective-C params. */
static tree
-cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp)
+/* APPLE LOCAL radar 3803157 - objc attribute */
+cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, tree* attributes)
{
tree params = make_node (TREE_LIST);
cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -17610,11 +18119,13 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp)
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_ELLIPSIS)
- {
- cp_lexer_consume_token (parser->lexer); /* Eat '...'. */
- *ellipsisp = true;
- break;
- }
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat '...'. */
+ *ellipsisp = true;
+ /* APPLE LOCAL radar 3803157 - objc attribute */
+ cp_parser_objc_maybe_attributes (parser, attributes);
+ break;
+ }
parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
parm = grokdeclarator (parmdecl->declarator,
@@ -17655,15 +18166,19 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
/* Parse a method signature. */
static tree
-cp_parser_objc_method_signature (cp_parser* parser)
+/* APPLE LOCAL radar 3803157 - objc attribute */
+cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
{
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);
+ /* APPLE LOCAL begin radar 3803157 - objc attribute */
+ *attributes = NULL_TREE;
+ kwdparms = cp_parser_objc_method_keyword_params (parser, attributes);
+ optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes);
+ /* APPLE LOCAL end radar 3803157 - objc attribute */
return objc_build_method_signature (rettype, kwdparms, optparms, ellipsis);
}
@@ -17675,22 +18190,31 @@ cp_parser_objc_method_prototype_list (cp_parser* parser)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- while (token->keyword != RID_AT_END)
+ /* APPLE LOCAL 4093475 */
+ while (token->keyword != RID_AT_END && token->type != CPP_EOF)
{
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);
- }
+ {
+ /* APPLE LOCAL begin radar 3803157 - objc attribute */
+ tree attributes, sig;
+ sig = cp_parser_objc_method_signature (parser, &attributes);
+ objc_add_method_declaration (sig, attributes);
+ /* APPLE LOCAL end radar 3803157 - objc attribute */
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ }
+ /* APPLE LOCAL begin C* interface */
+ else if (token->keyword == RID_AT_PROPERTY)
+ objc_cp_parser_at_property (parser);
+ /* APPLE LOCAL end C* interface */
else
- /* Allow for interspersed non-ObjC++ code. */
+ /* 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'. */
+ /* APPLE LOCAL 4093475 */
+ cp_parser_require_keyword (parser, RID_AT_END, "`@end'");
objc_finish_interface ();
}
@@ -17701,27 +18225,49 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- while (token->keyword != RID_AT_END)
+ /* APPLE LOCAL 4093475 */
+ while (token->keyword != RID_AT_END && token->type != CPP_EOF)
{
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));
+ {
+ /* APPLE LOCAL radar 4290840 */
+ cp_token *ptk;
+ /* APPLE LOCAL begin radar 3803157 - objc attribute */
+ tree sig, attribute;
+ push_deferring_access_checks (dk_deferred);
+ sig = cp_parser_objc_method_signature (parser, &attribute);
+ objc_start_method_definition (sig, attribute);
+ /* APPLE LOCAL end radar 3803157 - objc attribute */
/* 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);
+ /* APPLE LOCAL begin radar 4290840 */
+ /* Check for all possibilities of illegal lookahead tokens. */
+ ptk = cp_lexer_peek_token (parser->lexer);
+ /* APPLE LOCAL radar 6271728 */
+ if (ptk->type == CPP_OPEN_BRACE)
+ {
+ 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);
}
+ /* APPLE LOCAL begin radar 6271728 */
+ else
+ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+ /* APPLE LOCAL end radar 6271728 */
+ /* APPLE LOCAL end radar 4290840 */
+ }
+ /* APPLE LOCAL begin C* interface */
+ else if (token->keyword == RID_AT_PROPERTY)
+ objc_cp_parser_at_property (parser);
+ /* APPLE LOCAL end C* interface */
else
/* Allow for interspersed non-ObjC++ code. */
cp_parser_objc_interstitial_code (parser);
@@ -17729,7 +18275,8 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
token = cp_lexer_peek_token (parser->lexer);
}
- cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ /* APPLE LOCAL 4093475 */
+ cp_parser_require_keyword (parser, RID_AT_END, "`@end'");
objc_finish_implementation ();
}
@@ -17855,7 +18402,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
/* Parse an Objective-C protocol declaration. */
static void
-cp_parser_objc_protocol_declaration (cp_parser* parser)
+/* APPLE LOCAL radar 4947311 */
+cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
{
tree proto, protorefs;
cp_token *tok;
@@ -17873,8 +18421,9 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
/* Try a forward declaration first. */
if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
{
- objc_declare_protocols (cp_parser_objc_identifier_list (parser));
- finish:
+ /* APPLE LOCAL radar 4947311 */
+ objc_declare_protocols (cp_parser_objc_identifier_list (parser), attributes);
+ finish:
cp_parser_consume_semicolon_at_end_of_statement (parser);
}
@@ -17883,20 +18432,23 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
{
proto = cp_parser_identifier (parser);
protorefs = cp_parser_objc_protocol_refs_opt (parser);
- objc_start_protocol (proto, protorefs);
+ /* APPLE LOCAL radar 4947311 */
+ objc_start_protocol (proto, protorefs, attributes);
cp_parser_objc_method_prototype_list (parser);
}
}
/* Parse an Objective-C superclass or category. */
+/* APPLE LOCAL begin radar 4965989 */
static void
cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
- tree *categ)
+ tree *categ, bool *is_category)
{
cp_token *next = cp_lexer_peek_token (parser->lexer);
*super = *categ = NULL_TREE;
+ *is_category = false;
if (next->type == CPP_COLON)
{
cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
@@ -17905,29 +18457,47 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
else if (next->type == CPP_OPEN_PAREN)
{
cp_lexer_consume_token (parser->lexer); /* Eat '('. */
- *categ = cp_parser_identifier (parser);
+ /* APPLE LOCAL begin radar 4965989 */
+ next = cp_lexer_peek_token (parser->lexer);
+ *categ = (next->type == CPP_CLOSE_PAREN) ? NULL_TREE : cp_parser_identifier (parser);
+ *is_category = true;
+ /* APPLE LOCAL end radar 4965989 */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
}
}
+/* APPLE LOCAL end radar 4965989 */
/* Parse an Objective-C class interface. */
static void
-cp_parser_objc_class_interface (cp_parser* parser)
+/* APPLE LOCAL radar 4947311 */
+cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
{
tree name, super, categ, protos;
-
+ /* APPLE LOCAL radar 4965989 */
+ bool is_categ;
+ /* APPLE LOCAL radar 4947311 */
+ /* Code for radar 4548636 removed. */
cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
name = cp_parser_identifier (parser);
- cp_parser_objc_superclass_or_category (parser, &super, &categ);
+ /* APPLE LOCAL radar 4965989 */
+ cp_parser_objc_superclass_or_category (parser, &super, &categ, &is_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);
+ /* APPLE LOCAL radar 4965989 */
+ if (is_categ)
+ /* APPLE LOCAL begin radar 4548636 */
+ {
+ if (attributes)
+ error ("attributes may not be specified on a category");
+ objc_start_category_interface (name, categ, protos);
+ }
+ /* APPLE LOCAL end radar 4548636 */
else
{
- objc_start_class_interface (name, super, protos);
+ /* APPLE LOCAL radar 4548636 */
+ objc_start_class_interface (name, super, protos, attributes);
/* Handle instance variable declarations, if any. */
cp_parser_objc_class_ivars (parser);
objc_continue_interface ();
@@ -17942,14 +18512,25 @@ static void
cp_parser_objc_class_implementation (cp_parser* parser)
{
tree name, super, categ;
-
+ /* APPLE LOCAL radar 4965989 */
+ bool is_categ;
cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
name = cp_parser_identifier (parser);
- cp_parser_objc_superclass_or_category (parser, &super, &categ);
+ /* APPLE LOCAL radar 4965989 */
+ cp_parser_objc_superclass_or_category (parser, &super, &categ, &is_categ);
/* We have either a class or a category on our hands. */
- if (categ)
- objc_start_category_implementation (name, categ);
+ /* APPLE LOCAL begin radar 4965989 */
+ if (is_categ)
+ {
+ if (categ == NULL_TREE)
+ {
+ error ("cannot implement anonymous category");
+ return;
+ }
+ objc_start_category_implementation (name, categ);
+ }
+ /* APPLE LOCAL end radar 4965989 */
else
{
objc_start_class_implementation (name, super);
@@ -17987,10 +18568,24 @@ cp_parser_objc_declaration (cp_parser* parser)
cp_parser_objc_class_declaration (parser);
break;
case RID_AT_PROTOCOL:
- cp_parser_objc_protocol_declaration (parser);
+ /* APPLE LOCAL radar 4947311 */
+ cp_parser_objc_protocol_declaration (parser, NULL_TREE);
break;
+ /* APPLE LOCAL begin radar 4548636 - radar 4947311 */
+ case RID_ATTRIBUTE:
+ {
+ tree attributes = NULL_TREE;
+ cp_parser_objc_maybe_attributes (parser, &attributes);
+ if (cp_lexer_peek_token (parser->lexer)->keyword == RID_AT_INTERFACE)
+ cp_parser_objc_class_interface (parser, attributes);
+ else if (cp_lexer_peek_token (parser->lexer)->keyword == RID_AT_PROTOCOL)
+ cp_parser_objc_protocol_declaration (parser, attributes);
+ break;
+ }
+ /* APPLE LOCAL end radar 4548636 - radar 4947311 */
case RID_AT_INTERFACE:
- cp_parser_objc_class_interface (parser);
+ /* APPLE LOCAL radar 4947311 */
+ cp_parser_objc_class_interface (parser, NULL_TREE);
break;
case RID_AT_IMPLEMENTATION:
cp_parser_objc_class_implementation (parser);
@@ -18031,7 +18626,8 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
/* 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);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, NULL, false, false);
objc_begin_try_stmt (location, pop_stmt_list (stmt));
while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
@@ -18041,14 +18637,10 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
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);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, NULL, false, false);
objc_finish_catch_clause ();
}
@@ -18059,7 +18651,8 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
/* 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);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, NULL, false, false);
objc_build_finally_clause (location, pop_stmt_list (stmt));
}
@@ -18088,7 +18681,8 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
/* 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);
+ /* APPLE LOCAL radar 5982990 */
+ cp_parser_compound_statement (parser, NULL, false, flag_objc_sjlj_exceptions);
return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
}
@@ -18136,7 +18730,1735 @@ cp_parser_objc_statement (cp_parser * parser) {
return error_mark_node;
}
-
+
+/* APPLE LOCAL begin C* language */
+/* Routine closes up the C*'s foreach statement.
+*/
+
+static void
+objc_finish_foreach_stmt (tree for_stmt)
+{
+ if (flag_new_for_scope > 0)
+ {
+ tree scope = TREE_CHAIN (for_stmt);
+ TREE_CHAIN (for_stmt) = NULL;
+ add_stmt (do_poplevel (scope));
+ }
+
+ finish_stmt ();
+}
+
+/*
+ Synthesizer routine for C*'s feareach statement.
+
+ It synthesizes:
+ for ( type elem in collection) { stmts; }
+
+ Into:
+ {
+ type elem;
+ __objcFastEnumerationState enumState = { 0 };
+ id items[16];
+
+ unsigned long limit = [collection countByEnumeratingWithState:&enumState objects:items count:16];
+ if (limit) {
+ unsigned long startMutations = *enumState.mutationsPtr;
+ do {
+ unsigned long counter = 0;
+ do {
+ if (startMutations != *enumState.mutationsPtr) objc_enumerationMutation(collection);
+ elem = enumState.itemsPtr[counter++];
+ stmts;
+ } while (counter < limit);
+ } while (limit = [collection countByEnumeratingWithState:&enumState objects:items count:16]);
+ }
+ else
+ elem = nil; radar 4854605, 5128402
+
+*/
+
+static void
+objc_foreach_stmt (cp_parser* parser, tree statement)
+{
+ unsigned char in_statement;
+ tree enumerationMutation_call_exp;
+ tree countByEnumeratingWithState;
+ tree receiver;
+ tree exp, bind;
+ tree enumState_decl, items_decl;
+ tree limit_decl, limit_decl_assign_expr;
+ tree outer_if_stmt, inner_if_stmt, if_condition, startMutations_decl;
+ tree outer_do_stmt, inner_do_stmt, do_condition;
+ tree counter_decl;
+ tree_stmt_iterator i = tsi_start (TREE_CHAIN (statement));
+ tree t = tsi_stmt (i);
+ /* APPLE LOCAL radar 5130983 */
+ tree elem_decl = TREE_CODE (t) == DECL_EXPR ? DECL_EXPR_DECL (t) : t;
+
+ receiver = cp_parser_condition (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ /* APPLE LOCAL begin radar 4507230 */
+ if (!objc_type_valid_for_messaging (TREE_TYPE (elem_decl)))
+ {
+ error ("selector element does not have a valid object type");
+ return;
+ }
+
+ if (!objc_type_valid_for_messaging (TREE_TYPE (receiver)))
+ {
+ error ("expression does not have a valid object type");
+ return;
+ }
+ /* APPLE LOCAL end radar 4507230 */
+
+ enumerationMutation_call_exp = objc_build_foreach_components (receiver, &enumState_decl,
+ &items_decl, &limit_decl,
+ &startMutations_decl, &counter_decl,
+ &countByEnumeratingWithState);
+
+ /* __objcFastEnumerationState enumState = { 0 }; */
+ exp = build_stmt (DECL_EXPR, enumState_decl);
+ bind = build3 (BIND_EXPR, void_type_node, enumState_decl, exp, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+
+ /* id items[16]; */
+ bind = build3 (BIND_EXPR, void_type_node, items_decl, NULL, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+
+ /* Generate this statement and add it to the list. */
+ /* limit = [collection countByEnumeratingWithState:&enumState objects:items count:16] */
+ limit_decl_assign_expr = build2 (MODIFY_EXPR, TREE_TYPE (limit_decl), limit_decl,
+ countByEnumeratingWithState);
+ bind = build3 (BIND_EXPR, void_type_node, limit_decl, NULL, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+
+ /* if (limit) { */
+ outer_if_stmt = begin_if_stmt ();
+ /* APPLE LOCAL radar 4547045 */
+ if_condition = build_binary_op (NE_EXPR, limit_decl_assign_expr,
+ fold_convert (TREE_TYPE (limit_decl), integer_zero_node),
+ 1);
+
+ finish_if_stmt_cond (if_condition, outer_if_stmt);
+
+ /* unsigned long startMutations = *enumState.mutationsPtr; */
+ exp = objc_build_component_ref (enumState_decl, get_identifier("mutationsPtr"));
+ exp = build_indirect_ref (exp, "unary *");
+ exp = build2 (MODIFY_EXPR, void_type_node, startMutations_decl, exp);
+ bind = build3 (BIND_EXPR, void_type_node, startMutations_decl, exp, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+
+ /* do { */
+/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
+ outer_do_stmt = begin_do_stmt (NULL_TREE);
+
+/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
+ /* Body of the outer do-while loop */
+ /* unsigned int counter = 0; */
+ exp = build2 (MODIFY_EXPR, void_type_node, counter_decl,
+ fold_convert (TREE_TYPE (counter_decl), integer_zero_node));
+ bind = build3 (BIND_EXPR, void_type_node, counter_decl, exp, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+
+ /* do { */
+/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
+ inner_do_stmt = begin_do_stmt (NULL_TREE);
+
+/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
+ /* Body of the inner do-while loop */
+
+ /* if (startMutations != *enumState.mutationsPtr) objc_enumerationMutation (collection); */
+ inner_if_stmt = begin_if_stmt ();
+ exp = objc_build_component_ref (enumState_decl, get_identifier("mutationsPtr"));
+ exp = build_indirect_ref (exp, "unary *");
+ if_condition = build_binary_op (NE_EXPR, startMutations_decl, exp, 1);
+ finish_if_stmt_cond (if_condition, inner_if_stmt);
+
+ add_stmt (enumerationMutation_call_exp);
+ finish_then_clause (inner_if_stmt);
+ finish_if_stmt (inner_if_stmt);
+
+ /* elem = enumState.itemsPtr [counter]; */
+ exp = objc_build_component_ref (enumState_decl, get_identifier("itemsPtr"));
+ exp = build_array_ref (exp, counter_decl);
+ add_stmt (build2 (MODIFY_EXPR, void_type_node, elem_decl, exp));
+ /* APPLE LOCAL radar 4538105 */
+ TREE_USED (elem_decl) = 1;
+
+ /* counter++; */
+ exp = build2 (PLUS_EXPR, TREE_TYPE (counter_decl), counter_decl,
+ build_int_cst (NULL_TREE, 1));
+ add_stmt (build2 (MODIFY_EXPR, void_type_node, counter_decl, exp));
+
+ /* ADD << stmts >> from the foreach loop. */
+ /* Parse the body of the for-statement. */
+ in_statement = parser->in_statement;
+ parser->in_statement = IN_ITERATION_STMT;
+ cp_parser_already_scoped_statement (parser);
+ parser->in_statement = in_statement;
+
+ finish_do_body (inner_do_stmt);
+
+ /* } while (counter < limit ); */
+ do_condition = build_binary_op (LT_EXPR, counter_decl, limit_decl, 1);
+ finish_do_stmt (do_condition, inner_do_stmt);
+ DO_FOREACH (inner_do_stmt) = integer_zero_node;
+ /* APPLE LOCAL radar 4667060 */
+ DO_FOREACH (outer_do_stmt) = elem_decl;
+
+ finish_do_body (outer_do_stmt);
+
+ /* } while (limit = [collection countByEnumeratingWithState:&enumState objects:items count:16]); */
+
+ exp = unshare_expr (limit_decl_assign_expr);
+ do_condition = build_binary_op (NE_EXPR, exp,
+ fold_convert (TREE_TYPE (limit_decl), integer_zero_node),
+ 1);
+ finish_do_stmt (do_condition, outer_do_stmt);
+
+
+ finish_then_clause (outer_if_stmt);
+
+ /* } */
+ /* APPLE LOCAL begin radar 4854605 - radar 5128402 */
+ begin_else_clause (outer_if_stmt);
+ add_stmt (build2 (MODIFY_EXPR, void_type_node, elem_decl,
+ fold_convert (TREE_TYPE (elem_decl), integer_zero_node)));
+ finish_else_clause (outer_if_stmt);
+ /* APPLE LOCAL end radar 4854605 - radar 5128402 */
+
+ finish_if_stmt (outer_if_stmt);
+
+ objc_finish_foreach_stmt (statement);
+}
+/* APPLE LOCAL end C* language */
+/* APPLE LOCAL begin blocks 6040305 (ce) */
+#define I_SYMBOL_BINDING(t) IDENTIFIER_BINDING(t)
+
+tree build_component_ref (tree e, tree member);
+tree
+build_component_ref (tree e, tree member)
+{
+ if (!DECL_P (member))
+ member = lookup_member (TREE_TYPE (e), member, 0, 0);
+ if (processing_template_decl)
+ return build3 (COMPONENT_REF, TREE_TYPE (member), e, DECL_NAME (member), NULL_TREE);
+ return build_class_member_access_expr (e, member,
+ NULL_TREE, false);
+}
+
+/* APPLE LOCAL begin radar 6214617 */
+static bool
+cp_block_requires_copying (tree exp)
+{
+ return (block_requires_copying (exp)
+ || TYPE_HAS_CONSTRUCTOR (TREE_TYPE (exp))
+ || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)));
+}
+/* APPLE LOCAL end radar 6214617 */
+
+/* APPLE LOCAL begin radar 5847213 - radar 6329245 */
+/** 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;
+ tree decl, constructor;
+ char name [32];
+ VEC(constructor_elt,gc) *impl_v = NULL;
+ 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;
+
+ /* Initialize "reserved" field to 0 for now. */
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (long_unsigned_type_node, 0));
+
+ /* Initialize "Size" field. */
+ size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (block_struct_type));
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (long_unsigned_type_node, size));
+
+ 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;
+ helper_addr = build_fold_addr_expr (block_impl->copy_helper_func_decl);
+ helper_addr = convert (ptr_type_node, helper_addr);
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, helper_addr);
+
+ DECL_CONTEXT (block_impl->destroy_helper_func_decl) = NULL_TREE;
+ helper_addr = build_fold_addr_expr (block_impl->destroy_helper_func_decl);
+ helper_addr = convert (ptr_type_node, helper_addr);
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, helper_addr);
+ }
+ /* Create a CONSTRUCTOR to represent the braced-initializer. */
+ constructor = make_node (CONSTRUCTOR);
+ CONSTRUCTOR_ELTS (constructor) = impl_v;
+ TREE_PUBLIC (decl) = 0;
+ TREE_STATIC (decl) = 1;
+ cp_finish_decl (decl, constructor, 0, 0, LOOKUP_ONLYCONVERTING);
+ return decl;
+}
+
+/* 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;
+ 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 fields = NULL_TREE;
+ tree field;
+ tree block_struct_type;
+
+ push_to_top_level ();
+ block_struct_type = xref_tag (record_type,
+ get_identifier ("__block_literal_generic"),
+ ts_current, false);
+ xref_basetypes (block_struct_type, NULL_TREE);
+ CLASSTYPE_DECLARED_CLASS (block_struct_type) = 0;
+ pushclass (block_struct_type);
+
+ field = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ field = build_decl (FIELD_DECL, get_identifier ("__flags"),
+ integer_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ field = build_decl (FIELD_DECL, get_identifier ("__reserved"),
+ integer_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ field = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"),
+ ptr_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ field = build_decl (FIELD_DECL, get_identifier ("__descriptor"),
+ build_block_descriptor_type (false));
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ TYPE_FIELDS (block_struct_type) = fields;
+ TYPE_NAME (block_struct_type) = build_decl (TYPE_DECL,
+ get_identifier ("__block_literal_generic"),
+ block_struct_type);
+ TYPE_STUB_DECL (block_struct_type) = TYPE_NAME (block_struct_type);
+ TYPE_BLOCK_IMPL_STRUCT (block_struct_type) = 1;
+ finish_struct (block_struct_type, NULL_TREE);
+ pop_from_top_level ();
+
+ return block_struct_type;
+}
+/* APPLE LOCAL end radar 6300081 */
+
+/** 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 fields = NULL_TREE, field, 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))
+ /* APPLE LOCAL begin radar 6214617 */
+ if (cp_block_requires_copying (TREE_VALUE (chain)))
+ {
+ tree type = TREE_TYPE (TREE_VALUE (chain));
+ block_impl->BlockHasCopyDispose = TRUE;
+ if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
+ {
+ block_impl->BlockImportsCxxObjects = TRUE;
+ break;
+ }
+ /* APPLE LOCAL end radar 6214617 */
+ }
+
+ /* 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 ();
+ /* APPLE LOCAL begin radar 6243400 */
+ block_struct_type = xref_tag (record_type, get_identifier (buffer), ts_current, false);
+ xref_basetypes (block_struct_type, NULL_TREE);
+ CLASSTYPE_DECLARED_CLASS (block_struct_type) = 0;
+ pushclass (block_struct_type);
+ /* APPLE LOCAL end radar 6243400 */
+ /* void * __isa; */
+ field = build_decl (FIELD_DECL, get_identifier ("__isa"), ptr_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ /* int __flags. */
+ field = build_decl (FIELD_DECL, get_identifier ("__flags"), integer_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ /* int __reserved. */
+ field = build_decl (FIELD_DECL, get_identifier ("__reserved"), integer_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ /* void *__FuncPtr. */
+ field = build_decl (FIELD_DECL, get_identifier ("__FuncPtr"),
+ ptr_type_node);
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ /* struct __block_descriptor *__descriptor */
+ field = build_decl (FIELD_DECL, get_identifier ("__descriptor"),
+ build_block_descriptor_type (block_impl->BlockHasCopyDispose));
+ TREE_CHAIN (field) = fields;
+ fields = field;
+
+ 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 = build_decl (FIELD_DECL, DECL_NAME (p),
+ c_build_qualified_type (TREE_TYPE (p),
+ TYPE_UNQUALIFIED));
+ TREE_CHAIN (field) = fields;
+ fields = field;
+ }
+
+ /* int *y; // byref variable list */
+ for (chain = block_impl->block_byref_decl_list; chain; chain = TREE_CHAIN (chain))
+ {
+ tree p = TREE_VALUE (chain);
+ field = build_decl (FIELD_DECL, DECL_NAME (p),
+ TREE_TYPE (p));
+ TREE_CHAIN (field) = fields;
+ fields = field;
+ }
+
+ /* APPLE LOCAL begin radar 6243400 */
+ TYPE_FIELDS (block_struct_type) = fields;
+ TYPE_NAME (block_struct_type) =
+ build_decl (TYPE_DECL, get_identifier (buffer), block_struct_type);
+ TYPE_STUB_DECL (block_struct_type) = TYPE_NAME (block_struct_type);
+ finish_struct (block_struct_type, NULL_TREE);
+ pop_from_top_level ();
+ /* APPLE LOCAL end radar 6243400 */
+ return block_struct_type;
+}
+
+/**
+ 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
+ ...
+ }
+*/
+/* APPLE LOCAL begin radar 6169527 */
+/* This routine is entirely rewritten as we now have to deal with full-blown
+ c++ classes with fields which may require construction. */
+static VEC(constructor_elt,gc) *
+build_block_struct_initlist (tree block_struct_type,
+ struct block_sema_info *block_impl)
+{
+ tree expr, chain, helper_addr;
+ /* APPLE LOCAL radar 7735196 */
+ unsigned flags = 0;
+ static tree NSConcreteStackBlock_decl = NULL_TREE;
+ static tree NSConcreteGlobalBlock_decl = NULL_TREE;
+ VEC(constructor_elt,gc) *impl_v = NULL;
+ 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 6214617 */
+ /* Set BLOCK_HAS_CXX_OBJ if block is importing a cxx object. */
+ if (block_impl->BlockImportsCxxObjects)
+ flags |= BLOCK_HAS_CXX_OBJ;
+ /* APPLE LOCAL end radar 6214617 */
+/* 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 */
+ /* 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 */
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE,
+ 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 */
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE,
+ convert (ptr_type_node,
+ build_fold_addr_expr (NSConcreteStackBlock_decl)));
+ /* APPLE LOCAL end radar 6457359 */
+ }
+
+ /* __flags */
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (integer_type_node, flags));
+ /* __reserved */
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, build_int_cst (integer_type_node, 0));
+ /* __FuncPtr */
+ helper_addr = build_fold_addr_expr (block_impl->helper_func_decl);
+ helper_addr = convert (ptr_type_node, helper_addr);
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, helper_addr);
+
+ /* &static_descriptor_variable initializer */
+ expr = build_fold_addr_expr (descriptor_block_decl);
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, expr);
+
+ for (chain = block_impl->block_original_ref_decl_list; chain;
+ chain = TREE_CHAIN (chain))
+ {
+ tree y = TREE_VALUE (chain);
+ TREE_USED (y) = 1;
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, y);
+ }
+ 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);
+
+ CONSTRUCTOR_APPEND_ELT(impl_v, NULL_TREE, forwarding_expr);
+ }
+ return impl_v;
+}
+/* APPLE LOCAL end radar 6169527 */
+/* APPLE LOCAL end radar 5847213 - radar 6329245 */
+
+/**
+ 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_1 *ii, int z);
+
+ 3) build the temporary initialization:
+ struct block_1 I = {
+ { &_NSConcreteStackBlock or &_NSConcreteGlobalBlock // isa,
+ BLOCK_HAS_CXX_OBJ | BLOCK_HAS_COPY_DISPOSE | BLOCK_IS_GLOBAL // flags,
+ 0, // reserved,
+ &helper_1,
+ &{
+ NULL,
+ sizeof(struct block_1),
+ copy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE
+ destroy_helper_block_1, // only if block BLOCK_HAS_COPY_DISPOSE
+ },
+ x,
+ &y
+};
+
+It return the temporary.
+*/
+/* APPLE LOCAL begin radar 6169527 */
+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;
+ 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. */
+ maybe_push_decl (block_holder_tmp_decl);
+ DECL_CONTEXT (block_holder_tmp_decl) = staticBlockTmp ? NULL_TREE
+ : current_function_decl;
+ if (staticBlockTmp)
+ DECL_CONTEXT (block_impl->helper_func_decl) = NULL_TREE;
+ /* APPLE LOCAL end radar 6230297 */
+ DECL_ARTIFICIAL (block_holder_tmp_decl) = 1;
+
+ /* Create a CONSTRUCTOR to represent the braced-initializer. */
+ constructor = make_node (CONSTRUCTOR);
+
+ CONSTRUCTOR_ELTS (constructor) = build_block_struct_initlist (block_struct_type,
+ block_impl);
+ /* 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;
+ }
+ cp_finish_decl (block_holder_tmp_decl, constructor, 0, 0, LOOKUP_ONLYCONVERTING);
+ return block_holder_tmp_decl;
+}
+/* APPLE LOCAL end radar 6169527 */
+
+static tree
+clean_and_exit (tree block)
+{
+ pop_function_context ();
+ pop_lang_context ();
+ if (current_function_decl)
+ 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;
+ 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);
+ 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;
+
+ pushdecl (cur_block->copy_helper_func_decl);
+ /* 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)); */
+ DECL_ARGUMENTS (cur_block->copy_helper_func_decl) = dst_arg;
+ /* function header synthesis. */
+ push_function_context ();
+ /* start_block_helper_function (cur_block->copy_helper_func_decl, true); */
+ /* store_parm_decls (arg_info); */
+ start_preparsed_function (cur_block->copy_helper_func_decl,
+ /*attrs*/NULL_TREE,
+ SF_PRE_PARSED);
+
+ /* Body of the function. */
+ stmt = begin_compound_stmt (BCS_FN_BODY);
+ for (chain = block_impl->block_ref_decl_list; chain;
+ chain = TREE_CHAIN (chain))
+ /* APPLE LOCAL radar 6214617 */
+ if (cp_block_requires_copying (TREE_VALUE (chain)))
+ {
+ /* APPLE LOCAL begin radar 6175959 */
+ int flag = 0;
+ 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;
+ /* APPLE LOCAL begin radar 6214617 */
+ else if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (p))
+ || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (p)))
+ {
+ tree call_exp = build_aggr_init (dst_block_component, src_block_component,
+ LOOKUP_ONLYCONVERTING);
+ add_stmt (call_exp);
+ }
+ /* APPLE LOCAL end radar 6214617 */
+ else
+ /* _Block_object_assign(&_dest->myImportedBlock, _src->myImportedClosure, BLOCK_FIELD_IS_OBJECT) */
+ flag = BLOCK_FIELD_IS_OBJECT;
+ if (flag)
+ {
+ tree call_exp;
+ 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 used in |...| 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);
+ }
+
+ finish_compound_stmt (stmt);
+ /* APPLE LOCAL radar 6169580 */
+ finish_function (4);
+ /* Hum, would be nice if someone else did this for us. */
+ if (global_bindings_p ())
+ cgraph_finalize_function (block_impl->copy_helper_func_decl, false);
+ pop_function_context ();
+ /* free (arg_info); */
+}
+
+static void
+synth_destroy_helper_block_func (struct block_sema_info * block_impl)
+{
+ tree stmt, chain;
+ 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);
+ DECL_CONTEXT (src_arg) = cur_block->destroy_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)); */
+
+ pushdecl (cur_block->destroy_helper_func_decl);
+ /* arg_info->parms = src_arg; */
+ /* arg_info->types = tree_cons (NULL_TREE, block_impl->block_arg_ptr_type,
+ NULL_TREE); */
+ DECL_ARGUMENTS (cur_block->destroy_helper_func_decl) = src_arg;
+
+ /* function header synthesis. */
+ push_function_context ();
+ /* start_block_helper_function (cur_block->destroy_helper_func_decl, true); */
+ /* store_parm_decls_from (arg_info); */
+ start_preparsed_function (cur_block->destroy_helper_func_decl,
+ /*attrs*/NULL_TREE,
+ SF_PRE_PARSED);
+
+ /* Body of the function. */
+ stmt = begin_compound_stmt (BCS_FN_BODY);
+ for (chain = block_impl->block_ref_decl_list; chain;
+ chain = TREE_CHAIN (chain))
+ /* APPLE LOCAL begin radar 6214617 */
+ if (block_requires_copying (TREE_VALUE (chain))
+ || (TREE_CODE (TREE_TYPE (TREE_VALUE (chain))) == RECORD_TYPE
+ && CLASSTYPE_DESTRUCTORS (TREE_TYPE (TREE_VALUE (chain)))))
+ /* APPLE LOCAL end radar 6214617 */
+ {
+ int flag = 0;
+ 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;
+ /* APPLE LOCAL begin radar 6214617 */
+ else if (TREE_CODE (TREE_TYPE (p)) == RECORD_TYPE
+ && CLASSTYPE_DESTRUCTORS (TREE_TYPE (p)))
+ {
+ tree call_exp = cxx_maybe_build_cleanup (src_block_component);
+ gcc_assert (call_exp);
+ add_stmt (call_exp);
+ }
+ /* APPLE LOCAL end radar 6214617 */
+ else
+ /* _Block_object_dispose(_src->imported_object_0, BLOCK_FIELD_IS_OBJECT); */
+ flag = BLOCK_FIELD_IS_OBJECT;
+ if (flag)
+ {
+ rel_exp = build_block_object_dispose_call_exp (src_block_component, flag);
+ add_stmt (rel_exp);
+ }
+ }
+
+ /* For each __block declared variable used in |...| 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);
+ }
+
+ finish_compound_stmt (stmt);
+ /* APPLE LOCAL radar 6169580 */
+ finish_function (4);
+ /* Hum, would be nice if someone else did this for us. */
+ if (global_bindings_p ())
+ cgraph_finalize_function (block_impl->destroy_helper_func_decl, false);
+ pop_function_context ();
+}
+
+/* Parse a block-id.
+
+ GNU Extension:
+
+ block-id:
+ type-specifier-seq block-declarator
+
+ Returns the DECL specified or implied. */
+
+static tree
+cp_parser_block_id (cp_parser* parser)
+{
+ cp_decl_specifier_seq type_specifier_seq;
+ cp_declarator *declarator;
+
+ /* Parse the type-specifier-seq. */
+ cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ &type_specifier_seq);
+ if (type_specifier_seq.type == error_mark_node)
+ return error_mark_node;
+
+ /* Look for the block-declarator. */
+ declarator
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_BLOCK, NULL,
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
+
+ return grokblockdecl (&type_specifier_seq, 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
+cp_parser_block_literal_expr (cp_parser* parser)
+{
+ char name [32];
+ static int global_unique_count;
+ int unique_count = ++global_unique_count;
+ tree block_helper_function_decl;
+ tree expr, type, arglist = NULL_TREE, ftype;
+ tree self_arg, stmt;
+ /* struct c_arg_info *args = NULL; */
+ cp_parameter_declarator *args = NULL;
+ tree arg_type = void_list_node;
+ struct block_sema_info *block_impl;
+ tree tmp;
+ tree restype;
+ tree 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;
+ /* APPLE LOCAL radar 6169580 */
+ int context_is_nonstatic_method;
+ tree raises = NULL_TREE;
+
+ cp_lexer_consume_token (parser->lexer); /* eat '^' */
+
+ /* APPLE LOCAL begin radar 6237713 */
+ if (cp_lexer_peek_token (parser->lexer)->keyword == RID_ATTRIBUTE)
+ attributes = cp_parser_attributes_opt (parser);
+ /* APPLE LOCAL end radar 6237713 */
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ /* Parse the optional argument list */
+ cp_lexer_consume_token (parser->lexer);
+ /* Open the scope to collect parameter decls */
+ /* push_scope (); */
+ /* args = c_parser_parms_declarator (parser, true, NULL_TREE); */
+ /* Parse the parameter-declaration-clause. */
+ args = cp_parser_parameter_declaration_clause (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ arg_type = grokparms (args, &arglist);
+ /* Check for args as it might be NULL due to error. */
+ if (! args)
+ {
+ return error_mark_node;
+ }
+ raises = cp_parser_exception_specification_opt (parser);
+ }
+ /* APPLE LOCAL begin radar 6185344 */
+ else if (cp_lexer_next_token_is_not (parser->lexer, 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 = cp_parser_block_id (parser);
+
+ if (decl && decl != error_mark_node)
+ {
+ arg_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ arglist = DECL_ARGUMENTS (decl);
+ raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl));
+ declared_block_return_type = TREE_TYPE (TREE_TYPE (decl));
+ }
+ }
+ /* APPLE LOCAL end radar 6185344 */
+
+ block = begin_block ();
+ /* APPLE LOCAL begin radar 6169580 */
+ context_is_nonstatic_method = (current_function_decl
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (current_function_decl));
+ /* APPLE LOCAL end radar 6169580 */
+
+ /* cur_block->arg_info = NULL; */
+ /* APPLE LOCAL begin radar 6185344 */
+ 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;
+ /* APPLE LOCAL end radar 6185344 */
+
+ /* 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_artificial_parm (get_identifier (".block_descriptor"), ptr_type_node);
+
+ /* TREE_CHAIN (self_arg) = cur_block->arg_info->parms; */
+ TREE_CHAIN (self_arg) = arglist;
+ arg_type = tree_cons (NULL_TREE, ptr_type_node, arg_type);
+ arglist = 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. */
+
+ push_lang_context (lang_name_c);
+
+ ftype = build_function_type ((!cur_block->block_has_return_type
+ ? void_type_node : cur_block->return_type),
+ arg_type);
+ /* APPLE LOCAL end radar 6185344 */
+ if (raises)
+ ftype = build_exception_variant (ftype, raises);
+ /* APPLE LOCAL radar 6160536 */
+ block_helper_function_decl = build_helper_func_decl (build_block_helper_name (unique_count),
+ ftype);
+ DECL_CONTEXT (block_helper_function_decl) = current_function_decl;
+ cur_block->helper_func_decl = block_helper_function_decl;
+
+ DECL_ARGUMENTS (block_helper_function_decl) = arglist;
+
+ push_function_context ();
+ /* start_block_helper_function (cur_block->helper_func_decl, false); */
+ /* Enter parameter list to the scope of the helper function. */
+ /* store_parm_decls_from (cur_block->arg_info); */
+ start_preparsed_function (cur_block->helper_func_decl,
+ /*attrs*/NULL_TREE,
+ SF_PRE_PARSED);
+ /* APPLE LOCAL begin radar 6237713 */
+ if (cp_lexer_peek_token (parser->lexer)->keyword == RID_ATTRIBUTE)
+ attributes = cp_parser_attributes_opt (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. */
+ {
+ unsigned save = parser->in_statement;
+ /* Indicate no valid break/continue context. We'll notice and
+ emit the proper error message in c_finish_bc_stmt. */
+ parser->in_statement = 0;
+ stmt = begin_compound_stmt (BCS_FN_BODY);
+ /* Set block's scope to the scope of the helper function's main body.
+ This is primarily used when nested blocks are declared. */
+ cur_block->cp_the_scope = current_binding_level;
+ /* APPLE LOCAL begin radar 6169580 */
+ if (context_is_nonstatic_method)
+ {
+ tree this_decl = lookup_name (this_identifier);
+ gcc_assert (this_decl);
+ build_block_ref_decl (this_identifier, this_decl);
+ }
+ /* APPLE LOCAL end radar 6169580 */
+ cp_parser_compound_statement (parser, NULL, false, false);
+ parser->in_statement = save;
+ }
+
+ 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);
+
+ finish_compound_stmt (stmt);
+ /* 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, TREE_CHAIN (arg_type));
+ if (raises)
+ ftype = build_exception_variant (ftype, raises);
+ /* 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);
+ if (raises)
+ helper_function_type = build_exception_variant (helper_function_type, raises);
+ TREE_TYPE (cur_block->helper_func_decl) = helper_function_type;
+ finish_function (4);
+ pop_function_context ();
+ /* Hum, would be nice if someone else did this for us. */
+ if (global_bindings_p ())
+ cgraph_finalize_function (cur_block->helper_func_decl, false);
+ pop_lang_context ();
+
+ /* Build the declaration for copy_helper_block and destroy_helper_block
+ helper functions for later use. */
+
+ if (cur_block->BlockHasCopyDispose)
+ {
+ tree s_ftype;
+
+ push_lang_context (lang_name_c);
+ /* void copy_helper_block (struct block*, struct block *); */
+ 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);
+ DECL_CONTEXT (cur_block->copy_helper_func_decl) = current_function_decl;
+ 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);
+ DECL_CONTEXT (cur_block->destroy_helper_func_decl) = current_function_decl;
+ synth_destroy_helper_block_func (cur_block);
+ pop_lang_context ();
+ }
+
+ 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 blocks 6040305 (ce) */
+
+/* APPLE LOCAL begin blocks 6040305 (ch) */
+/* build_byref_local_var_access - converts EXPR to:
+ EXPR.__forwarding-><decl-name>.
+ */
+tree
+build_byref_local_var_access (tree expr, tree decl_name)
+{
+ tree exp = build_component_ref (expr, get_identifier ("__forwarding"));
+ exp = build_indirect_ref (exp, "unary *");
+ exp = build_component_ref (exp, decl_name);
+ return exp;
+}
+
+#define BINDING_VALUE(b) ((b)->value)
+
+/**
+ build_block_byref_decl - This routine inserts a variable declared as a
+ 'byref' variable using the |...| syntax in helper function's outer-most scope.
+ */
+tree
+build_block_byref_decl (tree name, tree decl, tree exp)
+{
+ tree ptr_type, byref_decl;
+ /* APPLE LOCAL begin radar 6225809 */
+ if (cur_block->prev_block_info) {
+ /* Traverse enclosing blocks. Insert a __block variable in
+ each enclosing block which has no declaration of this
+ variable. This is to ensure that the current (inner) block
+ gets the __block version of the variable; */
+ struct block_sema_info *cb = cur_block->prev_block_info;
+ while (cb) {
+ struct cxx_binding *b = I_SYMBOL_BINDING (name);
+ gcc_assert (b);
+ gcc_assert (BINDING_VALUE (b));
+ gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL);
+ /* Find the first declaration not in current block. */
+ while (b && BINDING_VALUE (b)
+ && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL)
+ && DECL_CONTEXT (BINDING_VALUE (b)) == cur_block->helper_func_decl)
+ {
+ /* FIXME: This can't happen?! */
+ abort ();
+ /* b = b->previous; */
+ }
+
+ gcc_assert (b);
+ gcc_assert (BINDING_VALUE (b));
+ gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL);
+
+ /* Is the next declaration not in the enclosing block? */
+ if (b && BINDING_VALUE (b)
+ && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL)
+ && DECL_CONTEXT (BINDING_VALUE (b)) != cb->helper_func_decl)
+ {
+ /* No declaration of variable seen in the block. Must insert one. */
+ /* FIXME: does this push enough? scope? */
+ struct cp_binding_level *save_scope = current_binding_level;
+ struct block_sema_info *save_current_block = cur_block;
+ tree save_current_function_decl = current_function_decl;
+ current_binding_level = cb->cp_the_scope;
+ cur_block = cb;
+ current_function_decl = cb->helper_func_decl;
+ decl = build_block_byref_decl (name, decl, exp);
+ cur_block = save_current_block;
+ current_binding_level = save_scope;
+ current_function_decl = save_current_function_decl;
+ }
+ cb = cb->prev_block_info;
+ }
+ }
+ /* APPLE LOCAL end radar 6225809 */
+
+ /* If it is already a byref declaration, do not add the pointer type
+ because such declarations already have the pointer type
+ added. This happens when we have two nested byref declarations in
+ nested blocks. */
+ ptr_type = (TREE_CODE (decl) == VAR_DECL && BLOCK_DECL_BYREF (decl))
+ ? TREE_TYPE (decl) : build_pointer_type (TREE_TYPE (decl));
+ byref_decl = build_decl (VAR_DECL, name, ptr_type);
+ DECL_CONTEXT (byref_decl) = current_function_decl;
+ BLOCK_DECL_BYREF (byref_decl) = 1;
+
+ if (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl))
+ {
+ COPYABLE_BYREF_LOCAL_VAR (byref_decl) = 1;
+ COPYABLE_BYREF_LOCAL_NONPOD (byref_decl) = COPYABLE_BYREF_LOCAL_NONPOD (decl);
+ /* APPLE LOCAL radar 5847976 */
+ COPYABLE_WEAK_BLOCK (byref_decl) = COPYABLE_WEAK_BLOCK (decl);
+ }
+
+ /* Current scope must be that of the main function body. */
+ /* FIXME gcc_assert (current_scope->function_body);*/
+ pushdecl (byref_decl);
+ mark_used (byref_decl);
+ /* APPLE LOCAL begin radar 6083129 - byref escapes (cp) */
+ /* FIXME: finish this off, ensure the decl is scoped appropriately
+ for when we want the cleanup to run. */
+ /* APPLE LOCAL end radar 6083129 - byref escapes (cp) */
+ cur_block->block_byref_decl_list =
+ tree_cons (NULL_TREE, byref_decl, cur_block->block_byref_decl_list);
+ /* APPLE LOCAL radar 5847213 */
+ /* build of block_original_byref_decl_list us removed. */
+ /* APPLE LOCAL begin radar 6144664 */
+ DECL_SOURCE_LOCATION (byref_decl)
+ = DECL_SOURCE_LOCATION (cur_block->helper_func_decl);
+ /* APPLE LOCAL end radar 6144664 */
+ return byref_decl;
+}
+
+/**
+ build_block_ref_decl - This routine inserts a copied-in variable (a variable
+ referenced in the block but whose scope is outside the block) in helper
+ function's outer-most scope. It also sets its type to 'const' as such
+ variables are read-only.
+ */
+tree
+build_block_ref_decl (tree name, tree decl)
+{
+ /* FIXME - Broken, should be found via objc runtime testcases. */
+ /* FIXME - Don't use DECL_CONTEXT on any helpers */
+ tree ref_decl;
+ /* APPLE LOCAL radar 6212722 */
+ tree type, exp;
+ /* 'decl' was previously declared as __block. Simply, copy the value
+ embedded in the above variable. */
+ if (TREE_CODE (decl) == VAR_DECL && COPYABLE_BYREF_LOCAL_VAR (decl))
+ decl = build_byref_local_var_access (decl, DECL_NAME (decl));
+ else {
+ if (cur_block->prev_block_info) {
+ /* Traverse enclosing blocks. Insert a copied-in variable in
+ each enclosing block which has no declaration of this
+ variable. This is to ensure that the current (inner) block
+ has the 'frozen' value of the copied-in variable; which means
+ the value of the copied in variable is at the point of the
+ block declaration and *not* when the inner block is
+ invoked. */
+ struct block_sema_info *cb = cur_block->prev_block_info;
+ while (cb) {
+ struct cxx_binding *b = I_SYMBOL_BINDING (name);
+ gcc_assert (b);
+ gcc_assert (BINDING_VALUE (b));
+ gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL);
+ /* Find the first declaration not in current block. */
+ while (b && BINDING_VALUE (b)
+ && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL)
+ && DECL_CONTEXT (BINDING_VALUE (b)) == cur_block->helper_func_decl)
+ {
+ /* FIXME: This can't happen?! */
+ abort ();
+ /* b = b->previous; */
+ }
+
+ gcc_assert (b);
+ gcc_assert (BINDING_VALUE (b));
+ gcc_assert (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL);
+
+ /* Is the next declaration not in the enclosing block? */
+ if (b && BINDING_VALUE (b)
+ && (TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ || TREE_CODE (BINDING_VALUE (b)) == PARM_DECL)
+ && DECL_CONTEXT (BINDING_VALUE (b)) != cb->helper_func_decl)
+ {
+ /* No declaration of variable seen in the block. Must
+ insert one, so it 'freezes' the variable in this
+ block. */
+ /* FIXME: does this push enough? scope? */
+ struct cp_binding_level *save_scope = current_binding_level;
+ struct block_sema_info *save_current_block = cur_block;
+ tree save_current_function_decl = current_function_decl;
+ current_binding_level = cb->cp_the_scope;
+ cur_block = cb;
+ current_function_decl = cb->helper_func_decl;
+ decl = build_block_ref_decl (name, decl);
+ cur_block = save_current_block;
+ current_binding_level = save_scope;
+ current_function_decl = save_current_function_decl;
+ }
+ cb = cb->prev_block_info;
+ }
+ }
+ }
+ /* APPLE LOCAL begin radar 6212722 */
+ exp = decl;
+ type = TREE_TYPE (exp);
+ if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == FUNCTION_TYPE) {
+ exp = decay_conversion (exp);
+ type = TREE_TYPE (exp);
+ }
+ ref_decl = build_decl (VAR_DECL, name,
+ build_qualified_type (type, TYPE_QUAL_CONST));
+ /* APPLE LOCAL end radar 6212722 */
+ /* APPLE LOCAL begin radar 6144664 */
+ DECL_SOURCE_LOCATION (ref_decl) = DECL_SOURCE_LOCATION
+ (cur_block->helper_func_decl);
+ /* APPLE LOCAL end radar 6144664 */
+ DECL_CONTEXT (ref_decl) = current_function_decl;
+ DECL_INITIAL (ref_decl) = error_mark_node;
+ c_apply_type_quals_to_decl (TYPE_QUAL_CONST, ref_decl);
+ BLOCK_DECL_COPIED (ref_decl) = 1;
+
+ /* Find the scope for function body (outer-most scope) and insert
+ this variable in that scope. This is to avoid duplicate
+ declaration of the save variable. */
+ {
+ struct cp_binding_level *b = current_binding_level;
+ while (b->level_chain->kind != sk_function_parms)
+ b = b->level_chain;
+ pushdecl_with_scope (ref_decl, b, /*is_friend=*/false);
+ /* APPLE LOCAL radar 6169527 */
+ add_decl_expr (ref_decl);
+ }
+ cur_block->block_ref_decl_list =
+ tree_cons (NULL_TREE, ref_decl, cur_block->block_ref_decl_list);
+ cur_block->block_original_ref_decl_list =
+ /* APPLE LOCAL radar 6212722 */
+ tree_cons (NULL_TREE, exp, cur_block->block_original_ref_decl_list);
+ return ref_decl;
+}
+
+/* APPLE LOCAL begin radar 5847213 - radar 6329245 */
+static GTY (()) tree descriptor_ptr_type;
+static GTY (()) tree descriptor_ptr_type_with_copydispose;
+/** build_block_descriptor_type - This routine builds following internal type:
+ 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 is set (withCopyDispose true)
+ void *DestroyFuncPtr; // When BLOCK_HAS_COPY_DISPOSE is set (withCopyDispose true)
+ } *descriptor_ptr_type;
+
+ Objects of this type will always be static. This is one main component of abi change.
+ */
+tree
+build_block_descriptor_type (bool withCopyDispose)
+{
+ tree field_decl_chain = NULL_TREE, field_decl;
+ tree main_type;
+
+ if (withCopyDispose && descriptor_ptr_type_with_copydispose)
+ return descriptor_ptr_type_with_copydispose;
+ if (!withCopyDispose && descriptor_ptr_type)
+ return descriptor_ptr_type;
+
+ main_type = make_aggr_type (RECORD_TYPE);
+ xref_basetypes (main_type, NULL_TREE);
+
+ /* unsigned long int reserved; */
+ field_decl = build_decl (FIELD_DECL, get_identifier ("reserved"), long_unsigned_type_node);
+ TREE_CHAIN (field_decl) = field_decl_chain;
+ field_decl_chain = field_decl;
+
+ /* unsigned long int Size; */
+ field_decl = build_decl (FIELD_DECL, get_identifier ("Size"), long_unsigned_type_node);
+ TREE_CHAIN (field_decl) = field_decl_chain;
+ field_decl_chain = field_decl;
+
+ if (withCopyDispose)
+ {
+ /* void *CopyFuncPtr; */
+ field_decl = build_decl (FIELD_DECL, get_identifier ("CopyFuncPtr"), ptr_type_node);
+ TREE_CHAIN (field_decl) = field_decl_chain;
+ field_decl_chain = field_decl;
+ /* void *DestroyFuncPtr; */
+ field_decl = build_decl (FIELD_DECL, get_identifier ("DestroyFuncPtr"), ptr_type_node);
+ TREE_CHAIN (field_decl) = field_decl_chain;
+ field_decl_chain = field_decl;
+ }
+
+ /* Mark this struct as being a block struct rather than a 'normal'
+ struct. */
+ TYPE_BLOCK_IMPL_STRUCT (main_type) = 1;
+ if (withCopyDispose)
+ finish_builtin_struct (main_type, "__block_descriptor_withcopydispose", field_decl_chain, NULL_TREE);
+ else
+ finish_builtin_struct (main_type, "__block_descriptor", field_decl_chain, NULL_TREE);
+ CLASSTYPE_AS_BASE (main_type) = main_type;
+
+ main_type = build_pointer_type (main_type);
+ if (withCopyDispose)
+ descriptor_ptr_type_with_copydispose = main_type;
+ else
+ descriptor_ptr_type = main_type;
+ return main_type;
+}
+/* APPLE LOCAL end radar 5847213 - radar 6329245 */
+
+cp_declarator *
+make_block_pointer_declarator (tree attributes,
+ cp_cv_quals quals,
+ cp_declarator *target)
+{
+ struct cp_declarator *itarget = target;
+ struct cp_declarator *ret = make_declarator (cdk_block_pointer);
+
+ /* APPLE LOCAL radar 5847213 */
+ /* code removed */
+
+
+ ret->attributes = attributes;
+ ret->declarator = itarget;
+ ret->u.block_pointer.qualifiers = quals;
+ return ret;
+}
+
+/* This routine returns 'true' if 'name' has a declaration inside the
+ current block, 'false' otherwise. If 'name' has no declaration in
+ the current block, it returns in DECL the user declaration for
+ 'name' found in the enclosing scope. Note that if it is declared
+ in current declaration, it can be either a user declaration or a
+ byref/copied-in declaration added in current block's scope by the
+ compiler. */
+bool
+lookup_name_in_block (tree name, tree *decl)
+{
+ /* FIXME - Broken, should be found via objc runtime testcases. */
+ /* FIXME - Don't use DECL_CONTEXT on any helpers */
+ cxx_binding *b = I_SYMBOL_BINDING (name);
+ if (b && b->declared_in_block
+ && DECL_CONTEXT (BINDING_VALUE (b)) == current_function_decl)
+ return true;
+
+ /* Check for variables only, as we may have parameters, such as
+ 'self' */
+ /* Note that if a copied-in variable (BLOCK_DECL_COPIED) in the
+ enclosing block is found, it must be returned as this is
+ where the variable in current (nested block) will have to get
+ its value. */
+ while (b
+ && TREE_CODE (BINDING_VALUE (b)) == VAR_DECL
+ && (BLOCK_DECL_BYREF (BINDING_VALUE (b))))
+ b = b->previous;
+ if (b)
+ *decl = BINDING_VALUE (b);
+ return false;
+}
+
+/**
+ build_helper_func_decl - This routine builds a FUNCTION_DECL for
+ a block helper function.
+ */
+tree
+build_helper_func_decl (tree ident, tree type)
+{
+ tree func_decl = build_decl (FUNCTION_DECL, ident, type);
+ DECL_EXTERNAL (func_decl) = 0;
+ TREE_PUBLIC (func_decl) = 0;
+ TREE_USED (func_decl) = 1;
+ TREE_NOTHROW (func_decl) = 0;
+ /* APPLE LOCAL radar 6172148 */
+ BLOCK_SYNTHESIZED_FUNC (func_decl) = 1;
+ retrofit_lang_decl (func_decl);
+ if (current_function_decl)
+ DECL_NO_STATIC_CHAIN (current_function_decl) = 0;
+ return func_decl;
+}
+
+/**
+ declare_block_prologue_local_vars - utility routine to do the actual
+ declaration and initialization for each referecned block variable.
+ */
+/* APPLE LOCAL begin radar 6169527 */
+/* This routine is mostly rewritten for c++ because initialization of variables
+ may involve copy construction. */
+static void
+declare_block_prologue_local_vars (tree self_parm, tree component,
+ tree stmt)
+{
+ tree decl, block_component;
+ tree_stmt_iterator i;
+ tree initialization_stmt;
+ /* APPLE LOCAL radar 6163705 */
+ int save_line = LOCATION_LINE (input_location);
+
+ decl = component;
+ block_component = build_component_ref (build_indirect_ref (self_parm, "->"),
+ DECL_NAME (component));
+ gcc_assert (block_component);
+ /* APPLE LOCAL radar 6163705 */
+ LOCATION_LINE (input_location) = DECL_SOURCE_LINE (decl) - 1;
+ DECL_EXTERNAL (decl) = 0;
+ TREE_STATIC (decl) = 0;
+ TREE_USED (decl) = 1;
+ DECL_CONTEXT (decl) = current_function_decl;
+ DECL_ARTIFICIAL (decl) = 1;
+ initialization_stmt = push_stmt_list();
+ cp_finish_decl (decl, block_component, 0, 0, LOOKUP_ONLYCONVERTING);
+ initialization_stmt = pop_stmt_list (initialization_stmt);
+ /* APPLE LOCAL radar 6163705 */
+ LOCATION_LINE (input_location) = save_line;
+ /* Prepend a initialization_stmt statement to the statement list. */
+ i = tsi_start (stmt);
+ tsi_link_before (&i, initialization_stmt, TSI_SAME_STMT);
+}
+
+/**
+ declare_block_prologue_local_byref_vars - utility routine to do the actual
+ declaration and initialization for each __block referenced block variable.
+ */
+static void
+declare_block_prologue_local_byref_vars (tree self_parm, tree component,
+ tree stmt)
+{
+ tree decl, block_component;
+ tree_stmt_iterator i;
+ tree decl_stmt;
+
+ decl = component;
+ block_component = build_component_ref (build_indirect_ref (self_parm, "->"),
+ DECL_NAME (component));
+ gcc_assert (block_component);
+ DECL_EXTERNAL (decl) = 0;
+ TREE_STATIC (decl) = 0;
+ TREE_USED (decl) = 1;
+ DECL_CONTEXT (decl) = current_function_decl;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_INITIAL (decl) = block_component;
+ /* Prepend a DECL_EXPR statement to the statement list. */
+ i = tsi_start (stmt);
+ decl_stmt = build_stmt (DECL_EXPR, decl);
+ SET_EXPR_LOCATION (decl_stmt, DECL_SOURCE_LOCATION (decl));
+ /* APPLE LOCAL begin radar 6163705, Blocks prologues */
+ /* Give the prologue statements a line number of one before the beginning of
+ the function, to make them easily identifiable later. */
+ EXPR_LINENO (decl_stmt) = DECL_SOURCE_LINE (decl) - 1;
+ /* APPLE LOCAL end radar 6163705, Blocks prologues */
+ decl_stmt = build3 (BIND_EXPR, void_type_node, decl, decl_stmt, NULL);
+ TREE_SIDE_EFFECTS (decl_stmt) = 1;
+
+ tsi_link_before (&i, decl_stmt, TSI_SAME_STMT);
+}
+/* APPLE LOCAL end radar 6169527 */
+
+/**
+ block_build_prologue
+ - This routine builds the declarations for the
+ variables referenced in the block; as in:
+ int *y = .block_descriptor->y;
+ int x = .block_descriptor->x;
+
+ The decl_expr declaration for each initialization is enterred at the
+ beginning of the helper function's statement-list which is passed
+ in block_impl->block_body.
+ */
+void
+block_build_prologue (struct block_sema_info *block_impl)
+{
+ tree chain;
+ tree self_parm = lookup_name (get_identifier (".block_descriptor"));
+ gcc_assert (self_parm);
+
+ for (chain = block_impl->block_ref_decl_list; chain;
+ chain = TREE_CHAIN (chain))
+ declare_block_prologue_local_vars (self_parm, TREE_VALUE (chain),
+ block_impl->block_body);
+ /* APPLE LOCAL begin radar 6169527 */
+ for (chain = block_impl->block_byref_decl_list; chain;
+ chain = TREE_CHAIN (chain))
+ declare_block_prologue_local_byref_vars (self_parm, TREE_VALUE (chain),
+ block_impl->block_body);
+ /* APPLE LOCAL end radar 6169527 */
+}
+/* APPLE LOCAL end blocks 6040305 (ch) */
+
/* OpenMP 2.5 parsing routines. */
/* All OpenMP clauses. OpenMP 2.5. */
@@ -18875,6 +21197,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
return c_finish_omp_critical (stmt, name);
}
+
/* OpenMP 2.5:
# pragma omp flush flush-vars[opt] new-line
OpenPOWER on IntegriCloud