#include "cpplib.h"
#include "intl.h"
#include "timevar.h"
-#include "c-lex.h"
+#include "c-pragma.h" /* For YYDEBUG definition, and parse_in. */
#include "c-tree.h"
-#include "c-pragma.h"
#include "flags.h"
#include "output.h"
#include "toplev.h"
#include "ggc.h"
-#include "diagnostic.h"
#ifdef MULTIBYTE_CHARS
#include <locale.h>
#include "objc-act.h"
end ifobjc
-/* Since parsers are distinct for each language, put the language string
- definition here. */
-ifobjc
-const char * const language_string = "GNU Objective-C";
-end ifobjc
-ifc
-const char * const language_string = "GNU C";
-end ifc
-
/* Like YYERROR but do call yyerror. */
#define YYERROR1 { yyerror ("syntax error"); YYERROR; }
-/* Cause the "yydebug" variable to be defined. */
-#define YYDEBUG 1
-
-/* Rename the "yyparse" function so that we can override it elsewhere. */
-#define yyparse yyparse_1
+/* Like the default stack expander, except (1) use realloc when possible,
+ (2) impose no hard maxiumum on stack size, (3) REALLY do not use alloca.
+
+ Irritatingly, YYSTYPE is defined after this %{ %} block, so we cannot
+ give malloced_yyvs its proper type. This is ok since all we need from
+ it is to be able to free it. */
+
+static short *malloced_yyss;
+static void *malloced_yyvs;
+
+#define yyoverflow(MSG, SS, SSSIZE, VS, VSSIZE, YYSSZ) \
+do { \
+ size_t newsize; \
+ short *newss; \
+ YYSTYPE *newvs; \
+ newsize = *(YYSSZ) *= 2; \
+ if (malloced_yyss) \
+ { \
+ newss = (short *) \
+ really_call_realloc (*(SS), newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) \
+ really_call_realloc (*(VS), newsize * sizeof (YYSTYPE)); \
+ } \
+ else \
+ { \
+ newss = (short *) really_call_malloc (newsize * sizeof (short)); \
+ newvs = (YYSTYPE *) really_call_malloc (newsize * sizeof (YYSTYPE)); \
+ if (newss) \
+ memcpy (newss, *(SS), (SSSIZE)); \
+ if (newvs) \
+ memcpy (newvs, *(VS), (VSSIZE)); \
+ } \
+ if (!newss || !newvs) \
+ { \
+ yyerror (MSG); \
+ return 2; \
+ } \
+ *(SS) = newss; \
+ *(VS) = newvs; \
+ malloced_yyss = newss; \
+ malloced_yyvs = (void *) newvs; \
+} while (0)
%}
%start program
/* Reserved words that specify storage class.
yylval contains an IDENTIFIER_NODE which indicates which one. */
-%token SCSPEC
+%token SCSPEC /* Storage class other than static. */
+%token STATIC /* Static storage class. */
/* Reserved words that specify type.
yylval contains an IDENTIFIER_NODE which indicates which one. */
%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 <ttype> typespec_reserved_nonattr typespec_reserved_attr
%type <ttype> typespec_nonreserved_nonattr
-%type <ttype> SCSPEC TYPESPEC TYPE_QUAL maybe_type_qual
+%type <ttype> scspec SCSPEC STATIC TYPESPEC TYPE_QUAL maybe_type_qual
%type <ttype> initdecls notype_initdecls initdcl notype_initdcl
%type <ttype> init maybeasm
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
static int if_stmt_line;
/* List of types and structure classes of the current declaration. */
-static tree current_declspecs = NULL_TREE;
-static tree prefix_attributes = NULL_TREE;
+static GTY(()) tree current_declspecs;
+static GTY(()) tree prefix_attributes;
/* List of all the attributes applying to the identifier currently being
declared; includes prefix_attributes and possibly some more attributes
just after a comma. */
-static tree all_prefix_attributes = NULL_TREE;
+static GTY(()) tree all_prefix_attributes;
/* Stack of saved values of current_declspecs, prefix_attributes and
all_prefix_attributes. */
-static tree declspec_stack;
+static GTY(()) tree declspec_stack;
/* PUSH_DECLSPEC_STACK is called from setspecs; POP_DECLSPEC_STACK
should be called from the productions making use of setspecs. */
/* For __extension__, save/restore the warning flags which are
controlled by __extension__. */
-#define SAVE_WARN_FLAGS() \
- size_int (pedantic | (warn_pointer_arith << 1))
-#define RESTORE_WARN_FLAGS(tval) \
- do { \
- int val = tree_low_cst (tval, 0); \
- pedantic = val & 1; \
- warn_pointer_arith = (val >> 1) & 1; \
+#define SAVE_EXT_FLAGS() \
+ size_int (pedantic \
+ | (warn_pointer_arith << 1) \
+ | (warn_traditional << 2) \
+ | (flag_iso << 3))
+
+#define RESTORE_EXT_FLAGS(tval) \
+ do { \
+ int val = tree_low_cst (tval, 0); \
+ pedantic = val & 1; \
+ warn_pointer_arith = (val >> 1) & 1; \
+ warn_traditional = (val >> 2) & 1; \
+ flag_iso = (val >> 3) & 1; \
} while (0)
ifobjc
static void yyprint PARAMS ((FILE *, int, YYSTYPE));
static void yyerror PARAMS ((const char *));
static int yylexname PARAMS ((void));
+static int yylexstring PARAMS ((void));
static inline int _yylex PARAMS ((void));
static int yylex PARAMS ((void));
static void init_reswords PARAMS ((void));
-/* Add GC roots for variables local to this file. */
+ /* Initialisation routine for this file. */
void
c_parse_init ()
{
- ggc_add_tree_root (&declspec_stack, 1);
- ggc_add_tree_root (¤t_declspecs, 1);
- ggc_add_tree_root (&prefix_attributes, 1);
- ggc_add_tree_root (&all_prefix_attributes, 1);
+ init_reswords ();
}
%}
get us back to the global binding level. */
while (! global_bindings_p ())
poplevel (0, 0, 0);
-ifc
+ /* __FUNCTION__ is defined at file scope (""). This
+ call may not be necessary as my tests indicate it
+ still works without it. */
finish_fname_decls ();
-end ifc
finish_file ();
}
;
else
error ("argument of `asm' is not a constant string"); }
| extension extdef
- { RESTORE_WARN_FLAGS ($1); }
+ { RESTORE_EXT_FLAGS ($1); }
;
datadef:
setspecs notype_initdecls ';'
{ if (pedantic)
error ("ISO C forbids data definition with no type or storage class");
- else if (!flag_traditional)
+ else
warning ("data definition has no type or storage class");
POP_DECLSPEC_STACK; }
save_filename save_lineno compstmt_or_error
{ DECL_SOURCE_FILE (current_function_decl) = $7;
DECL_SOURCE_LINE (current_function_decl) = $8;
- finish_function (0);
+ finish_function (0, 1);
POP_DECLSPEC_STACK; }
| declspecs_ts setspecs declarator error
{ POP_DECLSPEC_STACK; }
save_filename save_lineno compstmt_or_error
{ DECL_SOURCE_FILE (current_function_decl) = $7;
DECL_SOURCE_LINE (current_function_decl) = $8;
- finish_function (0);
+ finish_function (0, 1);
POP_DECLSPEC_STACK; }
| declspecs_nots setspecs notype_declarator error
{ POP_DECLSPEC_STACK; }
save_filename save_lineno compstmt_or_error
{ DECL_SOURCE_FILE (current_function_decl) = $6;
DECL_SOURCE_LINE (current_function_decl) = $7;
- finish_function (0);
+ finish_function (0, 1);
POP_DECLSPEC_STACK; }
| setspecs notype_declarator error
{ POP_DECLSPEC_STACK; }
/* __extension__ turns off -pedantic for following primary. */
| extension cast_expr %prec UNARY
{ $$ = $2;
- RESTORE_WARN_FLAGS ($1); }
+ RESTORE_EXT_FLAGS ($1); }
| unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0);
overflow_warning ($$); }
| expr_no_commas '^' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas ANDAND
- { $1 = truthvalue_conversion (default_conversion ($1));
+ { $1 = c_common_truthvalue_conversion
+ (default_conversion ($1));
skip_evaluation += $1 == boolean_false_node; }
expr_no_commas
{ skip_evaluation -= $1 == boolean_false_node;
$$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
| expr_no_commas OROR
- { $1 = truthvalue_conversion (default_conversion ($1));
+ { $1 = c_common_truthvalue_conversion
+ (default_conversion ($1));
skip_evaluation += $1 == boolean_true_node; }
expr_no_commas
{ skip_evaluation -= $1 == boolean_true_node;
$$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
| expr_no_commas '?'
- { $1 = truthvalue_conversion (default_conversion ($1));
+ { $1 = c_common_truthvalue_conversion
+ (default_conversion ($1));
skip_evaluation += $1 == boolean_false_node; }
expr ':'
{ skip_evaluation += (($1 == boolean_true_node)
pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
/* Make sure first operand is calculated only once. */
$<ttype>2 = save_expr ($1);
- $1 = truthvalue_conversion (default_conversion ($<ttype>2));
+ $1 = c_common_truthvalue_conversion
+ (default_conversion ($<ttype>2));
skip_evaluation += $1 == boolean_true_node; }
':' expr_no_commas
{ skip_evaluation -= $1 == boolean_true_node;
| expr_no_commas ASSIGN expr_no_commas
{ char class;
$$ = build_modify_expr ($1, $2, $3);
- /* This inhibits warnings in truthvalue_conversion. */
+ /* This inhibits warnings in
+ c_common_truthvalue_conversion. */
class = TREE_CODE_CLASS (TREE_CODE ($$));
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
$$ = build_external_ref ($1, yychar == '(');
}
| CONSTANT
- | string
- { $$ = combine_strings ($1); }
+ | STRING
+ { $$ = fix_string_type ($$); }
| 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. */
| declspecs ';'
{ shadow_tag ($1); }
| extension decl
- { RESTORE_WARN_FLAGS ($1); }
+ { RESTORE_EXT_FLAGS ($1); }
;
/* A list of declaration specifiers. These are:
- - Storage class specifiers (SCSPEC), which for GCC currently include
+ - Storage class specifiers (scspec), which for GCC currently includes
function specifiers ("inline").
- Type specifiers (typespec_*).
;
declspecs_sc_nots_nosa_noea:
- SCSPEC
+ scspec
{ $$ = tree_cons (NULL_TREE, $1, NULL_TREE);
TREE_STATIC ($$) = 0; }
| declspecs_sc_nots_nosa_noea TYPE_QUAL
| declspecs_sc_nots_nosa_ea TYPE_QUAL
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_nots_nosa_noea SCSPEC
+ | declspecs_nosc_nots_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_nots_nosa_ea SCSPEC
+ | declspecs_nosc_nots_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_nosa_noea SCSPEC
+ | declspecs_sc_nots_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_nosa_ea SCSPEC
+ | declspecs_sc_nots_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
| declspecs_sc_nots_sa_ea TYPE_QUAL
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_nots_sa_noea SCSPEC
+ | declspecs_nosc_nots_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_nots_sa_ea SCSPEC
+ | declspecs_nosc_nots_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_sa_noea SCSPEC
+ | declspecs_sc_nots_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_nots_sa_ea SCSPEC
+ | declspecs_sc_nots_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
| declspecs_sc_nots_nosa_ea typespec_nonattr
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_ts_nosa_noea SCSPEC
+ | declspecs_nosc_ts_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_ts_nosa_ea SCSPEC
+ | declspecs_nosc_ts_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_nosa_noea SCSPEC
+ | declspecs_sc_ts_nosa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_nosa_ea SCSPEC
+ | declspecs_sc_ts_nosa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
| declspecs_sc_nots_sa_ea typespec_nonattr
{ $$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = 1; }
- | declspecs_nosc_ts_sa_noea SCSPEC
+ | declspecs_nosc_ts_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_nosc_ts_sa_ea SCSPEC
+ | declspecs_nosc_ts_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_sa_noea SCSPEC
+ | declspecs_sc_ts_sa_noea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = tree_cons (NULL_TREE, $2, $1);
TREE_STATIC ($$) = TREE_STATIC ($1); }
- | declspecs_sc_ts_sa_ea SCSPEC
+ | declspecs_sc_ts_sa_ea scspec
{ if (extra_warnings && TREE_STATIC ($1))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
maybeasm:
/* empty */
{ $$ = NULL_TREE; }
- | ASM_KEYWORD '(' string ')'
- { if (TREE_CHAIN ($3)) $3 = combine_strings ($3);
- $$ = $3;
- }
+ | ASM_KEYWORD '(' STRING ')'
+ { $$ = $3; }
;
initdcl:
any_word:
identifier
- | SCSPEC
+ | scspec
| TYPESPEC
| TYPE_QUAL
;
+
+scspec:
+ STATIC
+ | SCSPEC
+ ;
\f
/* Initializers. `init' is the entry point. */
{ tree decl = current_function_decl;
DECL_SOURCE_FILE (decl) = $5;
DECL_SOURCE_LINE (decl) = $6;
- finish_function (1);
+ finish_function (1, 1);
pop_function_context ();
add_decl_stmt (decl); }
;
{ tree decl = current_function_decl;
DECL_SOURCE_FILE (decl) = $5;
DECL_SOURCE_LINE (decl) = $6;
- finish_function (1);
+ finish_function (1, 1);
pop_function_context ();
add_decl_stmt (decl); }
;
$$ = get_class_ivars (interface);
else
{
- error ("Cannot find interface declaration for `%s'",
+ error ("cannot find interface declaration for `%s'",
IDENTIFIER_POINTER ($3));
$$ = NULL_TREE;
}
{ $$ = NULL_TREE; }
| extension component_decl
{ $$ = $2;
- RESTORE_WARN_FLAGS ($1); }
+ RESTORE_EXT_FLAGS ($1); }
;
components:
typename:
declspecs_nosc
- { tree specs, attrs;
- pending_xref_error ();
- split_specs_attrs ($1, &specs, &attrs);
- /* We don't yet support attributes here. */
- if (attrs != NULL_TREE)
- warning ("attributes on type name ignored");
- $<ttype>$ = specs; }
+ { pending_xref_error ();
+ $<ttype>$ = $1; }
absdcl
{ $$ = build_tree_list ($<ttype>2, $3); }
;
/* The [...] part of a declarator for an array type. */
array_declarator:
- '[' expr ']'
- { $$ = build_array_declarator ($2, NULL_TREE, 0, 0); }
- | '[' declspecs_nosc expr ']'
+ '[' maybe_type_quals_attrs expr ']'
{ $$ = build_array_declarator ($3, $2, 0, 0); }
- | '[' ']'
- { $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 0); }
- | '[' declspecs_nosc ']'
+ | '[' maybe_type_quals_attrs ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
- | '[' '*' ']'
- { $$ = build_array_declarator (NULL_TREE, NULL_TREE, 0, 1); }
- | '[' declspecs_nosc '*' ']'
+ | '[' maybe_type_quals_attrs '*' ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
- | '[' SCSPEC expr ']'
- { if (C_RID_CODE ($2) != RID_STATIC)
- error ("storage class specifier in array declarator");
- $$ = build_array_declarator ($3, NULL_TREE, 1, 0); }
- | '[' SCSPEC declspecs_nosc expr ']'
- { if (C_RID_CODE ($2) != RID_STATIC)
- error ("storage class specifier in array declarator");
- $$ = build_array_declarator ($4, $3, 1, 0); }
- | '[' declspecs_nosc SCSPEC expr ']'
- { if (C_RID_CODE ($3) != RID_STATIC)
- error ("storage class specifier in array declarator");
- $$ = build_array_declarator ($4, $2, 1, 0); }
+ | '[' STATIC maybe_type_quals_attrs expr ']'
+ { $$ = build_array_declarator ($4, $3, 1, 0); }
+ /* declspecs_nosc_nots is a synonym for type_quals_attrs. */
+ | '[' declspecs_nosc_nots STATIC expr ']'
+ { $$ = build_array_declarator ($4, $2, 1, 0); }
;
/* A nonempty series of declarations and statements (possibly followed by
poplevel: /* empty */
{ $$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); }
+ ;
/* Start and end blocks created for the new scopes of C99. */
c99_block_start: /* empty */
;
compstmt_start: '{' { compstmt_count++;
- $$ = c_begin_compound_stmt (); }
+ $$ = c_begin_compound_stmt (); }
+ ;
compstmt_nostart: '}'
{ $$ = convert (void_type_node, integer_zero_node); }
compstmt_count++;
$$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
}
+ ;
compstmt: compstmt_start compstmt_nostart
{ RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
+ last_expr_type = NULL_TREE;
$$ = $1; }
;
;
if_prefix:
- IF '(' expr ')'
- { c_expand_start_cond (truthvalue_conversion ($3),
- compstmt_count);
+ /* We must build the IF_STMT node before parsing its
+ condition so that STMT_LINENO refers to the line
+ containing the "if", and not the line containing
+ the close-parenthesis.
+
+ c_begin_if_stmt returns the IF_STMT node, which
+ we later pass to c_expand_start_cond to fill
+ in the condition and other tidbits. */
+ IF
+ { $<ttype>$ = c_begin_if_stmt (); }
+ '(' expr ')'
+ { c_expand_start_cond (c_common_truthvalue_conversion ($4),
+ compstmt_count,$<ttype>2);
$<itype>$ = stmt_count;
if_stmt_file = $<filename>-2;
if_stmt_line = $<lineno>-1; }
- ;
+ ;
/* This is a subroutine of stmt.
It is used twice, once for valid DO statements
Otherwise a crash is likely. */
| simple_if ELSE error
{ c_expand_end_cond (); }
+ /* We must build the WHILE_STMT node before parsing its
+ condition so that STMT_LINENO refers to the line
+ containing the "while", and not the line containing
+ the close-parenthesis.
+
+ c_begin_while_stmt returns the WHILE_STMT node, which
+ we later pass to c_finish_while_stmt_cond to fill
+ in the condition and other tidbits. */
| WHILE
- { stmt_count++; }
+ { stmt_count++;
+ $<ttype>$ = c_begin_while_stmt (); }
'(' expr ')'
- { $4 = truthvalue_conversion ($4);
- $<ttype>$
- = add_stmt (build_stmt (WHILE_STMT, $4, NULL_TREE)); }
+ { $4 = c_common_truthvalue_conversion ($4);
+ c_finish_while_stmt_cond
+ (c_common_truthvalue_conversion ($4), $<ttype>2);
+ $<ttype>$ = add_stmt ($<ttype>2); }
c99_block_lineno_labeled_stmt
{ RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
| do_stmt_start
'(' expr ')' ';'
- { DO_COND ($1) = truthvalue_conversion ($3); }
+ { DO_COND ($1) = c_common_truthvalue_conversion ($3); }
| do_stmt_start error
{ }
| FOR
RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
xexpr ';'
{ if ($6)
- FOR_COND ($<ttype>2) = truthvalue_conversion ($6); }
+ FOR_COND ($<ttype>2)
+ = c_common_truthvalue_conversion ($6); }
xexpr ')'
{ FOR_EXPR ($<ttype>2) = $9; }
c99_block_lineno_labeled_stmt
STRING '(' expr ')'
{ $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $3); }
| '[' identifier ']' STRING '(' expr ')'
- { $$ = build_tree_list (build_tree_list ($2, $4), $6); }
+ { $2 = build_string (IDENTIFIER_LENGTH ($2),
+ IDENTIFIER_POINTER ($2));
+ $$ = build_tree_list (build_tree_list ($2, $4), $6); }
;
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.
where either a parmlist or an identifier list is ok.
Its value is a list of ..._TYPE nodes or a list of identifiers. */
parmlist_or_identifiers:
+ maybe_attribute
{ pushlevel (0);
clear_parm_order ();
declare_parm_level (1); }
parmlist_or_identifiers_1
- { $$ = $2;
+ { $$ = $3;
parmlist_tags_warning ();
poplevel (0, 0, 0); }
;
for (t = $1; t; t = TREE_CHAIN (t))
if (TREE_VALUE (t) == NULL_TREE)
error ("`...' in old-style identifier list");
- $$ = tree_cons (NULL_TREE, NULL_TREE, $1); }
+ $$ = tree_cons (NULL_TREE, NULL_TREE, $1);
+
+ /* Make sure we have a parmlist after attributes. */
+ if ($<ttype>-1 != 0
+ && (TREE_CODE ($$) != TREE_LIST
+ || TREE_PURPOSE ($$) == 0
+ || TREE_CODE (TREE_PURPOSE ($$)) != PARM_DECL))
+ YYERROR1;
+ }
;
/* A nonempty list of identifiers. */
extension:
EXTENSION
- { $$ = SAVE_WARN_FLAGS();
+ { $$ = SAVE_EXT_FLAGS();
pedantic = 0;
- warn_pointer_arith = 0; }
+ warn_pointer_arith = 0;
+ warn_traditional = 0;
+ flag_iso = 0; }
;
\f
ifobjc
/* Disable mask. Keywords are disabled if (reswords[i].disable & mask) is
_true_. */
-#define D_TRAD 0x01 /* not in traditional C */
-#define D_C89 0x02 /* not in C89 */
-#define D_EXT 0x04 /* GCC extension */
-#define D_EXT89 0x08 /* GCC extension incorporated in C99 */
-#define D_OBJC 0x10 /* Objective C only */
+#define D_C89 0x01 /* not in C89 */
+#define D_EXT 0x02 /* GCC extension */
+#define D_EXT89 0x04 /* GCC extension incorporated in C99 */
+#define D_OBJC 0x08 /* Objective C only */
static const struct resword reswords[] =
{
{ "__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 },
{ "__restrict__", RID_RESTRICT, 0 },
{ "__signed", RID_SIGNED, 0 },
{ "__signed__", RID_SIGNED, 0 },
+ { "__thread", RID_THREAD, 0 },
{ "__typeof", RID_TYPEOF, 0 },
{ "__typeof__", RID_TYPEOF, 0 },
{ "__unbounded", RID_UNBOUNDED, 0 },
{ "break", RID_BREAK, 0 },
{ "case", RID_CASE, 0 },
{ "char", RID_CHAR, 0 },
- { "const", RID_CONST, D_TRAD },
+ { "const", RID_CONST, 0 },
{ "continue", RID_CONTINUE, 0 },
{ "default", RID_DEFAULT, 0 },
{ "do", RID_DO, 0 },
{ "for", RID_FOR, 0 },
{ "goto", RID_GOTO, 0 },
{ "if", RID_IF, 0 },
- { "inline", RID_INLINE, D_TRAD|D_EXT89 },
+ { "inline", RID_INLINE, D_EXT89 },
{ "int", RID_INT, 0 },
{ "long", RID_LONG, 0 },
{ "register", RID_REGISTER, 0 },
- { "restrict", RID_RESTRICT, D_TRAD|D_C89 },
+ { "restrict", RID_RESTRICT, D_C89 },
{ "return", RID_RETURN, 0 },
{ "short", RID_SHORT, 0 },
- { "signed", RID_SIGNED, D_TRAD },
+ { "signed", RID_SIGNED, 0 },
{ "sizeof", RID_SIZEOF, 0 },
{ "static", RID_STATIC, 0 },
{ "struct", RID_STRUCT, 0 },
{ "switch", RID_SWITCH, 0 },
{ "typedef", RID_TYPEDEF, 0 },
- { "typeof", RID_TYPEOF, D_TRAD|D_EXT },
+ { "typeof", RID_TYPEOF, D_EXT },
{ "union", RID_UNION, 0 },
{ "unsigned", RID_UNSIGNED, 0 },
{ "void", RID_VOID, 0 },
- { "volatile", RID_VOLATILE, D_TRAD },
+ { "volatile", RID_VOLATILE, 0 },
{ "while", RID_WHILE, 0 },
ifobjc
{ "id", RID_ID, D_OBJC },
three languages. */
static const short rid_to_yy[RID_MAX] =
{
- /* RID_STATIC */ SCSPEC,
+ /* RID_STATIC */ STATIC,
/* RID_UNSIGNED */ TYPESPEC,
/* RID_LONG */ TYPESPEC,
/* RID_CONST */ TYPE_QUAL,
/* RID_BOUNDED */ TYPE_QUAL,
/* RID_UNBOUNDED */ TYPE_QUAL,
/* RID_COMPLEX */ TYPESPEC,
+ /* RID_THREAD */ SCSPEC,
/* C++ */
/* RID_FRIEND */ 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,
unsigned int i;
tree id;
int mask = (flag_isoc99 ? 0 : D_C89)
- | (flag_traditional ? D_TRAD : 0)
| (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0);
if (c_language != clk_objective_c)
}
}
-const char *
-init_parse (filename)
- const char *filename;
-{
- add_c_tree_codes ();
-
- /* Make identifier nodes long enough for the language-specific slots. */
- set_identifier_size (sizeof (struct lang_identifier));
-
- init_reswords ();
- init_pragma ();
-
- return init_c_lex (filename);
-}
-
-void
-finish_parse ()
-{
- cpp_finish (parse_in);
- /* Call to cpp_destroy () omitted for performance reasons. */
- errorcount += cpp_errors (parse_in);
-}
-
#define NAME(type) cpp_type2name (type)
static void
const char *name = fname_string (rid_code);
yylval.ttype = build_string (strlen (name) + 1, name);
+ C_ARTIFICIAL_STRING_P (yylval.ttype) = 1;
last_token = CPP_STRING; /* so yyerror won't choke */
return STRING;
}
return IDENTIFIER;
}
+/* Concatenate strings before returning them to the parser. This isn't quite
+ as good as having it done in the lexer, but it's better than nothing. */
+
+static int
+yylexstring ()
+{
+ enum cpp_ttype next_type;
+ tree orig = yylval.ttype;
+
+ next_type = c_lex (&yylval.ttype);
+ if (next_type == CPP_STRING
+ || next_type == CPP_WSTRING
+ || (next_type == CPP_NAME && yylexname () == STRING))
+ {
+ varray_type strings;
+
+ifc
+ static int last_lineno = 0;
+ static const char *last_input_filename = 0;
+ 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
+
+ VARRAY_TREE_INIT (strings, 32, "strings");
+ VARRAY_PUSH_TREE (strings, orig);
+
+ do
+ {
+ VARRAY_PUSH_TREE (strings, yylval.ttype);
+ next_type = c_lex (&yylval.ttype);
+ }
+ while (next_type == CPP_STRING
+ || next_type == CPP_WSTRING
+ || (next_type == CPP_NAME && yylexname () == STRING));
+
+ yylval.ttype = combine_strings (strings);
+ }
+ else
+ yylval.ttype = orig;
+
+ /* We will have always read one token too many. */
+ _cpp_backup_tokens (parse_in, 1);
+
+ return STRING;
+}
static inline int
_yylex ()
return 0;
case CPP_NAME:
- return yylexname ();
+ {
+ int ret = yylexname ();
+ if (ret == STRING)
+ return yylexstring ();
+ else
+ return ret;
+ }
case CPP_NUMBER:
case CPP_CHAR:
case CPP_STRING:
case CPP_WSTRING:
- return STRING;
+ return yylexstring ();
/* This token is Objective-C specific. It gives the next token
special significance. */
return r;
}
-/* Sets the value of the 'yydebug' variable to VALUE.
- This is a function so we don't have to have YYDEBUG defined
- in order to build the compiler. */
-
-void
-set_yydebug (value)
- int value;
-{
-#if YYDEBUG != 0
- yydebug = value;
-#else
- warning ("YYDEBUG not defined.");
-#endif
-}
-
/* Function used when yydebug is set, to print a token in more detail. */
static void
case TYPESPEC:
case TYPE_QUAL:
case SCSPEC:
+ case STATIC:
if (IDENTIFIER_POINTER (t))
fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
break;
/* This is not the ideal place to put these, but we have to get them out
of c-lex.c because cp/lex.c has its own versions. */
-/* Return something to represent absolute declarators containing a *.
- TARGET is the absolute declarator that the * contains.
- TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
- to apply to the pointer type, represented as identifiers, possible mixed
- with attributes.
-
- We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
- if attributes are present) and whose type is the modifier list. */
+/* Free malloced parser stacks if necessary. */
-tree
-make_pointer_declarator (type_quals_attrs, target)
- tree type_quals_attrs, target;
+void
+free_parser_stacks ()
{
- tree quals, attrs;
- tree itarget = target;
- split_specs_attrs (type_quals_attrs, &quals, &attrs);
- if (attrs != NULL_TREE)
- itarget = tree_cons (attrs, target, NULL_TREE);
- return build1 (INDIRECT_REF, quals, itarget);
+ if (malloced_yyss)
+ {
+ free (malloced_yyss);
+ free (malloced_yyvs);
+ }
}
+
+#include "gt-c-parse.h"