aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c2350
1 files changed, 2315 insertions, 35 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f38f6fbc78f..f89e5fa402f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -36,6 +36,10 @@
#include "toplev.h"
#include "output.h"
#include "target.h"
+/* APPLE LOCAL Objective-C++ */
+#include "c-common.h"
+/* APPLE LOCAL pascal strings */
+#include "../../libcpp/internal.h"
/* The lexer. */
@@ -405,6 +409,25 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
mapped to `const'. */
token->value = ridpointers[token->keyword];
}
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Handle Objective-C++ keywords. */
+ else if (token->type == CPP_AT_NAME)
+ {
+ token->type = CPP_KEYWORD;
+ switch (C_RID_CODE (token->value))
+ {
+ /* Map 'class' to '@class', 'private' to '@private', etc. */
+ case RID_CLASS: token->keyword = RID_AT_CLASS; break;
+ case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
+ case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
+ case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
+ case RID_THROW: token->keyword = RID_AT_THROW; break;
+ case RID_TRY: token->keyword = RID_AT_TRY; break;
+ case RID_CATCH: token->keyword = RID_AT_CATCH; break;
+ default: token->keyword = C_RID_CODE (token->value);
+ }
+ }
+ /* APPLE LOCAL end Objective-C++ */
else
token->keyword = RID_MAX;
}
@@ -1638,6 +1661,81 @@ static bool cp_parser_extension_opt
static void cp_parser_label_declaration
(cp_parser *);
+/* APPLE LOCAL begin Objective-C++ */
+/* Objective-C++ Productions */
+
+static tree cp_parser_objc_message_receiver
+ (cp_parser *);
+static tree cp_parser_objc_message_args
+ (cp_parser *);
+static tree cp_parser_objc_message_expression
+ (cp_parser *);
+static tree cp_parser_objc_encode_expression
+ (cp_parser *);
+static tree cp_parser_objc_defs_expression
+ (cp_parser *);
+static tree cp_parser_objc_protocol_expression
+ (cp_parser *);
+static tree cp_parser_objc_selector_expression
+ (cp_parser *);
+static tree cp_parser_objc_expression
+ (cp_parser *);
+static void cp_parser_objc_visibility_spec
+ (cp_parser *);
+static void cp_parser_objc_method_type
+ (cp_parser *);
+static tree cp_parser_objc_protocol_qualifiers
+ (cp_parser *);
+static tree cp_parser_objc_typename
+ (cp_parser *);
+static bool cp_parser_objc_selector_p
+ (enum cpp_ttype);
+static tree cp_parser_objc_selector
+ (cp_parser *);
+static tree cp_parser_objc_method_keyword_params
+ (cp_parser *);
+static tree cp_parser_objc_method_tail_params_opt
+ (cp_parser *);
+static void cp_parser_objc_interstitial_code
+ (cp_parser *);
+static tree cp_parser_objc_method_signature
+ (cp_parser *);
+static void cp_parser_objc_method_prototype_list
+ (cp_parser *);
+static void cp_parser_objc_method_definition_list
+ (cp_parser *);
+static void cp_parser_objc_class_ivars
+ (cp_parser *);
+static tree cp_parser_objc_identifier_list
+ (cp_parser *);
+static void cp_parser_objc_alias_declaration
+ (cp_parser *);
+static void cp_parser_objc_class_declaration
+ (cp_parser *);
+static void cp_parser_objc_protocol_declaration
+ (cp_parser *);
+static tree cp_parser_objc_protocol_refs_opt
+ (cp_parser *);
+static void cp_parser_objc_superclass_or_category
+ (cp_parser *, tree *, tree *);
+static void cp_parser_objc_class_interface
+ (cp_parser *);
+static void cp_parser_objc_class_implementation
+ (cp_parser *);
+static void cp_parser_objc_end_implementation
+ (cp_parser *);
+static void cp_parser_objc_declaration
+ (cp_parser *);
+static tree cp_parser_objc_try_catch_finally_statement
+ (cp_parser *);
+static tree cp_parser_objc_synchronized_statement
+ (cp_parser *);
+static tree cp_parser_objc_throw_statement
+ (cp_parser *);
+static tree cp_parser_objc_statement
+ (cp_parser *);
+/* APPLE LOCAL end Objective-C++ */
+
/* Utility Routines */
static tree cp_parser_lookup_name
@@ -1763,6 +1861,33 @@ static bool cp_parser_is_keyword
static tree cp_parser_make_typename_type
(cp_parser *, tree, tree);
+/* APPLE LOCAL begin CW asm blocks */
+static tree cp_parser_cw_asm_compound_statement
+ (cp_parser *);
+static void cp_parser_cw_asm_declaration_seq_opt
+ (cp_parser *);
+static void cp_parser_cw_asm_line_seq_opt
+ (cp_parser *);
+static void cp_parser_cw_asm_line
+ (cp_parser *);
+static void cp_parser_cw_asm_statement_seq_opt
+ (cp_parser *);
+static void cp_parser_cw_asm_statement
+ (cp_parser *);
+static tree cp_parser_cw_asm_operands
+ (cp_parser *);
+static tree cp_parser_cw_asm_operand
+ (cp_parser *);
+static tree cp_parser_cw_asm_postfix_expression
+ (cp_parser *, bool);
+static tree cp_parser_cw_identifier_or_number
+ (cp_parser* parser);
+static tree cw_build_identifier_string
+ (cp_parser* parser, const char* str);
+static tree cp_parser_cw_asm_relative_branch
+ (cp_parser *parser);
+/* APPLE LOCAL end CW asm blocks */
+
/* Returns nonzero if we are parsing tentatively. */
static inline bool
@@ -1787,6 +1912,16 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
return token->keyword == keyword;
}
+/* A minimum or maximum operator has been seen. As these are
+ deprecated, issue a warning. */
+
+static inline void
+cp_parser_warn_min_max (void)
+{
+ if (warn_deprecated && !in_system_header)
+ warning ("minimum/maximum operators are deprecated");
+}
+
/* If not parsing tentatively, issue a diagnostic of the form
FILE:LINE: MESSAGE before TOKEN
where TOKEN is the next token in the input stream. MESSAGE
@@ -1995,7 +2130,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
template <typename T> struct B : public A<T> { X x; };
The user should have said "typename A<T>::X". */
- if (processing_template_decl && current_class_type)
+ if (processing_template_decl && current_class_type
+ && TYPE_BINFO (current_class_type))
{
tree b;
@@ -2474,6 +2610,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
tree value;
bool wide = false;
+ /* APPLE LOCAL pascal strings */
+ bool pascal_p = false;
size_t count;
struct obstack str_ob;
cpp_string str, istr, *strs;
@@ -2498,6 +2636,11 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
count = 1;
if (tok->type == CPP_WSTRING)
wide = true;
+ /* APPLE LOCAL begin pascal strings */
+ else if (CPP_OPTION (parse_in, pascal_strings)
+ && str.text[1] == '\\' && str.text[2] == 'p')
+ pascal_p = true;
+ /* APPLE LOCAL end pascal strings */
strs = &str;
}
@@ -2514,6 +2657,11 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
str.len = TREE_STRING_LENGTH (tok->value);
if (tok->type == CPP_WSTRING)
wide = true;
+ /* APPLE LOCAL begin pascal strings */
+ else if (count == 1 && CPP_OPTION (parse_in, pascal_strings)
+ && str.text[1] == '\\' && str.text[2] == 'p')
+ pascal_p = true;
+ /* APPLE LOCAL end pascal strings */
obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -2530,13 +2678,23 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
wide = false;
}
+ /* APPLE LOCAL begin pascal strings */
+ if (wide)
+ pascal_p = false;
+ /* APPLE LOCAL end pascal strings */
+
if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
- (parse_in, strs, count, &istr, wide))
+ /* APPLE LOCAL pascal strings */
+ (parse_in, strs, count, &istr, wide, pascal_p))
{
value = build_string (istr.len, (char *)istr.text);
free ((void *)istr.text);
- TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
+ /* APPLE LOCAL begin pascal strings */
+ TREE_TYPE (value) = wide ? wchar_array_type_node
+ : pascal_p ? pascal_string_type_node
+ : char_array_type_node;
+ /* APPLE LOCAL end pascal strings */
value = fix_string_type (value);
}
else
@@ -2637,6 +2795,13 @@ cp_parser_translation_unit (cp_parser* parser)
( compound-statement )
__builtin_va_arg ( assignment-expression , type-id )
+ APPLE LOCAL begin Objective-C++
+ Objective-C++ Extension:
+
+ primary-expression:
+ objc-expression
+ APPLE LOCAL end Objective-C++
+
literal:
__null
@@ -2658,6 +2823,8 @@ cp_parser_primary_expression (cp_parser *parser,
tree *qualifying_class)
{
cp_token *token;
+ /* APPLE LOCAL CW asm blocks */
+ int atsignhack = 0;
/* Assume the primary expression is not an id-expression. */
*idk = CP_ID_KIND_NONE;
@@ -2863,11 +3030,27 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_OFFSETOF:
return cp_parser_builtin_offsetof (parser);
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Objective-C++ expressions. */
+ case RID_AT_ENCODE:
+ case RID_AT_PROTOCOL:
+ case RID_AT_SELECTOR:
+ return cp_parser_objc_expression (parser);
+ /* APPLE LOCAL end Objective-C++ */
+
default:
cp_parser_error (parser, "expected primary-expression");
return error_mark_node;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ case CPP_ATSIGN:
+ /* Recognize @-labels and handle them specially later. */
+ cp_lexer_consume_token (parser->lexer);
+ atsignhack = 1;
+ token = cp_lexer_peek_token (parser->lexer);
+ /* APPLE LOCAL end CW asm blocks */
+
/* An id-expression can start with either an identifier, a
`::' as the beginning of a qualified-id, or the "operator"
keyword. */
@@ -2888,6 +3071,11 @@ cp_parser_primary_expression (cp_parser *parser,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/false);
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Replace the id with an id prefixed with @. */
+ if (atsignhack)
+ id_expression = prepend_char_identifier (id_expression, '@');
+ /* APPLE LOCAL end CW asm blocks */
if (id_expression == error_mark_node)
return error_mark_node;
/* If we have a template-id, then no further lookup is
@@ -2911,6 +3099,13 @@ cp_parser_primary_expression (cp_parser *parser,
been issued. */
if (ambiguous_p)
return error_mark_node;
+
+ /* APPLE LOCAL begin Objective-C++ */
+ /* In Objective-C++, an instance variable (ivar) may be preferred
+ to whatever cp_parser_lookup_name() found. */
+ decl = objc_lookup_ivar (decl, id_expression);
+ /* APPLE LOCAL end Objective-C++ */
+
/* If name lookup gives us a SCOPE_REF, then the
qualifying scope was dependent. Just propagate the
name. */
@@ -2961,6 +3156,13 @@ cp_parser_primary_expression (cp_parser *parser,
/* Anything else is an error. */
default:
+ /* APPLE LOCAL begin Objective-C++ */
+ /* ...unless we have an Objective-C++ message or string literal, that is. */
+ if (c_dialect_objc ()
+ && (token->type == CPP_OPEN_SQUARE || token->type == CPP_OBJC_STRING))
+ return cp_parser_objc_expression (parser);
+ /* APPLE LOCAL end Objective-C++ */
+
cp_parser_error (parser, "expected primary-expression");
return error_mark_node;
}
@@ -3319,6 +3521,22 @@ cp_parser_unqualified_id (cp_parser* parser,
return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
+ /* APPLE LOCAL begin CW asm blocks C++ */
+ case CPP_NUMBER:
+ {
+ if (flag_cw_asm_blocks
+ && TREE_CODE (token->value) == INTEGER_CST)
+ {
+ char buf[60];
+
+ sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, tree_low_cst (token->value, 0));
+ cp_lexer_consume_token (parser->lexer);
+ return get_identifier (buf);
+ }
+ goto bad;
+ }
+ /* APPLE LOCAL end CW asm blocks C++ */
+
case CPP_KEYWORD:
if (token->keyword == RID_OPERATOR)
{
@@ -3347,6 +3565,8 @@ cp_parser_unqualified_id (cp_parser* parser,
/* Fall through. */
default:
+ /* APPLE LOCAL CW asm blocks C++ */
+ bad:
cp_parser_error (parser, "expected unqualified-id");
return error_mark_node;
}
@@ -3860,18 +4080,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
bool template_p = false;
tree id;
tree type;
+ tree scope;
/* Consume the `typename' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false);
- /* Look for the nested-name-specifier. */
- cp_parser_nested_name_specifier (parser,
- /*typename_keyword_p=*/true,
- /*check_dependency_p=*/true,
- /*type_p=*/true,
- /*is_declaration=*/true);
+ /* Look for the nested-name-specifier. In case of error here,
+ consume the trailing id to avoid subsequent error messages
+ for usual cases. */
+ scope = cp_parser_nested_name_specifier (parser,
+ /*typename_keyword_p=*/true,
+ /*check_dependency_p=*/true,
+ /*type_p=*/true,
+ /*is_declaration=*/true);
+
/* Look for the optional `template' keyword. */
template_p = cp_parser_optional_template_keyword (parser);
/* We don't know whether we're looking at a template-id or an
@@ -3884,9 +4108,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
/* If that didn't work, try an identifier. */
if (!cp_parser_parse_definitely (parser))
id = cp_parser_identifier (parser);
+
+ /* Don't process id if nested name specifier is invalid. */
+ if (scope == error_mark_node)
+ return error_mark_node;
/* If we look up a template-id in a non-dependent qualifying
scope, there's no need to create a dependent type. */
- if (TREE_CODE (id) == TYPE_DECL
+ else if (TREE_CODE (id) == TYPE_DECL
&& !dependent_type_p (parser->scope))
type = TREE_TYPE (id);
/* Create a TYPENAME_TYPE to represent the type to which the
@@ -3961,7 +4189,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
{
/* Warn the user that a compound literal is not
allowed in standard C++. */
- if (pedantic)
+ /* APPLE LOCAL Altivec initializers 3068233 */
+ if (pedantic && TREE_CODE (type) != VECTOR_TYPE)
pedwarn ("ISO C++ forbids compound-literals");
/* Form the representation of the compound-literal. */
postfix_expression
@@ -4645,8 +4874,13 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
switch (keyword)
{
- case RID_ALIGNOF:
+ /* APPLE LOCAL begin CW asm blocks */
case RID_SIZEOF:
+ if (inside_cw_asm_block)
+ break;
+
+ case RID_ALIGNOF:
+ /* APPLE LOCAL end CW asm blocks */
{
tree operand;
enum tree_code op;
@@ -4727,6 +4961,19 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
/* Look for a unary operator. */
unary_operator = cp_parser_unary_operator (token);
+
+ /* APPLE LOCAL begin CW asm blocks */
+ /* In the context of CW asm block, '*' followed by '+' or '-' is for
+ relative branch syntax. This is to allow "b *+8" which
+ is disallwed by darwin's assembler but nevertheless is needed to
+ be compatible with CW tools. */
+ if (inside_cw_asm_block && unary_operator == INDIRECT_REF)
+ {
+ cp_token *token = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ unary_operator = ERROR_MARK;
+ }
+ /* APPLE LOCAL end CW asm blocks */
/* The `++' and `--' operators can be handled similarly, even though
they are not technically unary-operators in the grammar. */
if (unary_operator == ERROR_MARK)
@@ -4785,6 +5032,13 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
case CONVERT_EXPR:
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
+ /* APPLE LOCAL begin CW asm blocks */
+ if (inside_cw_asm_block && TREE_TYPE (cast_expression) == 0)
+ {
+ expression = build1 (unary_operator, NULL_TREE, cast_expression);
+ break;
+ }
+ /* APPLE LOCAL end CW asm blocks */
expression = finish_unary_op_expr (unary_operator, cast_expression);
break;
@@ -4800,6 +5054,14 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
return expression;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Postfix expressions in CW asm are more restricted and handled
+ quite differently, so diverge from the usual expression
+ precedence sequence here. */
+ if (inside_cw_asm_block)
+ return cp_parser_cw_asm_postfix_expression (parser, address_p);
+ /* APPLE LOCAL end CW asm blocks */
+
return cp_parser_postfix_expression (parser, address_p, cast_p);
}
@@ -5392,8 +5654,19 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
{
/* Get an operator token. */
token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_MIN || token->type == CPP_MAX)
+ cp_parser_warn_min_max ();
+
new_prec = TOKEN_PRECEDENCE (token);
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks && inside_cw_asm_block)
+ {
+ if ((token->flags & BOL) != 0)
+ new_prec = PREC_NOT_OPERATOR;
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
/* Popping an entry off the stack means we completed a subexpression:
- either we found a token which is not an operator (`>' where it is not
an operator, or prec == PREC_NOT_OPERATOR), in which case popping
@@ -5424,6 +5697,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
cases such as 3 + 4 + 5 or 3 * 4 + 5. */
token = cp_lexer_peek_token (parser->lexer);
lookahead_prec = TOKEN_PRECEDENCE (token);
+
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks && inside_cw_asm_block)
+ {
+ if ((token->flags & BOL) != 0)
+ lookahead_prec = PREC_NOT_OPERATOR;
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
if (lookahead_prec > new_prec)
{
/* ... and prepare to parse the RHS of the new, higher priority
@@ -5454,6 +5736,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
lhs = sp->lhs;
}
+ /* APPLE LOCAL begin CW asm blocks */
+ if (inside_cw_asm_block && TREE_CODE (rhs) == COMPOUND_EXPR)
+ {
+ gcc_assert (TREE_CODE (TREE_OPERAND (rhs, 1)) == IDENTIFIER_NODE);
+ lhs = build_x_binary_op (tree_type, lhs, TREE_OPERAND (rhs, 0), &overloaded_p);
+ lhs = cw_asm_build_register_offset (lhs, TREE_OPERAND (rhs, 1));
+ return lhs;
+ }
+ /* APPLE LOCAL end CW asm blocks */
overloaded_p = false;
lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
@@ -5647,10 +5938,12 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
case CPP_MIN_EQ:
op = MIN_EXPR;
+ cp_parser_warn_min_max ();
break;
case CPP_MAX_EQ:
op = MAX_EXPR;
+ cp_parser_warn_min_max ();
break;
default:
@@ -5925,6 +6218,17 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
statement = cp_parser_jump_statement (parser);
break;
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Objective-C++ exception-handling constructs. */
+ case RID_AT_TRY:
+ case RID_AT_CATCH:
+ case RID_AT_FINALLY:
+ case RID_AT_SYNCHRONIZED:
+ case RID_AT_THROW:
+ statement = cp_parser_objc_statement (parser);
+ break;
+ /* APPLE LOCAL end Objective-C++ */
+
case RID_TRY:
statement = cp_parser_try_block (parser);
break;
@@ -6122,6 +6426,23 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
return error_mark_node;
/* Begin the compound-statement. */
compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Maybe this is the body of an asm function, which has asm lines
+ following the decls. */
+ if (cw_asm_state >= cw_asm_decls)
+ {
+ cw_asm_in_decl = 1;
+ cp_parser_cw_asm_declaration_seq_opt (parser);
+ cw_asm_in_decl = 0;
+ cw_asm_state = cw_asm_asm;
+ inside_cw_asm_block = 1;
+ clear_cw_asm_labels ();
+ cp_parser_cw_asm_line_seq_opt (parser);
+ cw_asm_state = cw_asm_none;
+ inside_cw_asm_block = 0;
+ }
+ else
+ /* APPLE LOCAL end CW asm blocks */
/* Parse an (optional) statement-seq. */
cp_parser_statement_seq_opt (parser, in_statement_expr);
/* Finish the compound-statement. */
@@ -6132,6 +6453,16 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
return compound_stmt;
}
+/* APPLE LOCAL begin CW asm blocks */
+static bool
+cp_lexer_cw_bol (cp_lexer* lexer)
+{
+ cp_token *token = cp_lexer_peek_token (lexer);
+
+ return (token->flags & BOL) != 0;
+}
+/* APPLE LOCAL end CW asm blocks */
+
/* Parse an (optional) statement-seq.
statement-seq:
@@ -6151,6 +6482,14 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
/* Parse the statement. */
cp_parser_statement (parser, in_statement_expr);
+
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks
+ && cw_asm_state >= cw_asm_decls
+ && (cp_lexer_cw_bol (parser->lexer)
+ || cp_lexer_next_token_is (parser->lexer, CPP_NAME)))
+ break;
+ /* APPLE LOCAL end CW asm blocks */
}
}
@@ -6826,6 +7165,11 @@ cp_parser_declaration (cp_parser* parser)
/* An unnamed namespace definition. */
|| token2.type == CPP_OPEN_BRACE))
cp_parser_namespace_definition (parser);
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Objective-C++ declaration/definition. */
+ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
+ cp_parser_objc_declaration (parser);
+ /* APPLE LOCAL end Objective-C++ */
/* We must have either a block declaration or a function
definition. */
else
@@ -6965,6 +7309,13 @@ cp_parser_simple_declaration (cp_parser* parser,
if (!function_definition_allowed_p
&& !decl_specifiers.any_specifiers_p)
{
+ /* APPLE LOCAL begin CW asm blocks */
+ /* We might have seen an asm opcode, and it's time to switch to
+ asm instruction handling. */
+ if (flag_cw_asm_blocks && cw_asm_state >= cw_asm_decls)
+ return;
+ /* APPLE LOCAL end CW asm blocks */
+
cp_parser_error (parser, "expected declaration");
goto done;
}
@@ -7079,6 +7430,11 @@ cp_parser_simple_declaration (cp_parser* parser,
/* Consume the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ /* APPLE LOCAL begin CW asm blocks */
+ if (flag_cw_asm_blocks)
+ cw_asm_in_decl = 0;
+ /* APPLE LOCAL end CW asm blocks */
+
done:
pop_deferring_access_checks ();
}
@@ -7234,6 +7590,15 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
++decl_specs->specs[(int) ds_thread];
break;
+ /* APPLE LOCAL begin CW asm blocks */
+ /* If we ever get here, we must be in CW asm mode. */
+ case RID_ASM:
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ ++decl_specs->specs[(int) ds_cw_asm];
+ break;
+ /* APPLE LOCAL end CW asm blocks */
+
default:
/* We did not yet find a decl-specifier yet. */
found_decl_spec = false;
@@ -7355,6 +7720,10 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
case RID_EXTERN:
case RID_MUTABLE:
case RID_THREAD:
+ /* APPLE LOCAL begin CW asm blocks */
+ /* If we ever get here, we must be in CW asm mode. */
+ case RID_ASM:
+ /* APPLE LOCAL end CW asm blocks */
/* Consume the token. */
return cp_lexer_consume_token (parser->lexer)->value;
@@ -8030,18 +8399,22 @@ cp_parser_operator (cp_parser* parser)
/* Extensions. */
case CPP_MIN:
id = ansi_opname (MIN_EXPR);
+ cp_parser_warn_min_max ();
break;
case CPP_MAX:
id = ansi_opname (MAX_EXPR);
+ cp_parser_warn_min_max ();
break;
case CPP_MIN_EQ:
id = ansi_assopname (MIN_EXPR);
+ cp_parser_warn_min_max ();
break;
case CPP_MAX_EQ:
id = ansi_assopname (MAX_EXPR);
+ cp_parser_warn_min_max ();
break;
default:
@@ -8703,6 +9076,8 @@ cp_parser_template_name (cp_parser* parser,
;
else
{
+ tree fn = NULL_TREE;
+
/* The standard does not explicitly indicate whether a name that
names a set of overloaded declarations, some of which are
templates, is a template-name. However, such a name should
@@ -8710,16 +9085,13 @@ cp_parser_template_name (cp_parser* parser,
template-id for the overloaded templates. */
fns = BASELINK_P (decl) ? BASELINK_FUNCTIONS (decl) : decl;
if (TREE_CODE (fns) == OVERLOAD)
- {
- tree fn;
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
+ if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
+ break;
- for (fn = fns; fn; fn = OVL_NEXT (fn))
- if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
- break;
- }
- else
+ if (!fn)
{
- /* Otherwise, the name does not name a template. */
+ /* The name does not name a template. */
cp_parser_error (parser, "expected template-name");
return error_mark_node;
}
@@ -9562,7 +9934,28 @@ cp_parser_simple_type_specifier (cp_parser* parser,
followed by a "<". That usually indicates that the user thought
that the type was a template. */
if (type && type != error_mark_node)
- cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+ /* APPLE LOCAL begin Objective-C++ */
+ {
+ /* As a last-ditch effort, see if TYPE is an Objective-C type.
+ If it is, then the '<'...'>' enclose protocol names rather than
+ template arguments, and so everything is fine. */
+ if (c_dialect_objc ()
+ && (objc_is_id (type) || objc_is_class_name (type)))
+ {
+ tree protos = cp_parser_objc_protocol_refs_opt (parser);
+ tree qual_type = objc_get_protocol_qualified_type (type, protos);
+
+ /* Clobber the "unqualified" type previously entered into
+ DECL_SPECS with the new, improved protocol-qualifed version. */
+ if (decl_specs)
+ decl_specs->type = qual_type;
+
+ return qual_type;
+ }
+
+ cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+ }
+ /* APPLE LOCAL end Objective-C++ */
return type;
}
@@ -9580,7 +9973,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
typedef-name:
identifier
- Returns a TYPE_DECL for the the type. */
+ Returns a TYPE_DECL for the type. */
static tree
cp_parser_type_name (cp_parser* parser)
@@ -9608,6 +10001,19 @@ cp_parser_type_name (cp_parser* parser)
/* Look up the type-name. */
type_decl = cp_parser_lookup_name_simple (parser, identifier);
+
+ /* APPLE LOCAL begin Objective-C++ */
+ if (TREE_CODE (type_decl) != TYPE_DECL
+ && (objc_is_id (identifier) || objc_is_class_name (identifier)))
+ {
+ /* See if this is an Objective-C type. */
+ tree protos = cp_parser_objc_protocol_refs_opt (parser);
+ tree type = objc_get_protocol_qualified_type (identifier, protos);
+ if (type)
+ type_decl = TYPE_NAME (type);
+ }
+ /* APPLE LOCAL end Objective-C++ */
+
/* Issue an error if we did not find a type-name. */
if (TREE_CODE (type_decl) != TYPE_DECL)
{
@@ -10326,6 +10732,8 @@ cp_parser_using_directive (cp_parser* parser)
asm-definition:
asm ( string-literal ) ;
+ APPLE LOCAL CW asm blocks
+ asm { asm-line [opt] }
GNU Extension:
@@ -10349,6 +10757,27 @@ cp_parser_asm_definition (cp_parser* parser)
bool volatile_p = false;
bool extended_p = false;
+ /* APPLE LOCAL begin CW asm blocks */
+ cp_token *nextup;
+ /* Detect when a leading `asm' is actually a spec of an asm function
+ rather than an asm statement or block. */
+ if (flag_cw_asm_blocks)
+ {
+ nextup = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (!((nextup->type == CPP_OPEN_PAREN)
+ || (nextup->keyword == RID_VOLATILE
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_OPEN_PAREN)
+ || (nextup->type == CPP_OPEN_BRACE)))
+ {
+ /* An asm function - we'll treat the `asm' as if it were a
+ storage class spec, which will eventually affect function
+ body parsing. */
+ cp_parser_simple_declaration (parser, true);
+ return;
+ }
+ }
+ /* APPLE LOCAL end CW asm blocks */
+
/* Look for the `asm' keyword. */
cp_parser_require_keyword (parser, RID_ASM, "`asm'");
/* See if the next token is `volatile'. */
@@ -10360,6 +10789,21 @@ cp_parser_asm_definition (cp_parser* parser)
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
}
+ /* APPLE LOCAL begin CW asm blocks */
+ /* A CW-style asm block is introduced by an open brace. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ if (flag_cw_asm_blocks)
+ {
+ cp_parser_cw_asm_compound_statement (parser);
+ }
+ else
+ {
+ error ("asm blocks not enabled, use `-fasm-blocks'");
+ }
+ return;
+ }
+ /* APPLE LOCAL end CW asm blocks */
/* Look for the opening `('. */
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
return;
@@ -11107,15 +11551,8 @@ cp_parser_direct_declarator (cp_parser* parser,
bounds = fold_non_dependent_expr (bounds);
/* Normally, the array bound must be an integral constant
expression. However, as an extension, we allow VLAs
- in function scopes. And, we allow type-dependent
- expressions in templates; sometimes we don't know for
- sure whether or not something is a valid integral
- constant expression until instantiation time. (It
- doesn't make sense to check for value-dependency, as
- an expression is only value-dependent when it is a
- constant expression.) */
- else if (!type_dependent_expression_p (bounds)
- && !at_function_scope_p ())
+ in function scopes. */
+ else if (!at_function_scope_p ())
{
error ("array bound is not an integer constant");
bounds = error_mark_node;
@@ -11693,7 +12130,11 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
/* Peek at the next token. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
- || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+ /* APPLE LOCAL begin Objective-C++ */
+ || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
+ || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ /* APPLE LOCAL end Objective-C++ */
/* The parameter-declaration-list is complete. */
break;
else if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
@@ -12849,9 +13290,18 @@ cp_parser_class_head (cp_parser* parser,
CLASSTYPE_DECLARED_CLASS (type) = (class_key == class_type);
cp_parser_check_class_key (class_key, type);
+ /* If this type was already complete, and we see another definition,
+ that's an error. */
+ if (type != error_mark_node && COMPLETE_TYPE_P (type))
+ {
+ error ("redefinition of %q#T", type);
+ cp_error_at ("previous definition of %q#T", type);
+ type = NULL_TREE;
+ goto done;
+ }
+
/* We will have entered the scope containing the class; the names of
- base classes should be looked up in that context. For example,
- given:
+ base classes should be looked up in that context. For example:
struct A { struct B {}; struct C; };
struct A::C : B {};
@@ -13027,6 +13477,24 @@ cp_parser_member_declaration (cp_parser* parser)
return;
}
+ /* APPLE LOCAL begin Objective-C++ */
+ /* Check for @defs. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS))
+ {
+ tree ivar, member;
+ tree ivar_chains = cp_parser_objc_defs_expression (parser);
+ ivar = ivar_chains;
+ while (ivar)
+ {
+ member = ivar;
+ ivar = TREE_CHAIN (member);
+ TREE_CHAIN (member) = NULL_TREE;
+ finish_member_declaration (member);
+ }
+ return;
+ }
+ /* APPLE LOCAL end Objective-C++ */
+
/* Parse the decl-specifier-seq. */
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_OPTIONAL,
@@ -14332,7 +14800,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
lookup_member, we must enter the scope here. */
if (dependent_p)
pushed_scope = push_scope (parser->scope);
- /* If the PARSER->SCOPE is a a template specialization, it
+ /* If the PARSER->SCOPE is a template specialization, it
may be instantiated during name lookup. In that case,
errors may be issued. Even if we rollback the current
tentative parse, those errors are valid. */
@@ -15991,6 +16459,1818 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
return parser->allow_gnu_extensions_p;
}
+/* APPLE LOCAL begin CW asm blocks */
+
+/* This is the section of CW-asm-specific parsing functions. */
+
+static tree
+cp_parser_cw_asm_compound_statement (cp_parser *parser)
+{
+ tree compound_stmt;
+
+ cw_asm_state = cw_asm_asm;
+ inside_cw_asm_block = 1;
+ cw_asm_at_bol = 1;
+ clear_cw_asm_labels ();
+ if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+ return error_mark_node;
+ /* Begin the compound-statement. */
+ compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ /* Parse an (optional) statement-seq. */
+ cp_parser_cw_asm_line_seq_opt (parser);
+ /* Finish the compound-statement. */
+ finish_compound_stmt (compound_stmt);
+ /* Consume the `}'. */
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ /* We're done with the block of asm. */
+ inside_cw_asm_block = 0;
+ cw_asm_state = cw_asm_none;
+ return compound_stmt;
+}
+
+static void
+cp_parser_cw_asm_declaration_seq_opt (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_NAME
+ && !cw_asm_typename_or_reserved (token->value))
+ return;
+
+ /* Scan declarations until there aren't any more. */
+ while (true)
+ {
+ /* If we're looking at a `}', then we've run out of statements. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ /* Parse a declaration. */
+ cp_parser_simple_declaration (parser, false);
+
+ /* CPP_PRAGMA is a #pragma inside a function body, which
+ constitutes a declaration all its own. */
+ if (token->type == CPP_PRAGMA)
+ cp_lexer_handle_pragma (parser->lexer);
+
+ if (cw_asm_state >= cw_asm_decls
+ && (cp_lexer_cw_bol (parser->lexer)
+ || cp_lexer_next_token_is (parser->lexer, CPP_NAME)))
+ break;
+ }
+}
+
+/* Parse an (optional) line-seq.
+
+ line-seq:
+ line
+ line-seq [opt] line */
+
+static void
+cp_parser_cw_asm_line_seq_opt (cp_parser* parser)
+{
+ /* Scan lines of asm until there aren't any more. */
+ while (true)
+ {
+ /* If we're looking at a `}', then we've run out of lines. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ /* Parse the line. */
+ cp_parser_cw_asm_line (parser);
+ }
+}
+
+static void
+cp_parser_cw_asm_line (cp_parser* parser)
+{
+ cp_parser_cw_asm_statement_seq_opt (parser);
+}
+
+static void
+cp_parser_cw_asm_statement_seq_opt (cp_parser* parser)
+{
+ /* Scan statements until there aren't any more. */
+ while (true)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ /* Semicolons divide up individual statements. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+
+ /* Parse a single statement. */
+ cp_parser_cw_asm_statement (parser);
+
+ /* We parse at most, one line. */
+ if (cp_lexer_cw_bol (parser->lexer))
+ break;
+
+ if (!(cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)))
+ {
+ cp_parser_error (parser, "expected `;' or `}' or end-of-line");
+ }
+ }
+}
+
+/* Build an identifier comprising the string passed and the
+ next token. */
+
+static tree
+cw_build_identifier_string (cp_parser* parser, const char* str)
+{
+ char *buf;
+ int len;
+ tree id;
+
+ id = cp_parser_cw_identifier_or_number (parser);
+ len = strlen (str);
+ buf = (char *) alloca (IDENTIFIER_LENGTH (id) + len + 1);
+ memcpy (buf, str, len);
+ memcpy (buf+len, IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
+ buf[IDENTIFIER_LENGTH (id) + len] = 0;
+ return get_identifier (buf);
+}
+
+/* Parse a CW asm identifier. Returns an IDENTIFIER_NODE representing
+ the identifier. The CW asm identifieriers include [.+-] as part of
+ the identifier. */
+
+static tree
+cp_parser_cw_identifier (cp_parser* parser)
+{
+ cp_token *token;
+ tree t;
+ const char *str = "";
+
+ /* We have to accept certain keywords. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->flags & NAMED_OP)
+ {
+ const char *s = 0;
+ switch (token->type) {
+ case CPP_AND_AND: s="and"; break;
+ case CPP_AND_EQ: s="and_eq"; break;
+ case CPP_AND: s="bitand"; break;
+ case CPP_OR: s="bitor"; break;
+ case CPP_COMPL: s="compl"; break;
+ case CPP_NOT: s="not"; break;
+ case CPP_NOT_EQ: s="not_eq"; break;
+ case CPP_OR_OR: s="or"; break;
+ case CPP_OR_EQ: s="or_eq"; break;
+ case CPP_XOR: s="xor"; break;
+ case CPP_XOR_EQ: s="xor_eq"; break;
+ default: break;
+ }
+
+ /* The above list is the entire list of named operators. We
+ can't fail to translate the name. See operator_array in
+ libcpp/init.c. */
+ gcc_assert (s != 0);
+ cp_lexer_consume_token (parser->lexer);
+ t = get_identifier (s);
+ }
+ else
+ if (token->type == CPP_DOT)
+ {
+ /* .align */
+ cp_lexer_consume_token (parser->lexer);
+ t = cw_build_identifier_string (parser, ".");
+ }
+ else
+ t = cp_parser_identifier (parser);
+
+ if (t == error_mark_node)
+ return t;
+
+ token = cp_lexer_peek_token (parser->lexer);
+
+ switch (token->type)
+ {
+ case CPP_DOT:
+ str = ".";
+ break;
+ case CPP_PLUS:
+ str = "+";
+ break;
+ case CPP_MINUS:
+ str = "-";
+ break;
+ case CPP_PLUS_PLUS:
+ str = "++";
+ break;
+ case CPP_MINUS_MINUS:
+ str = "--";
+ break;
+ default:
+ return t;
+ }
+
+ /* If there was whitespace between the identifier and the [.+-]
+ character, then that character can't be part of the
+ identifier. */
+ if (token->flags & PREV_WHITE)
+ return t;
+
+ cp_lexer_consume_token (parser->lexer);
+
+ return cw_get_identifier (t, str);
+}
+
+static tree
+cp_parser_cw_identifier_or_number (cp_parser* parser)
+{
+ cp_token *token;
+
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_NUMBER
+ && TREE_CODE (token->value) == INTEGER_CST)
+ {
+ char buf[60];
+
+ sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, tree_low_cst (token->value, 0));
+ cp_lexer_consume_token (parser->lexer);
+ return get_identifier (buf);
+ }
+
+ return cp_parser_identifier (parser);
+}
+
+static void
+cp_parser_cw_asm_statement (cp_parser* parser)
+{
+ tree aname, scspec, anothername, operands;
+
+ /* Keep sucking labels from the front of the statement until a
+ non-label is seen. */
+ while (true)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
+ {
+ cp_lexer_handle_pragma (parser->lexer);
+ }
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_ATSIGN))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ aname = cp_parser_cw_identifier_or_number (parser);
+ /* Optional ':' after a label. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ cp_lexer_consume_token (parser->lexer);
+ cw_asm_label (aname, 1);
+ }
+ else
+ {
+ aname = cp_parser_cw_identifier (parser);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cw_asm_label (aname, 0);
+ }
+ else
+ {
+ scspec = cp_parser_storage_class_specifier_opt (parser);
+ if (scspec)
+ {
+ anothername = cp_parser_cw_asm_operand (parser);
+ cw_asm_entry (aname, scspec, anothername);
+ }
+ else
+ {
+ cw_asm_in_operands = 1;
+ operands = cp_parser_cw_asm_operands (parser);
+ cw_asm_stmt (aname, operands, input_line);
+ }
+ break;
+ }
+ }
+
+ if (cp_lexer_cw_bol (parser->lexer))
+ break;
+ }
+}
+
+tree
+cp_parser_cw_asm_operands (cp_parser *parser)
+{
+ tree operands = NULL_TREE, operand;
+
+ while (true)
+ {
+ /* If we're looking at the end of the line, then we've run out of operands. */
+ if (cp_lexer_cw_bol (parser->lexer)
+ || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+ || cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
+ || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
+
+ operand = cp_parser_cw_asm_operand (parser);
+
+ if (operand)
+ {
+ operands = chainon (operands, build_tree_list (NULL_TREE, operand));
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ {
+ return error_mark_node;
+ }
+ }
+
+ return operands;
+}
+
+tree
+cp_parser_cw_asm_operand (cp_parser *parser)
+{
+ tree operand;
+
+ /* Jump into the usual operand precedence stack. */
+ operand = cp_parser_binary_expression (parser, false);
+
+ return operand;
+}
+
+/* Need to handle case of relative branch using: .[+|-]number
+ syntax */
+static tree
+cp_parser_cw_asm_relative_branch (cp_parser *parser)
+{
+ cp_token *token;
+ token = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ const char *str = (token->type == CPP_PLUS) ? ".+" : ".-";
+ /* consume '.' */
+ cp_lexer_consume_token (parser->lexer);
+ /* consume '-' or '+' */
+ cp_lexer_consume_token (parser->lexer);
+ return cw_build_identifier_string (parser, str);
+ }
+ return error_mark_node;
+}
+
+/* Parse a CW asm-style postfix-expression.
+
+ postfix-expression:
+ primary-expression
+ postfix-expression [ expression ]
+ postfix-expression ( expression-list [opt] )
+ simple-type-specifier ( expression-list [opt] )
+ postfix-expression . template [opt] id-expression
+ postfix-expression -> template [opt] id-expression
+ postfix-expression . pseudo-destructor-name
+ postfix-expression -> pseudo-destructor-name
+ typeid ( expression )
+ typeid ( type-id )
+
+ GNU Extension:
+
+ postfix-expression:
+ ( type-id ) { initializer-list , [opt] }
+
+ This extension is a GNU version of the C99 compound-literal
+ construct. (The C99 grammar uses `type-name' instead of `type-id',
+ but they are essentially the same concept.)
+
+ If ADDRESS_P is true, the postfix expression is the operand of the
+ `&' operator.
+
+ Returns a representation of the expression. */
+
+static tree
+cp_parser_cw_asm_postfix_expression (cp_parser *parser, bool address_p)
+{
+ bool for_offsetof = false;
+ cp_token *token;
+ enum rid keyword;
+ cp_id_kind idk = CP_ID_KIND_NONE;
+ tree postfix_expression = NULL_TREE;
+ /* Non-NULL only if the current postfix-expression can be used to
+ form a pointer-to-member. In that case, QUALIFYING_CLASS is the
+ class used to qualify the member. */
+ tree qualifying_class = NULL_TREE;
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* Some of the productions are determined by keywords. */
+ keyword = token->keyword;
+ switch (keyword)
+ {
+ case RID_SIZEOF:
+ {
+ tree operand;
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the operand. */
+ operand = cp_parser_sizeof_operand (parser, keyword);
+ postfix_expression = cxx_sizeof_or_alignof_type (operand, SIZEOF_EXPR, true);
+ break;
+ }
+
+ default:
+ {
+ tree type;
+
+ /* If the next thing is a simple-type-specifier, we may be
+ looking at a functional cast. We could also be looking at
+ an id-expression. So, we try the functional cast, and if
+ that doesn't work we fall back to the primary-expression. */
+ cp_parser_parse_tentatively (parser);
+ /* Look for the simple-type-specifier. */
+ type = cp_parser_simple_type_specifier (parser,
+ CP_PARSER_FLAGS_NONE,
+ /*identifier_p=*/false);
+ /* Parse the cast itself. */
+ if (!cp_parser_error_occurred (parser))
+ postfix_expression
+ = cp_parser_functional_cast (parser, type);
+ /* If that worked, we're done. */
+ if (cp_parser_parse_definitely (parser))
+ break;
+
+ if (token->type == CPP_DOT || token->type == CPP_MULT)
+ {
+ postfix_expression = cp_parser_cw_asm_relative_branch (parser);
+ if (postfix_expression != error_mark_node)
+ break;
+ }
+
+ /* If the functional-cast didn't work out, try a
+ compound-literal. */
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ tree initializer_list = NULL_TREE;
+ bool saved_in_type_id_in_expr_p;
+
+ cp_parser_parse_tentatively (parser);
+ /* Consume the `('. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the type. */
+ saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+ parser->in_type_id_in_expr_p = true;
+ type = cp_parser_type_id (parser);
+ parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
+ /* Look for the `)'. */
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ /* Look for the `{'. */
+ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+ /* If things aren't going well, there's no need to
+ keep going. */
+ if (!cp_parser_error_occurred (parser))
+ {
+ bool non_constant_p;
+ /* Parse the initializer-list. */
+ initializer_list
+ = cp_parser_initializer_list (parser, &non_constant_p);
+ /* Allow a trailing `,'. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ /* Look for the final `}'. */
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ }
+ /* If that worked, we're definitely looking at a
+ compound-literal expression. */
+ if (cp_parser_parse_definitely (parser))
+ {
+ /* Warn the user that a compound literal is not
+ allowed in standard C++. */
+ if (pedantic)
+ pedwarn ("ISO C++ forbids compound-literals");
+ /* Form the representation of the compound-literal. */
+ postfix_expression
+ = finish_compound_literal (type, initializer_list);
+ break;
+ }
+ }
+
+ /* It must be a primary-expression. */
+ postfix_expression = cp_parser_primary_expression (parser,
+ false,
+ &idk,
+ &qualifying_class);
+ }
+ break;
+ }
+
+ /* If we were avoiding committing to the processing of a
+ qualified-id until we knew whether or not we had a
+ pointer-to-member, we now know. */
+ if (qualifying_class)
+ {
+ bool done;
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ done = (token->type != CPP_OPEN_SQUARE
+ && token->type != CPP_OPEN_PAREN
+ && token->type != CPP_DOT
+ && token->type != CPP_DEREF
+ && token->type != CPP_PLUS_PLUS
+ && token->type != CPP_MINUS_MINUS);
+
+ postfix_expression = finish_qualified_id_expr (qualifying_class,
+ postfix_expression,
+ done,
+ address_p);
+ if (done)
+ return postfix_expression;
+ }
+
+ /* Keep looping until the postfix-expression is complete. */
+ while (true)
+ {
+ if (idk == CP_ID_KIND_UNQUALIFIED
+ && TREE_CODE (postfix_expression) == IDENTIFIER_NODE
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
+ /* It is not a Koenig lookup function call. */
+ postfix_expression
+ = unqualified_name_lookup_error (postfix_expression);
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ switch (token->type)
+ {
+ case CPP_OPEN_SQUARE:
+ /* postfix-expression [ expression ] */
+ {
+ tree index;
+
+ /* Consume the `[' token. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the index expression. */
+ index = cp_parser_expression (parser, false);
+ /* Look for the closing `]'. */
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+
+ /* Build the ARRAY_REF. */
+ postfix_expression
+ = grok_array_decl (postfix_expression, index);
+ idk = CP_ID_KIND_NONE;
+ /* Array references are not permitted in
+ constant-expressions. */
+ if (cp_parser_non_integral_constant_expression
+ (parser, "an array reference"))
+ postfix_expression = error_mark_node;
+ }
+ break;
+
+ case CPP_OPEN_PAREN:
+ /* postfix-expression ( expression ) */
+ {
+ tree expr;
+
+ cp_lexer_consume_token (parser->lexer);
+ expr = cp_parser_binary_expression (parser, false);
+
+ if (expr == error_mark_node)
+ {
+ postfix_expression = error_mark_node;
+ break;
+ }
+
+ postfix_expression =
+ cw_asm_build_register_offset (postfix_expression, expr);
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ /* The POSTFIX_EXPRESSION is certainly no longer an id. */
+ idk = CP_ID_KIND_NONE;
+ }
+ break;
+
+ case CPP_DOT:
+ /* Disambiguation of asm's last operand followed by a '.'.
+ This happens when an asm instruction is followed by a
+ directive, such as .align. Bail out early. */
+ if (TREE_CODE (postfix_expression) == INTEGER_CST
+ || TREE_CODE (postfix_expression) == IDENTIFIER_NODE
+ || TREE_CODE (postfix_expression) == COMPOUND_EXPR)
+ return postfix_expression;
+
+ case CPP_DEREF:
+ /* postfix-expression . template [opt] id-expression
+ postfix-expression . pseudo-destructor-name
+ postfix-expression -> template [opt] id-expression
+ postfix-expression -> pseudo-destructor-name */
+ {
+ tree name;
+ bool dependent_p;
+ bool template_p;
+ tree scope = NULL_TREE;
+ enum cpp_ttype token_type = token->type;
+
+ /* If this is a `->' operator, dereference the pointer. */
+ if (token->type == CPP_DEREF)
+ postfix_expression = build_x_arrow (postfix_expression);
+ /* Check to see whether or not the expression is
+ type-dependent. */
+ dependent_p = type_dependent_expression_p (postfix_expression);
+ /* The identifier following the `->' or `.' is not
+ qualified. */
+ parser->scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ idk = CP_ID_KIND_NONE;
+ /* Enter the scope corresponding to the type of the object
+ given by the POSTFIX_EXPRESSION. */
+ if (!dependent_p
+ && TREE_TYPE (postfix_expression) != NULL_TREE)
+ {
+ scope = TREE_TYPE (postfix_expression);
+ /* According to the standard, no expression should
+ ever have reference type. Unfortunately, we do not
+ currently match the standard in this respect in
+ that our internal representation of an expression
+ may have reference type even when the standard says
+ it does not. Therefore, we have to manually obtain
+ the underlying type here. */
+ scope = non_reference (scope);
+ /* The type of the POSTFIX_EXPRESSION must be
+ complete. */
+ scope = complete_type_or_else (scope, NULL_TREE);
+ /* Let the name lookup machinery know that we are
+ processing a class member access expression. */
+ parser->context->object_type = scope;
+ /* If something went wrong, we want to be able to
+ discern that case, as opposed to the case where
+ there was no SCOPE due to the type of expression
+ being dependent. */
+ if (!scope)
+ scope = error_mark_node;
+ /* If the SCOPE was erroneous, make the various
+ semantic analysis functions exit quickly -- and
+ without issuing additional error messages. */
+ if (scope == error_mark_node)
+ postfix_expression = error_mark_node;
+ }
+
+ /* Consume the `.' or `->' operator. */
+ cp_lexer_consume_token (parser->lexer);
+ /* If the SCOPE is not a scalar type, we are looking at an
+ ordinary class member access expression, rather than a
+ pseudo-destructor-name. */
+ if (!scope || !SCALAR_TYPE_P (scope))
+ {
+ template_p = cp_parser_optional_template_keyword (parser);
+ /* Parse the id-expression. */
+ name = cp_parser_id_expression (parser,
+ template_p,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false);
+ /* In general, build a SCOPE_REF if the member name is
+ qualified. However, if the name was not dependent
+ and has already been resolved; there is no need to
+ build the SCOPE_REF. For example;
+
+ struct X { void f(); };
+ template <typename T> void f(T* t) { t->X::f(); }
+
+ Even though "t" is dependent, "X::f" is not and has
+ been resolved to a BASELINK; there is no need to
+ include scope information. */
+
+ /* But we do need to remember that there was an explicit
+ scope for virtual function calls. */
+ if (parser->scope)
+ idk = CP_ID_KIND_QUALIFIED;
+
+ if (name != error_mark_node
+ && !BASELINK_P (name)
+ && parser->scope)
+ {
+ name = build_nt (SCOPE_REF, parser->scope, name);
+ parser->scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ }
+ if (scope && name && BASELINK_P (name))
+ adjust_result_of_qualified_name_lookup
+ (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
+ postfix_expression
+ = cw_asm_cp_build_component_ref (postfix_expression, name);
+ }
+ /* Otherwise, try the pseudo-destructor-name production. */
+ else
+ {
+ tree s = NULL_TREE;
+ tree type;
+
+ /* Parse the pseudo-destructor-name. */
+ cp_parser_pseudo_destructor_name (parser, &s, &type);
+ /* Form the call. */
+ postfix_expression
+ = finish_pseudo_destructor_expr (postfix_expression,
+ s, TREE_TYPE (type));
+ }
+
+ /* We no longer need to look up names in the scope of the
+ object on the left-hand side of the `.' or `->'
+ operator. */
+ parser->context->object_type = NULL_TREE;
+
+ /* Outside of offsetof, these operators may not appear in
+ constant-expressions. */
+ if (!for_offsetof
+ && (cp_parser_non_integral_constant_expression
+ (parser, token_type == CPP_DEREF ? "'->'" : "`.'")))
+ postfix_expression = error_mark_node;
+ }
+ break;
+
+ default:
+ return postfix_expression;
+ }
+ }
+
+ /* We should never get here. */
+ abort ();
+ return error_mark_node;
+}
+
+int
+cw_asm_typename_or_reserved (tree value)
+{
+ return (C_IS_RESERVED_WORD (value));
+}
+/* APPLE LOCAL end CW asm blocks */
+
+/* APPLE LOCAL begin Objective-C++ */
+/* Objective-C++ Productions */
+
+
+/* Parse an Objective-C expression, which feeds into a primary-expression
+ above.
+
+ objc-expression:
+ objc-message-expression
+ objc-string-literal
+ objc-encode-expression
+ objc-protocol-expression
+ objc-selector-expression
+
+ Returns a tree representation of the expression. */
+
+static tree
+cp_parser_objc_expression (cp_parser* parser)
+{
+ /* Try to figure out what kind of declaration is present. */
+ cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+ switch (kwd->type)
+ {
+ case CPP_OPEN_SQUARE:
+ return cp_parser_objc_message_expression (parser);
+
+ case CPP_OBJC_STRING:
+ kwd = cp_lexer_consume_token (parser->lexer);
+ return objc_build_string_object (kwd->value);
+
+ case CPP_KEYWORD:
+ switch (kwd->keyword)
+ {
+ case RID_AT_ENCODE:
+ return cp_parser_objc_encode_expression (parser);
+
+ case RID_AT_PROTOCOL:
+ return cp_parser_objc_protocol_expression (parser);
+
+ case RID_AT_SELECTOR:
+ return cp_parser_objc_selector_expression (parser);
+
+ default:
+ break;
+ }
+ default:
+ error ("misplaced `@%D' Objective-C++ construct", kwd->value);
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ }
+
+ return error_mark_node;
+}
+
+/* Parse an Objective-C message expression.
+
+ objc-message-expression:
+ [ objc-message-receiver objc-message-args ]
+
+ Returns a representation of an Objective-C message. */
+
+static tree
+cp_parser_objc_message_expression (cp_parser* parser)
+{
+ tree receiver, messageargs;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '['. */
+ receiver = cp_parser_objc_message_receiver (parser);
+ messageargs = cp_parser_objc_message_args (parser);
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+
+ return objc_build_message_expr (build_tree_list (receiver, messageargs));
+}
+
+/* Parse an objc-message-receiver.
+
+ objc-message-receiver:
+ type-name
+ expression
+
+ Returns a representation of the type or expression. */
+
+static tree
+cp_parser_objc_message_receiver (cp_parser* parser)
+{
+ tree rcv;
+ bool class_scope_p, template_p;
+
+ /* An Objective-C message receiver may be either (1) a type
+ or (2) an expression. */
+ cp_parser_parse_tentatively (parser);
+ rcv = cp_parser_expression (parser, false);
+
+ if (cp_parser_parse_definitely (parser))
+ return rcv;
+
+ /* Look for the optional `::' operator. */
+ cp_parser_global_scope_opt (parser, false);
+ /* Look for the nested-name-specifier. */
+ cp_parser_nested_name_specifier_opt (parser,
+ /*typename_keyword_p=*/true,
+ /*check_dependency_p=*/true,
+ /*type_p=*/true,
+ /*is_declaration=*/true);
+ class_scope_p = (parser->scope && TYPE_P (parser->scope));
+ template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
+ /* Finally, look for the class-name. */
+ rcv = cp_parser_class_name (parser,
+ class_scope_p,
+ template_p,
+ /*type_p=*/true,
+ /*check_dependency_p=*/true,
+ /*class_head_p=*/false,
+ /*is_declaration=*/true);
+
+ return objc_get_class_reference (rcv);
+}
+
+/* Parse the arguments and selectors comprising an Objective-C message.
+
+ objc-message-args:
+ objc-selector
+ objc-selector-args
+ objc-selector-args , objc-comma-args
+
+ objc-selector-args:
+ objc-selector [opt] : assignment-expression
+ objc-selector-args objc-selector [opt] : assignment-expression
+
+ objc-comma-args:
+ assignment-expression
+ objc-comma-args , assignment-expression
+
+ Returns a TREE_LIST, with TREE_PURPOSE containing a list of
+ selector arguments and TREE_VALUE containing a list of comma
+ arguments. */
+
+static tree
+cp_parser_objc_message_args (cp_parser* parser)
+{
+ tree sel_args = NULL_TREE, addl_args = NULL_TREE;
+ bool maybe_unary_selector_p = true;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+ {
+ tree selector = NULL_TREE, arg;
+
+ if (token->type != CPP_COLON)
+ selector = cp_parser_objc_selector (parser);
+
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ return build_tree_list (selector, NULL_TREE);
+
+ maybe_unary_selector_p = false;
+ cp_parser_require (parser, CPP_COLON, "`:'");
+ arg = cp_parser_assignment_expression (parser, false);
+
+ sel_args
+ = chainon (sel_args,
+ build_tree_list (selector, arg));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ /* Handle non-selector arguments, if any. */
+ while (token->type == CPP_COMMA)
+ {
+ tree arg;
+
+ cp_lexer_consume_token (parser->lexer);
+ arg = cp_parser_assignment_expression (parser, false);
+
+ addl_args
+ = chainon (addl_args,
+ build_tree_list (NULL_TREE, arg));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return build_tree_list (sel_args, addl_args);
+}
+
+/* Parse an Objective-C encode expression.
+
+ objc-encode-expression:
+ @encode objc-typename
+
+ Returns an encoded representation of the type argument. */
+
+static tree
+cp_parser_objc_encode_expression (cp_parser* parser)
+{
+ tree type;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ type = complete_type (cp_parser_type_id (parser));
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ if (!type)
+ {
+ error ("`@encode' must specify a type as an argument");
+ return error_mark_node;
+ }
+
+ return objc_build_encode_expr (type);
+}
+
+/* Parse an Objective-C @defs expression. */
+
+static tree
+cp_parser_objc_defs_expression (cp_parser *parser)
+{
+ tree name;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@defs'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ name = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ return objc_get_class_ivars (name);
+}
+
+/* Parse an Objective-C protocol expression.
+
+ objc-protocol-expression:
+ @protocol ( identifier )
+
+ Returns a representation of the protocol expression. */
+
+static tree
+cp_parser_objc_protocol_expression (cp_parser* parser)
+{
+ tree proto;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ proto = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ return objc_build_protocol_expr (proto);
+}
+
+/* Parse an Objective-C selector expression.
+
+ objc-selector-expression:
+ @selector ( objc-method-signature )
+
+ objc-method-signature:
+ objc-selector
+ objc-selector-seq
+
+ objc-selector-seq:
+ objc-selector :
+ objc-selector-seq objc-selector :
+
+ Returns a representation of the method selector. */
+
+static tree
+cp_parser_objc_selector_expression (cp_parser* parser)
+{
+ tree sel_seq = NULL_TREE;
+ bool maybe_unary_selector_p = true;
+ cp_token *token;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ token = cp_lexer_peek_token (parser->lexer);
+
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+ {
+ tree selector = NULL_TREE;
+
+ if (token->type != CPP_COLON)
+ selector = cp_parser_objc_selector (parser);
+
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ {
+ sel_seq = selector;
+ goto finish_selector;
+ }
+
+ maybe_unary_selector_p = false;
+ cp_parser_require (parser, CPP_COLON, "`:'");
+
+ sel_seq
+ = chainon (sel_seq,
+ build_tree_list (selector, NULL_TREE));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ finish_selector:
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ return objc_build_selector_expr (sel_seq);
+}
+
+/* Parse a list of identifiers.
+
+ objc-identifier-list:
+ identifier
+ objc-identifier-list , identifier
+
+ Returns a TREE_LIST of identifier nodes. */
+
+static tree
+cp_parser_objc_identifier_list (cp_parser* parser)
+{
+ tree list = build_tree_list (NULL_TREE, cp_parser_identifier (parser));
+ cp_token *sep = cp_lexer_peek_token (parser->lexer);
+
+ while (sep->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ list = chainon (list,
+ build_tree_list (NULL_TREE,
+ cp_parser_identifier (parser)));
+ sep = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return list;
+}
+
+/* Parse an Objective-C alias declaration.
+
+ objc-alias-declaration:
+ @compatibility_alias identifier identifier ;
+
+ This function registers the alias mapping with the Objective-C front-end.
+ It returns nothing. */
+
+static void
+cp_parser_objc_alias_declaration (cp_parser* parser)
+{
+ tree alias, orig;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@compatibility_alias'. */
+ alias = cp_parser_identifier (parser);
+ orig = cp_parser_identifier (parser);
+ objc_declare_alias (alias, orig);
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse an Objective-C class forward-declaration.
+
+ objc-class-declaration:
+ @class objc-identifier-list ;
+
+ The function registers the forward declarations with the Objective-C
+ front-end. It returns nothing. */
+
+static void
+cp_parser_objc_class_declaration (cp_parser* parser)
+{
+ cp_lexer_consume_token (parser->lexer); /* Eat '@class'. */
+ objc_declare_class (cp_parser_objc_identifier_list (parser));
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse a list of Objective-C protocol references.
+
+ objc-protocol-refs-opt:
+ objc-protocol-refs [opt]
+
+ objc-protocol-refs:
+ < objc-identifier-list >
+
+ Returns a TREE_LIST of identifiers, if any. */
+
+static tree
+cp_parser_objc_protocol_refs_opt (cp_parser* parser)
+{
+ tree protorefs = NULL_TREE;
+
+ if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat '<'. */
+ protorefs = cp_parser_objc_identifier_list (parser);
+ cp_parser_require (parser, CPP_GREATER, "`>'");
+ }
+
+ return protorefs;
+}
+
+static void
+cp_parser_objc_visibility_spec (cp_parser* parser)
+{
+ cp_token *vis = cp_lexer_peek_token (parser->lexer);
+
+ switch (vis->keyword)
+ {
+ case RID_AT_PRIVATE:
+ objc_set_visibility (2);
+ break;
+ case RID_AT_PROTECTED:
+ objc_set_visibility (0);
+ break;
+ case RID_AT_PUBLIC:
+ objc_set_visibility (1);
+ break;
+ default:
+ return;
+ }
+
+ /* Eat '@private'/'@protected'/'@public'. */
+ cp_lexer_consume_token (parser->lexer);
+}
+
+static void
+cp_parser_objc_method_type (cp_parser* parser)
+{
+ objc_set_method_type
+ (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS
+ ? PLUS_EXPR
+ : MINUS_EXPR);
+}
+
+static tree
+cp_parser_objc_protocol_qualifiers (cp_parser* parser)
+{
+ tree quals = NULL_TREE, node;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ node = token->value;
+
+ while (node && TREE_CODE (node) == IDENTIFIER_NODE
+ && (node == ridpointers [(int) RID_IN]
+ || node == ridpointers [(int) RID_OUT]
+ || node == ridpointers [(int) RID_INOUT]
+ || node == ridpointers [(int) RID_BYCOPY]
+ || node == ridpointers [(int) RID_BYREF]
+ || node == ridpointers [(int) RID_ONEWAY]))
+ {
+ quals = tree_cons (NULL_TREE, node, quals);
+ cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
+ node = token->value;
+ }
+
+ return quals;
+}
+
+static tree
+cp_parser_objc_typename (cp_parser* parser)
+{
+ tree typename = NULL_TREE;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ tree proto_quals, cp_type = NULL_TREE;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '('. */
+ proto_quals = cp_parser_objc_protocol_qualifiers (parser);
+
+ /* An ObjC type name may consist of just protocol qualifiers, in which
+ case the type shall default to 'id'. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+ cp_type = cp_parser_type_id (parser);
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ typename = build_tree_list (proto_quals, cp_type);
+ }
+
+ return typename;
+}
+
+static bool
+cp_parser_objc_selector_p (enum cpp_ttype type)
+{
+ return (type == CPP_NAME || type == CPP_KEYWORD
+ || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND
+ || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT
+ || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ
+ || type == CPP_XOR || type == CPP_XOR_EQ);
+}
+
+static tree
+cp_parser_objc_selector (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+
+ if (!cp_parser_objc_selector_p (token->type))
+ {
+ error ("invalid Objective-C++ selector name");
+ return error_mark_node;
+ }
+
+ /* C++ operator names are allowed to appear in ObjC selectors. */
+ switch (token->type)
+ {
+ case CPP_AND_AND: return get_identifier ("and");
+ case CPP_AND_EQ: return get_identifier ("and_eq");
+ case CPP_AND: return get_identifier ("bitand");
+ case CPP_OR: return get_identifier ("bitor");
+ case CPP_COMPL: return get_identifier ("compl");
+ case CPP_NOT: return get_identifier ("not");
+ case CPP_NOT_EQ: return get_identifier ("not_eq");
+ case CPP_OR_OR: return get_identifier ("or");
+ case CPP_OR_EQ: return get_identifier ("or_eq");
+ case CPP_XOR: return get_identifier ("xor");
+ case CPP_XOR_EQ: return get_identifier ("xor_eq");
+ default: return token->value;
+ }
+}
+
+static tree
+cp_parser_objc_method_keyword_params (cp_parser* parser)
+{
+ tree params = NULL_TREE;
+ bool maybe_unary_selector_p = true;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+ {
+ tree selector = NULL_TREE, typename, identifier;
+
+ if (token->type != CPP_COLON)
+ selector = cp_parser_objc_selector (parser);
+
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ return selector;
+
+ maybe_unary_selector_p = false;
+ cp_parser_require (parser, CPP_COLON, "`:'");
+ typename = cp_parser_objc_typename (parser);
+ identifier = cp_parser_identifier (parser);
+
+ params
+ = chainon (params,
+ objc_build_keyword_decl (selector,
+ typename,
+ identifier));
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return params;
+}
+
+static tree
+cp_parser_objc_method_tail_params_opt (cp_parser* parser)
+{
+ tree params = make_node (TREE_LIST);
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ TREE_OVERFLOW (params) = 0; /* Initially, assume no ellipsis. */
+
+ while (token->type == CPP_COMMA)
+ {
+ cp_parameter_declarator *parmdecl;
+ tree parm;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_ELLIPSIS)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat '...'. */
+ TREE_OVERFLOW (params) = 1;
+ break;
+ }
+
+ parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+ parm = grokdeclarator (parmdecl->declarator,
+ &parmdecl->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL);
+
+ chainon (params, build_tree_list (NULL_TREE, parm));
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ return params;
+}
+
+static void
+cp_parser_objc_interstitial_code (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ /* If the next token is `extern' and the following token is a string
+ literal, then we have a linkage specification. */
+ if (token->keyword == RID_EXTERN
+ && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2)))
+ cp_parser_linkage_specification (parser);
+ /* Handle #pragma, if any. */
+ else if (token->type == CPP_PRAGMA)
+ cp_lexer_handle_pragma (parser->lexer);
+ /* Allow stray semicolons. */
+ else if (token->type == CPP_SEMICOLON)
+ cp_lexer_consume_token (parser->lexer);
+ /* Finally, try to parse a block-declaration, or a function-definition. */
+ else
+ cp_parser_block_declaration (parser, /*statement_p=*/false);
+}
+
+static tree
+cp_parser_objc_method_signature (cp_parser* parser)
+{
+ tree rettype, kwdparms, optparms;
+
+ 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);
+
+ return objc_build_method_signature (rettype, kwdparms, optparms);
+}
+
+static void
+cp_parser_objc_method_prototype_list (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (token->keyword != RID_AT_END)
+ {
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ objc_add_method_declaration
+ (cp_parser_objc_method_signature (parser));
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ }
+ else
+ /* Allow for interspersed non-ObjC++ code. */
+ cp_parser_objc_interstitial_code (parser);
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ objc_finish_interface ();
+}
+
+static void
+cp_parser_objc_method_definition_list (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ while (token->keyword != RID_AT_END)
+ {
+ tree meth;
+
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+ {
+ push_deferring_access_checks (dk_deferred);
+ objc_start_method_definition
+ (cp_parser_objc_method_signature (parser));
+
+ /* For historical reasons, we accept an optional semicolon. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+
+ perform_deferred_access_checks ();
+ stop_deferring_access_checks ();
+ meth = cp_parser_function_definition_after_declarator (parser,
+ false);
+ pop_deferring_access_checks ();
+ objc_finish_method_definition (meth);
+ }
+ else
+ /* Allow for interspersed non-ObjC++ code. */
+ cp_parser_objc_interstitial_code (parser);
+
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ objc_finish_implementation ();
+}
+
+static void
+cp_parser_objc_class_ivars (cp_parser* parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type != CPP_OPEN_BRACE)
+ return; /* No ivars specified. */
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '{'. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ while (token->type != CPP_CLOSE_BRACE)
+ {
+ cp_decl_specifier_seq declspecs;
+ int decl_class_or_enum_p;
+ tree prefix_attributes;
+
+ cp_parser_objc_visibility_spec (parser);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ break;
+
+ cp_parser_decl_specifier_seq (parser,
+ CP_PARSER_FLAGS_OPTIONAL,
+ &declspecs,
+ &decl_class_or_enum_p);
+ prefix_attributes = declspecs.attributes;
+ declspecs.attributes = NULL_TREE;
+
+ /* Keep going until we hit the `;' at the end of the
+ declaration. */
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ {
+ tree width = NULL_TREE, attributes, first_attribute, decl;
+ cp_declarator *declarator = NULL;
+ int ctor_dtor_or_conv_p;
+
+ /* Check for a (possibly unnamed) bitfield declaration. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_COLON)
+ goto eat_colon;
+
+ if (token->type == CPP_NAME
+ && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
+ == CPP_COLON))
+ {
+ /* Get the name of the bitfield. */
+ declarator = make_id_declarator (NULL_TREE,
+ cp_parser_identifier (parser));
+
+ eat_colon:
+ cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
+ /* Get the width of the bitfield. */
+ width
+ = cp_parser_constant_expression (parser,
+ /*allow_non_constant=*/false,
+ NULL);
+ }
+ else
+ {
+ /* Parse the declarator. */
+ declarator
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+ &ctor_dtor_or_conv_p,
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
+ }
+
+ /* Look for attributes that apply to the ivar. */
+ attributes = cp_parser_attributes_opt (parser);
+ /* Remember which attributes are prefix attributes and
+ which are not. */
+ first_attribute = attributes;
+ /* Combine the attributes. */
+ attributes = chainon (prefix_attributes, attributes);
+
+ if (width)
+ {
+ /* Create the bitfield declaration. */
+ decl = grokbitfield (declarator, &declspecs, width);
+ cplus_decl_attributes (&decl, attributes, /*flags=*/0);
+ }
+ else
+ decl = grokfield (declarator, &declspecs, NULL_TREE,
+ NULL_TREE, attributes);
+
+ /* Add the instance variable. */
+ objc_add_instance_variable (decl);
+
+ /* Reset PREFIX_ATTRIBUTES. */
+ while (attributes && TREE_CHAIN (attributes) != first_attribute)
+ attributes = TREE_CHAIN (attributes);
+ if (attributes)
+ TREE_CHAIN (attributes) = NULL_TREE;
+
+ token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ','. */
+ continue;
+ }
+ break;
+ }
+
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '}'. */
+ /* For historical reasons, we accept an optional semicolon. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+}
+
+static void
+cp_parser_objc_protocol_declaration (cp_parser* parser)
+{
+ tree proto, protorefs;
+ cp_token *tok;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ error ("identifier expected after `@protocol'");
+ goto finish;
+ }
+
+ /* See if we have a foward declaration or a definition. */
+ tok = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+ /* Try a forward declaration first. */
+ if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
+ {
+ objc_declare_protocols (cp_parser_objc_identifier_list (parser));
+ finish:
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+ }
+
+ /* Ok, we got a full-fledged definition (or at least should). */
+ else
+ {
+ proto = cp_parser_identifier (parser);
+ protorefs = cp_parser_objc_protocol_refs_opt (parser);
+ objc_start_protocol (proto, protorefs);
+ cp_parser_objc_method_prototype_list (parser);
+ }
+}
+
+static void
+cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
+ tree *categ)
+{
+ cp_token *next = cp_lexer_peek_token (parser->lexer);
+
+ *super = *categ = NULL_TREE;
+ if (next->type == CPP_COLON)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat ':'. */
+ *super = cp_parser_identifier (parser);
+ }
+ else if (next->type == CPP_OPEN_PAREN)
+ {
+ cp_lexer_consume_token (parser->lexer); /* Eat '('. */
+ *categ = cp_parser_identifier (parser);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ }
+}
+
+static void
+cp_parser_objc_class_interface (cp_parser* parser)
+{
+ tree name, super, categ, protos;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
+ name = cp_parser_identifier (parser);
+ cp_parser_objc_superclass_or_category (parser, &super, &categ);
+ protos = cp_parser_objc_protocol_refs_opt (parser);
+
+ /* We have either a class or a category on our hands. */
+ if (categ)
+ objc_start_category_interface (name, categ, protos);
+ else
+ {
+ objc_start_class_interface (name, super, protos);
+ /* Handle instance variable declarations, if any. */
+ cp_parser_objc_class_ivars (parser);
+ objc_continue_interface ();
+ }
+
+ cp_parser_objc_method_prototype_list (parser);
+}
+
+static void
+cp_parser_objc_class_implementation (cp_parser* parser)
+{
+ tree name, super, categ;
+
+ cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
+ name = cp_parser_identifier (parser);
+ cp_parser_objc_superclass_or_category (parser, &super, &categ);
+
+ /* We have either a class or a category on our hands. */
+ if (categ)
+ objc_start_category_implementation (name, categ);
+ else
+ {
+ objc_start_class_implementation (name, super);
+ /* Handle instance variable declarations, if any. */
+ cp_parser_objc_class_ivars (parser);
+ objc_continue_implementation ();
+ }
+
+ cp_parser_objc_method_definition_list (parser);
+}
+
+static void
+cp_parser_objc_end_implementation (cp_parser* parser)
+{
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ objc_finish_implementation ();
+}
+
+static void
+cp_parser_objc_declaration (cp_parser* parser)
+{
+ /* Try to figure out what kind of declaration is present. */
+ cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+ switch (kwd->keyword)
+ {
+ case RID_AT_ALIAS:
+ cp_parser_objc_alias_declaration (parser);
+ break;
+ case RID_AT_CLASS:
+ cp_parser_objc_class_declaration (parser);
+ break;
+ case RID_AT_PROTOCOL:
+ cp_parser_objc_protocol_declaration (parser);
+ break;
+ case RID_AT_INTERFACE:
+ cp_parser_objc_class_interface (parser);
+ break;
+ case RID_AT_IMPLEMENTATION:
+ cp_parser_objc_class_implementation (parser);
+ break;
+ case RID_AT_END:
+ cp_parser_objc_end_implementation (parser);
+ break;
+ default:
+ error ("misplaced `@%D' Objective-C++ construct", kwd->value);
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ }
+}
+
+/* Parse an Objective-C try-catch-finally statement.
+
+ objc-try-catch-finally-stmt:
+ @try compound-statement objc-catch-clause-seq [opt]
+ objc-finally-clause [opt]
+
+ objc-catch-clause-seq:
+ objc-catch-clause objc-catch-clause-seq [opt]
+
+ objc-catch-clause:
+ @catch ( exception-declaration ) compound-statement
+
+ objc-finally-clause
+ @finally compound-statement
+
+ Returns NULL_TREE. */
+
+static tree
+cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
+ location_t location;
+ tree stmt;
+
+ cp_parser_require_keyword (parser, RID_AT_TRY, "`@try'");
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
+ node, lest it get absorbed into the surrounding block. */
+ stmt = push_stmt_list ();
+ cp_parser_compound_statement (parser, NULL, false);
+ objc_begin_try_stmt (location, pop_stmt_list (stmt));
+
+ while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
+ {
+ cp_parameter_declarator *parmdecl;
+ tree parm;
+
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+ parm = grokdeclarator (parmdecl->declarator,
+ &parmdecl->decl_specifiers,
+ PARM, /*initialized=*/0,
+ /*attrlist=*/NULL);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ objc_begin_catch_clause (parm);
+ cp_parser_compound_statement (parser, NULL, false);
+ objc_finish_catch_clause ();
+ }
+
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST
+ node, lest it get absorbed into the surrounding block. */
+ stmt = push_stmt_list ();
+ cp_parser_compound_statement (parser, NULL, false);
+ objc_build_finally_clause (location, pop_stmt_list (stmt));
+ }
+
+ return objc_finish_try_stmt ();
+}
+
+/* Parse an Objective-C synchronized statement.
+
+ objc-synchronized-stmt:
+ @synchronized ( expression ) compound-statement
+
+ Returns NULL_TREE. */
+
+static tree
+cp_parser_objc_synchronized_statement (cp_parser *parser) {
+ location_t location;
+ tree lock, stmt;
+
+ cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "`@synchronized'");
+
+ location = cp_lexer_peek_token (parser->lexer)->location;
+ cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ lock = cp_parser_expression (parser, false);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
+ node, lest it get absorbed into the surrounding block. */
+ stmt = push_stmt_list ();
+ cp_parser_compound_statement (parser, NULL, false);
+
+ return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
+}
+
+/* Parse an Objective-C throw statement.
+
+ objc-throw-stmt:
+ @throw assignment-expression [opt] ;
+
+ Returns a constructed '@throw' statement. */
+
+static tree
+cp_parser_objc_throw_statement (cp_parser *parser) {
+ tree expr = NULL_TREE;
+
+ cp_parser_require_keyword (parser, RID_AT_THROW, "`@throw'");
+
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ expr = cp_parser_assignment_expression (parser, false);
+
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+ return objc_build_throw_stmt (expr);
+}
+
+static tree
+cp_parser_objc_statement (cp_parser * parser) {
+ /* Try to figure out what kind of declaration is present. */
+ cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+ switch (kwd->keyword)
+ {
+ case RID_AT_TRY:
+ return cp_parser_objc_try_catch_finally_statement (parser);
+ case RID_AT_SYNCHRONIZED:
+ return cp_parser_objc_synchronized_statement (parser);
+ case RID_AT_THROW:
+ return cp_parser_objc_throw_statement (parser);
+ default:
+ error ("misplaced `@%D' Objective-C++ construct", kwd->value);
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ }
+
+ return error_mark_node;
+}
+/* APPLE LOCAL end Objective-C++ */
/* The parser. */