yylval is the node for the constant. */
%token CONSTANT
-/* String constants in raw form.
- yylval is a STRING_CST node. */
-%token STRING
+/* A STRING_CST with type an array of the appropriate character type. */
+%token STRING OBJC_STRING
/* "...", used for functions with variable arglists. */
%token ELLIPSIS
%token SIZEOF ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
%token BREAK CONTINUE RETURN GOTO ASM_KEYWORD TYPEOF ALIGNOF
%token ATTRIBUTE EXTENSION LABEL
-%token REALPART IMAGPART VA_ARG
+%token REALPART IMAGPART VA_ARG CHOOSE_EXPR TYPES_COMPATIBLE_P
%token PTR_VALUE PTR_BASE PTR_EXTENT
/* function name can be a string const or a var decl. */
%type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
-%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
+%type <ttype> expr_no_commas cast_expr unary_expr primary STRING
%type <ttype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea
%type <ttype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea
%type <ttype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
%type <lineno> save_lineno
\f
ifobjc
+%token OBJC_STRING
+
/* the Objective-C nonterminals */
%type <ttype> ivar_decl_list ivar_decls ivar_decl ivars ivar_declarator
%type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
%type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
-%type <ttype> CLASSNAME OBJECTNAME
+%type <ttype> CLASSNAME OBJECTNAME OBJC_STRING
end ifobjc
\f
%{
ifobjc
| objcdef
end ifobjc
- | ASM_KEYWORD '(' expr ')' ';'
- { STRIP_NOPS ($3);
- if ((TREE_CODE ($3) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND ($3, 0)) == STRING_CST)
- || TREE_CODE ($3) == STRING_CST)
- assemble_asm ($3);
- else
- error ("argument of `asm' is not a constant string"); }
+ | ASM_KEYWORD '(' STRING ')' ';'
+ { assemble_asm ($3); }
| extension extdef
{ RESTORE_WARN_FLAGS ($1); }
;
$$ = build_external_ref ($1, yychar == '(');
}
| CONSTANT
- | string
- { $$ = combine_strings ($1); }
+ | STRING
+ { $$ = $1; }
| VAR_FUNC_NAME
{ $$ = fname_decl (C_RID_CODE ($$), $$); }
| '(' typename ')' '{'
$2 = groktypename ($2);
really_start_incremental_init ($2); }
initlist_maybe_comma '}' %prec UNARY
- { const char *name;
- tree result = pop_init_level (0);
+ { tree constructor = pop_init_level (0);
tree type = $2;
finish_init ();
if (pedantic && ! flag_isoc99)
pedwarn ("ISO C89 forbids compound literals");
- if (TYPE_NAME (type) != 0)
- {
- if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
- name = IDENTIFIER_POINTER (TYPE_NAME (type));
- else
- name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
- }
- else
- name = "";
- $$ = result;
- if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
- {
- int failure = complete_array_type (type, $$, 1);
- if (failure)
- abort ();
- }
+ $$ = build_compound_literal (type, constructor);
}
| '(' expr ')'
{ char class = TREE_CODE_CLASS (TREE_CODE ($2));
{ $$ = build_function_call ($1, $3); }
| VA_ARG '(' expr_no_commas ',' typename ')'
{ $$ = build_va_arg ($3, groktypename ($5)); }
+ | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' expr_no_commas ')'
+ {
+ tree c;
+
+ c = fold ($3);
+ STRIP_NOPS (c);
+ if (TREE_CODE (c) != INTEGER_CST)
+ error ("first argument to __builtin_choose_expr not a constant");
+ $$ = integer_zerop (c) ? $7 : $5;
+ }
+ | TYPES_COMPATIBLE_P '(' typename ',' typename ')'
+ {
+ tree e1, e2;
+
+ e1 = TYPE_MAIN_VARIANT (groktypename ($3));
+ e2 = TYPE_MAIN_VARIANT (groktypename ($5));
+
+ $$ = comptypes (e1, e2)
+ ? build_int_2 (1, 0) : build_int_2 (0, 0);
+ }
| primary '[' expr ']' %prec '.'
{ $$ = build_array_ref ($1, $3); }
| primary '.' identifier
end ifobjc
;
-/* Produces a STRING_CST with perhaps more STRING_CSTs chained onto it. */
-string:
- STRING
- | string STRING
- {
-ifc
- static int last_lineno = 0;
- static const char *last_input_filename = 0;
-end ifc
- $$ = chainon ($1, $2);
-ifc
- if (warn_traditional && !in_system_header
- && (lineno != last_lineno || !last_input_filename ||
- strcmp (last_input_filename, input_filename)))
- {
- warning ("traditional C rejects string concatenation");
- last_lineno = lineno;
- last_input_filename = input_filename;
- }
-end ifc
- }
- ;
-
ifobjc
-/* Produces an STRING_CST with perhaps more STRING_CSTs chained
- onto it, which is to be read as an ObjC string object. */
+/* Chains ObjC string objects together. */
objc_string:
- '@' STRING
- { $$ = $2; }
- | objc_string '@' STRING
- { $$ = chainon ($1, $3); }
+ OBJC_STRING
+ { $$ = $1; }
+ | objc_string OBJC_STRING
+ { $$ = chainon ($1, $2); }
;
end ifobjc
maybeasm:
/* empty */
{ $$ = NULL_TREE; }
- | ASM_KEYWORD '(' string ')'
- { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
- $$ = $3;
- }
+ | ASM_KEYWORD '(' STRING ')'
+ { $$ = $3; }
;
initdcl:
$$ = get_class_ivars (interface);
else
{
- error ("Cannot find interface declaration for `%s'",
+ error ("cannot find interface declaration for `%s'",
IDENTIFIER_POINTER ($3));
$$ = NULL_TREE;
}
| RETURN expr ';'
{ stmt_count++;
$$ = c_expand_return ($2); }
- | ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
+ | ASM_KEYWORD maybe_type_qual '(' STRING ')' ';'
{ stmt_count++;
$$ = simple_asm_stmt ($4); }
/* This is the case with just output operands. */
- | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
+ | ASM_KEYWORD maybe_type_qual '(' STRING ':' asm_operands ')' ';'
{ stmt_count++;
$$ = build_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
/* This is the case with input operands as well. */
- | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
+ | ASM_KEYWORD maybe_type_qual '(' STRING ':' asm_operands ':'
asm_operands ')' ';'
{ stmt_count++;
$$ = build_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
/* This is the case with clobbered registers as well. */
- | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
+ | ASM_KEYWORD maybe_type_qual '(' STRING ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
{ stmt_count++;
$$ = build_asm_stmt ($2, $4, $6, $8, $10); }
;
asm_clobbers:
- string
- { $$ = tree_cons (NULL_TREE, combine_strings ($1), NULL_TREE); }
- | asm_clobbers ',' string
- { $$ = tree_cons (NULL_TREE, combine_strings ($3), $1); }
+ STRING
+ { $$ = tree_cons (NULL_TREE, $1, NULL_TREE); }
+ | asm_clobbers ',' STRING
+ { $$ = tree_cons (NULL_TREE, $3, $1); }
;
\f
/* This is what appears inside the parens in a function declarator.
{ "__attribute__", RID_ATTRIBUTE, 0 },
{ "__bounded", RID_BOUNDED, 0 },
{ "__bounded__", RID_BOUNDED, 0 },
+ { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
+ { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
{ "__builtin_va_arg", RID_VA_ARG, 0 },
{ "__complex", RID_COMPLEX, 0 },
{ "__complex__", RID_COMPLEX, 0 },
/* RID_PTREXTENT */ PTR_EXTENT,
/* RID_PTRVALUE */ PTR_VALUE,
+ /* RID_CHOOSE_EXPR */ CHOOSE_EXPR,
+ /* RID_TYPES_COMPATIBLE_P */ TYPES_COMPATIBLE_P,
+
/* RID_FUNCTION_NAME */ STRING_FUNC_NAME,
/* RID_PRETTY_FUNCTION_NAME */ STRING_FUNC_NAME,
/* RID_C99_FUNCTION_NAME */ VAR_FUNC_NAME,
to string constants. */
const char *name = fname_string (rid_code);
- yylval.ttype = build_string (strlen (name) + 1, name);
+ yylval.ttype
+ = combine_strings (build_string (strlen (name) + 1, name));
last_token = CPP_STRING; /* so yyerror won't choke */
return STRING;
}
special significance. */
case CPP_ATSIGN:
ifobjc
- {
- tree after_at;
- enum cpp_ttype after_at_type;
+ last_token = c_lex (&yylval.ttype);
- after_at_type = c_lex (&after_at);
+ if (last_token == CPP_NAME
+ && C_IS_RESERVED_WORD (yylval.ttype)
+ && OBJC_IS_AT_KEYWORD (C_RID_CODE (yylval.ttype)))
+ return rid_to_yy [(int) C_RID_CODE (yylval.ttype)];
+ else if (last_token == CPP_STRING || last_token == CPP_WSTRING)
+ return OBJC_STRING;
- if (after_at_type == CPP_NAME
- && C_IS_RESERVED_WORD (after_at)
- && OBJC_IS_AT_KEYWORD (C_RID_CODE (after_at)))
- {
- yylval.ttype = after_at;
- last_token = after_at_type;
- return rid_to_yy [(int) C_RID_CODE (after_at)];
- }
- _cpp_backup_tokens (parse_in, 1);
- return '@';
- }
+ /* Fall through... */
end ifobjc
/* These tokens are C++ specific (and will not be generated