aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-parse.in
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-parse.in')
-rw-r--r--gcc/c-parse.in347
1 files changed, 343 insertions, 4 deletions
diff --git a/gcc/c-parse.in b/gcc/c-parse.in
index fe0d51709eb..27aee72ac4c 100644
--- a/gcc/c-parse.in
+++ b/gcc/c-parse.in
@@ -29,7 +29,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
written by AT&T, but I have never seen it. */
@@ifc
-%expect 13 /* shift/reduce conflicts, and no reduce/reduce conflicts. */
+/* APPLE LOCAL CW asm blocks */
+%expect 15 /* shift/reduce conflicts, and no reduce/reduce conflicts. */
@@end_ifc
%{
@@ -150,6 +151,14 @@ do { \
%token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
%token FUNC_NAME OFFSETOF
+/* APPLE LOCAL begin CW asm blocks */
+/* This token is a pseudo-storage-class. */
+%token CW_ASM_KEYWORD
+%type <ttype> CW_ASM_KEYWORD
+/* These tokens indicate beginning and end of each asm line. */
+%token CW_ASM_BOL CW_ASM_EOL
+/* APPLE LOCAL end CW asm blocks */
+
/* Add precedence rules to solve dangling else s/r conflict */
%nonassoc IF
%nonassoc ELSE
@@ -242,6 +251,17 @@ do { \
%type <arginfotype> parmlist_or_identifiers parmlist_or_identifiers_1
%type <ttype> identifiers_or_typenames
+/* APPLE LOCAL begin CW asm blocks */
+%type <ttype> cw_identifier
+%type <exprtype> cw_asm_expr_no_commas cw_asm_unary_expr
+%type <exprtype> cw_asm_primary
+%type <ttype> cw_asm_operands cw_nonnull_asm_operands
+%type <exprtype> cw_asm_operand
+%type <ttype> cw_asm_stmt single_cw_asm_stmt
+%type <ttype> cw_asm_compstmt cw_asm_compstmt_start
+/*cw_asm_compstmt_nostart */
+/* APPLE LOCAL end CW asm blocks */
+
%type <itype> setspecs setspecs_fp extension
%type <location> save_location
@@ -358,6 +378,8 @@ static int yylexname (void);
static inline int _yylex (void);
static int yylex (void);
static void init_reswords (void);
+/* APPLE LOCAL CW asm blocks */
+static int cw_asm_lineno = 0;
/* Initialization routine for this file. */
void
@@ -683,7 +705,8 @@ primary:
finish_init ();
maybe_warn_string_init (type, init);
- if (pedantic && !flag_isoc99)
+ /* APPLE LOCAL AltiVec */
+ if (pedantic && TREE_CODE (type) != VECTOR_TYPE && !flag_isoc99)
pedwarn ("ISO C90 forbids compound literals");
$$.value = build_compound_literal (type, constructor);
$$.original_code = ERROR_MARK;
@@ -845,7 +868,8 @@ datadecl:
where statement labels are allowed. */
lineno_decl:
save_location decl
- { }
+ /* APPLE LOCAL CW asm blocks */
+ { if (flag_cw_asm_blocks) cw_asm_in_decl = 0; }
;
/* records the type and storage class specs to use for processing
@@ -1419,6 +1443,8 @@ any_word:
scspec:
STATIC
+ /* APPLE LOCAL CW asm blocks */
+ | CW_ASM_KEYWORD
| SCSPEC
;
@@ -2028,6 +2054,11 @@ compstmt_start: '{' { $$ = c_begin_compound_stmt (true); }
compstmt_nostart: '}'
| maybe_label_decls compstmt_contents_nonempty '}'
+ /* APPLE LOCAL begin CW asm blocks */
+ {
+ if (flag_cw_asm_blocks) inside_cw_asm_block = 0;
+ }
+ /* APPLE LOCAL end CW asm blocks */
;
compstmt_contents_nonempty:
@@ -2051,6 +2082,126 @@ compstmt: compstmt_start compstmt_nostart
{ $$ = c_end_compound_stmt ($1, true); }
;
+/* APPLE LOCAL begin CW asm blocks */
+/* A CW-style asm statement is recognized by having a BOL token preceding it. */
+cw_asm_stmt: CW_ASM_BOL save_location cw_asm_stmt_list CW_ASM_EOL
+
+{ $$ = NULL_TREE; }
+ ;
+
+/* A single line may have multiple statements separated by ';'. */
+cw_asm_stmt_list:
+ /* empty */
+ | single_cw_asm_stmt
+ {}
+ | cw_asm_stmt_list ';' single_cw_asm_stmt
+ | cw_asm_stmt_list ';'
+ ;
+
+cw_identifier:
+ identifier
+ | cw_identifier '.'
+ { $$ = cw_get_identifier ($1, "."); }
+ | cw_identifier '+'
+ { $$ = cw_get_identifier ($1, "+"); }
+ | cw_identifier '-'
+ { $$ = cw_get_identifier ($1, "-"); }
+ | '.' identifier
+ { $$ = prepend_char_identifier ($2, '.'); }
+ ;
+
+/* A single statement consists of one or more labels (identified by a
+ leading '@' and/or a trailing ':'), optionally followed by opcode
+ and operands. */
+single_cw_asm_stmt:
+ cw_identifier
+ { cw_asm_lineno = input_line; cw_asm_in_operands = 1; }
+ cw_asm_operands
+ { $$ = cw_asm_stmt ($1, $3, cw_asm_lineno); }
+ | identifier STATIC cw_asm_operand
+ { $$ = cw_asm_entry ($1, $2, $3.value); }
+ | identifier SCSPEC cw_asm_operand
+ { $$ = cw_asm_entry ($1, $2, $3.value); }
+ | cw_asm_label
+ {}
+ | cw_asm_label single_cw_asm_stmt
+ {}
+ ;
+
+cw_asm_label:
+ identifier ':'
+ { cw_asm_label ($1, 0); }
+ | '@' identifier
+ { cw_asm_label ($2, 1); }
+ | '@' identifier ':'
+ { cw_asm_label ($2, 1); }
+ ;
+
+cw_asm_stmts:
+ stmt
+ {}
+ | cw_asm_stmts stmt
+ {}
+ ;
+
+/* An asm block within a function is simpler than asm functions; no
+ declarations are possible, so we switch to the block interior state
+ immediately. */
+cw_asm_compstmt_start: ASM_KEYWORD '{'
+ {
+ if (flag_cw_asm_blocks)
+ {
+ cw_asm_state = cw_asm_asm;
+ inside_cw_asm_block = 1;
+ cw_asm_at_bol = 1;
+ clear_cw_asm_labels ();
+ }
+ else
+ /* This will probably choke badly... */
+ error ("asm blocks not enabled, use `-fasm-blocks'");
+ $$ = c_begin_compound_stmt (true);
+ }
+ ;
+
+cw_asm_compstmt_nostart:
+ '}'
+ | cw_asm_compstmt_contents_nonempty '}'
+ { inside_cw_asm_block = 0; }
+ ;
+
+cw_asm_compstmt_contents_nonempty:
+ cw_asm_stmts
+ | error
+ ;
+
+cw_asm_compstmt: cw_asm_compstmt_start cw_asm_compstmt_nostart
+ { $$ = c_end_compound_stmt ($1, true); }
+ ;
+
+cw_asm_operands:
+ /* empty */
+ { $$ = NULL_TREE; }
+ | cw_nonnull_asm_operands
+ ;
+
+cw_nonnull_asm_operands:
+ cw_asm_operand
+ { $$ = build_tree_list (NULL_TREE, $1.value); }
+ | cw_nonnull_asm_operands ',' cw_asm_operand
+ { $$ = chainon ($1, build_tree_list (NULL_TREE, $3.value)); }
+ ;
+
+/* Alternatively this could go to the regular expr_no_commas, but then
+ all the semantic actions would need to be tweaked to handle the
+ possibility of CW asm coming through. For example, "offset(reg)"
+ would be handled by function call code (bleah). */
+cw_asm_operand: cw_asm_expr_no_commas
+ | cw_asm_operand '(' cw_asm_expr_no_commas ')'
+ { $$.value = cw_asm_build_register_offset ($1.value, $3.value);
+ $$.original_code = ERROR_MARK; }
+ ;
+/* APPLE LOCAL end CW asm blocks */
+
/* The forced readahead in here is because we might be at the end of a
line, and the line and file won't be bumped until yylex absorbs the
first token on the next line. */
@@ -2233,6 +2384,12 @@ stmt_nocomp:
{ $$ = NULL_TREE; }
| switch_statement
{ $$ = NULL_TREE; }
+ /* APPLE LOCAL begin CW asm blocks */
+ | cw_asm_compstmt
+ { $$ = c_finish_expr_stmt ($1); }
+ | cw_asm_stmt
+ { $$ = c_finish_expr_stmt ($1); }
+ /* APPLE LOCAL end CW asm blocks */
| BREAK ';'
{ $$ = c_finish_bc_stmt (&c_break_label, true); }
| CONTINUE ';'
@@ -2441,6 +2598,139 @@ start_string_translation:
{ c_lex_string_translate = 1; }
;
+/* APPLE LOCAL begin CW asm blocks */
+cw_asm_expr_no_commas:
+ cw_asm_unary_expr
+ | cw_asm_expr_no_commas '+' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas '-' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas '*' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas '/' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas '%' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas LSHIFT cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas RSHIFT cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas ARITHCOMPARE cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas EQCOMPARE cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas '&' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas '|' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas '^' cw_asm_expr_no_commas
+ { $$ = parser_build_binary_op ($2, $1, $3); }
+ | cw_asm_expr_no_commas ANDAND
+ { $1.value = c_common_truthvalue_conversion
+ (default_conversion ($1.value));
+ skip_evaluation += $1.value == boolean_false_node; }
+ cw_asm_expr_no_commas
+ { skip_evaluation -= $1.value == boolean_false_node;
+ $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
+ | cw_asm_expr_no_commas OROR
+ { $1.value = c_common_truthvalue_conversion
+ (default_conversion ($1.value));
+ skip_evaluation += $1.value == boolean_true_node; }
+ cw_asm_expr_no_commas
+ { skip_evaluation -= $1.value == boolean_true_node;
+ $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
+ ;
+
+cw_asm_unary_expr:
+ cw_asm_primary
+ | '*' cw_asm_unary_expr %prec UNARY
+ { $$.value = build_indirect_ref ($2.value, "unary *");
+ $$.original_code = ERROR_MARK; }
+ | unop cw_asm_unary_expr %prec UNARY
+ {
+ if (TREE_CODE ($2.value) == COMPOUND_EXPR)
+ {
+ tree neg = build_unary_op ($1, TREE_OPERAND ($2.value, 0), 0);
+ tree reg = TREE_OPERAND ($2.value, 1);
+ $$.value = cw_asm_build_register_offset (neg, reg);
+ }
+ else
+ {
+ $$.value = build_unary_op ($1, $2.value, 0);
+ overflow_warning ($$.value);
+ }
+ $$.original_code = ERROR_MARK;
+ }
+ | sizeof cw_asm_unary_expr %prec UNARY
+ { skip_evaluation--;
+ if (TREE_CODE ($2.value) == COMPONENT_REF
+ && DECL_C_BIT_FIELD (TREE_OPERAND ($2.value, 1)))
+ error ("`sizeof' applied to a bit-field");
+ else if (TREE_CODE ($2.value) == IDENTIFIER_NODE)
+ {
+ undeclared_variable ($2.value);
+ $2.value = error_mark_node;
+ }
+ $$.value = c_sizeof (TREE_TYPE ($2.value));
+ $$.original_code = ERROR_MARK; }
+ | sizeof '(' typename ')' %prec HYPERUNARY
+ { skip_evaluation--;
+ $$.value = c_sizeof (groktypename ($3));
+ $$.original_code = ERROR_MARK; }
+ | alignof cw_asm_unary_expr %prec UNARY
+ { skip_evaluation--;
+ $$.value = c_alignof_expr ($2.value);
+ $$.original_code = ERROR_MARK; }
+ | alignof '(' typename ')' %prec HYPERUNARY
+ { skip_evaluation--;
+ $$.value = c_alignof (groktypename ($3));
+ $$.original_code = ERROR_MARK; }
+ ;
+
+cw_asm_primary:
+ IDENTIFIER
+ {
+ if (yychar == YYEMPTY)
+ yychar = YYLEX;
+ $$.value = build_external_ref ($1, yychar == '(');
+ $$.original_code = ERROR_MARK;
+ }
+ | '@' IDENTIFIER
+ {
+ tree atsignid = prepend_char_identifier ($2, '@');
+ if (yychar == YYEMPTY)
+ yychar = YYLEX;
+ $$.value = build_external_ref (atsignid, yychar == '(');
+ $$.original_code = ERROR_MARK;
+ }
+ | CONSTANT
+ { $$.value = $1; $$.original_code = ERROR_MARK; }
+ | STRING
+ { $$.value = $1; $$.original_code = STRING_CST; }
+ | '(' cw_asm_expr_no_commas ')'
+ { char class = TREE_CODE_CLASS (TREE_CODE ($2.value));
+ if (IS_EXPR_CODE_CLASS (class))
+ $2.original_code = ERROR_MARK;
+ $$ = $2; }
+ | '(' error ')'
+ { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
+ | cw_asm_primary '[' cw_asm_expr_no_commas ']' %prec '.'
+ { $$.value = build_array_ref ($1.value, $3.value);
+ $$.original_code = ERROR_MARK; }
+ | TYPENAME '.' identifier
+ { $$.value = cw_asm_c_build_component_ref ($1, $3);
+ $$.original_code = ERROR_MARK; }
+ | cw_asm_primary '.' identifier
+ { $$.value = cw_asm_c_build_component_ref ($1.value, $3);
+ $$.original_code = ERROR_MARK; }
+ | cw_asm_primary POINTSAT identifier
+ {
+ tree expr = build_indirect_ref ($1.value, "->");
+ $$.value = build_component_ref (expr, $3);
+ $$.original_code = ERROR_MARK;
+ }
+ ;
+/* APPLE LOCAL end CW asm blocks */
/* This is what appears inside the parens in a function declarator.
Its value is a list of ..._TYPE nodes. Attributes must appear here
@@ -3110,6 +3400,8 @@ static const struct resword reswords[] =
{ "__inline", RID_INLINE, 0 },
{ "__inline__", RID_INLINE, 0 },
{ "__label__", RID_LABEL, 0 },
+ /* APPLE LOCAL private extern */
+ { "__private_extern__", RID_PRIVATE_EXTERN, 0 },
{ "__real", RID_REALPART, 0 },
{ "__real__", RID_REALPART, 0 },
{ "__restrict", RID_RESTRICT, 0 },
@@ -3191,9 +3483,12 @@ static const struct resword reswords[] =
};
#define N_reswords (sizeof reswords / sizeof (struct resword))
+/* APPLE LOCAL begin keep tables in sync comment */
/* Table mapping from RID_* constants to yacc token numbers.
Unfortunately we have to have entries for all the keywords in all
- three languages. */
+ three languages (AND THEY MUST BE KEPT IN PARALLEL - see also
+ cp/lex.c). */
+/* APPLE LOCAL end keep tables in sync comment */
static const short rid_to_yy[RID_MAX] =
{
/* RID_STATIC */ STATIC,
@@ -3213,6 +3508,8 @@ static const short rid_to_yy[RID_MAX] =
/* C extensions */
/* RID_COMPLEX */ TYPESPEC,
/* RID_THREAD */ SCSPEC,
+ /* APPLE LOCAL private extern */
+ /* RID_PRIVATE_EXTERN */ SCSPEC,
/* C++ */
/* RID_FRIEND */ 0,
@@ -3373,8 +3670,30 @@ yylexname (void)
&& (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context))
@@end_ifobjc
{
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Outside of function bodies, "asm" either indicates a CW asm
+ function, or a GNU asm statement, which must be immediately
+ followed by '(', so sniff the next token to see which kind
+ must be meant, and change the CW keyword to a different
+ token type so we don't have grammar problems. */
+ int yycode = rid_to_yy[(int) rid_code];
+ if (yycode == ASM_KEYWORD && current_function_decl == NULL)
+ {
+ tree next_tok;
+ /* Take a sneak peek at the next token in the stream. */
+ enum cpp_ttype next_tok_type = c_lex (&next_tok);
+ /* Now put it back. */
+ _cpp_backup_tokens (parse_in, 1);
+ /* Change the code. No need to change the name though,
+ won't matter to parser. */
+ if (next_tok_type != CPP_OPEN_PAREN)
+ yycode = CW_ASM_KEYWORD;
+ }
+ /* APPLE LOCAL end CW asm blocks */
/* Return the canonical spelling for this keyword. */
yylval.ttype = ridpointers[(int) rid_code];
+ /* APPLE LOCAL CW asm blocks */
+ return yycode;
return rid_to_yy[(int) rid_code];
}
}
@@ -3465,6 +3784,17 @@ _yylex (void)
case CPP_CLOSE_PAREN: OBJC_NEED_RAW_IDENTIFIER (0); return ')';
case CPP_SEMICOLON: OBJC_NEED_RAW_IDENTIFIER (0); return ';';
+ /* APPLE LOCAL begin CW asm blocks */
+ case CPP_ATSIGN:
+ /* If we're doing CW assembly, return this as a regular token
+ (indicates labels). */
+ /* If we are not doing CW assembly and this symbol is seen. '@' has
+ not been consumed by the objc-lexer. This maybe because user forgot
+ to specify objc as the language or due to user error. Parser will decide.
+ */
+ return '@';
+ /* APPLE LOCAL end CW asm blocks */
+
case CPP_EOF:
return 0;
@@ -3484,6 +3814,15 @@ _yylex (void)
case CPP_WSTRING:
return STRING;
+ /* APPLE LOCAL begin CW asm blocks */
+ /* Convert a lexer-returned beginning-of-line token into a
+ parser token. */
+ case CPP_BOL:
+ return CW_ASM_BOL;
+ case CPP_EOL:
+ return CW_ASM_EOL;
+ /* APPLE LOCAL end CW asm blocks */
+
case CPP_OBJC_STRING:
return OBJC_STRING;