@@ -51,7 +51,8 @@ CFLAGS-c/gccspec.o += $(DRIVER_DEFINES)
# Language-specific object files for C and Objective C.
C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
- c/c-array-notation.o c/c-fold.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
+ c/c-array-notation.o c/c-fold.o c/gimple-parser.o \
+ $(C_COMMON_OBJS) $(C_TARGET_OBJS)
# Language-specific object files for C.
C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
@@ -25,6 +25,8 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "langhooks-def.h"
#include "c-objc-common.h"
+#include "c-family/c-pragma.h"
+#include "c-parser.h"
enum c_language_kind c_language = clk_c;
@@ -59,18 +59,8 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-expr.h"
#include "context.h"
#include "gcc-rich-location.h"
-#include "tree-vrp.h"
-#include "tree-pass.h"
-#include "tree-pretty-print.h"
-#include "tree.h"
-#include "basic-block.h"
-#include "gimple.h"
-#include "gimple-pretty-print.h"
-#include "tree-ssa.h"
-#include "pass_manager.h"
-#include "tree-ssanames.h"
-#include "gimple-ssa.h"
-#include "tree-dfa.h"
+#include "c-parser.h"
+#include "gimple-parser.h"
/* We need to walk over decls with incomplete struct/union/enum types
after parsing the whole translation unit.
@@ -162,116 +152,6 @@ c_parse_init (void)
}
}
-/* The C lexer intermediates between the lexer in cpplib and c-lex.c
- and the C parser. Unlike the C++ lexer, the parser structure
- stores the lexer information instead of using a separate structure.
- Identifiers are separated into ordinary identifiers, type names,
- keywords and some other Objective-C types of identifiers, and some
- look-ahead is maintained.
-
- ??? It might be a good idea to lex the whole file up front (as for
- C++). It would then be possible to share more of the C and C++
- lexer code, if desired. */
-
-/* More information about the type of a CPP_NAME token. */
-enum c_id_kind {
- /* An ordinary identifier. */
- C_ID_ID,
- /* An identifier declared as a typedef name. */
- C_ID_TYPENAME,
- /* An identifier declared as an Objective-C class name. */
- C_ID_CLASSNAME,
- /* An address space identifier. */
- C_ID_ADDRSPACE,
- /* Not an identifier. */
- C_ID_NONE
-};
-
-/* A single C token after string literal concatenation and conversion
- of preprocessing tokens to tokens. */
-struct GTY (()) c_token {
- /* The kind of token. */
- ENUM_BITFIELD (cpp_ttype) type : 8;
- /* If this token is a CPP_NAME, this value indicates whether also
- declared as some kind of type. Otherwise, it is C_ID_NONE. */
- ENUM_BITFIELD (c_id_kind) id_kind : 8;
- /* If this token is a keyword, this value indicates which keyword.
- Otherwise, this value is RID_MAX. */
- ENUM_BITFIELD (rid) keyword : 8;
- /* If this token is a CPP_PRAGMA, this indicates the pragma that
- was seen. Otherwise it is PRAGMA_NONE. */
- ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
- /* The location at which this token was found. */
- location_t location;
- /* The value associated with this token, if any. */
- tree value;
- /* Token flags. */
- unsigned char flags;
-
- source_range get_range () const
- {
- return get_range_from_loc (line_table, location);
- }
-
- location_t get_finish () const
- {
- return get_range ().m_finish;
- }
-};
-
-/* A parser structure recording information about the state and
- context of parsing. Includes lexer information with up to two
- tokens of look-ahead; more are not needed for C. */
-struct GTY(()) c_parser {
- /* The look-ahead tokens. */
- c_token * GTY((skip)) tokens;
- /* Buffer for look-ahead tokens. */
- c_token tokens_buf[4];
- /* How many look-ahead tokens are available (0 - 4, or
- more if parsing from pre-lexed tokens). */
- unsigned int tokens_avail;
- /* True if a syntax error is being recovered from; false otherwise.
- c_parser_error sets this flag. It should clear this flag when
- enough tokens have been consumed to recover from the error. */
- BOOL_BITFIELD error : 1;
- /* True if we're processing a pragma, and shouldn't automatically
- consume CPP_PRAGMA_EOL. */
- BOOL_BITFIELD in_pragma : 1;
- /* True if we're parsing the outermost block of an if statement. */
- BOOL_BITFIELD in_if_block : 1;
- /* True if we want to lex an untranslated string. */
- BOOL_BITFIELD lex_untranslated_string : 1;
-
- /* Objective-C specific parser/lexer information. */
-
- /* True if we are in a context where the Objective-C "PQ" keywords
- are considered keywords. */
- BOOL_BITFIELD objc_pq_context : 1;
- /* True if we are parsing a (potential) Objective-C foreach
- statement. This is set to true after we parsed 'for (' and while
- we wait for 'in' or ';' to decide if it's a standard C for loop or an
- Objective-C foreach loop. */
- BOOL_BITFIELD objc_could_be_foreach_context : 1;
- /* The following flag is needed to contextualize Objective-C lexical
- analysis. In some cases (e.g., 'int NSObject;'), it is
- undesirable to bind an identifier to an Objective-C class, even
- if a class with that name exists. */
- BOOL_BITFIELD objc_need_raw_identifier : 1;
- /* Nonzero if we're processing a __transaction statement. The value
- is 1 | TM_STMT_ATTR_*. */
- unsigned int in_transaction : 4;
- /* True if we are in a context where the Objective-C "Property attribute"
- keywords are valid. */
- BOOL_BITFIELD objc_property_attr_context : 1;
-
- /* Cilk Plus specific parser/lexer information. */
-
- /* Buffer to hold all the tokens from parsing the vector attribute for the
- SIMD-enabled functions (formerly known as elemental functions). */
- vec <c_token, va_gc> *cilk_simd_fn_tokens;
-};
-
-
/* The actual parser and external interface. ??? Does this need to be
garbage-collected? */
@@ -466,7 +346,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
/* Return a pointer to the next token from PARSER, reading it in if
necessary. */
-static inline c_token *
+c_token *
c_parser_peek_token (c_parser *parser)
{
if (parser->tokens_avail == 0)
@@ -477,37 +357,10 @@ c_parser_peek_token (c_parser *parser)
return &parser->tokens[0];
}
-/* Return true if the next token from PARSER has the indicated
- TYPE. */
-
-static inline bool
-c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
-{
- return c_parser_peek_token (parser)->type == type;
-}
-
-/* Return true if the next token from PARSER does not have the
- indicated TYPE. */
-
-static inline bool
-c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
-{
- return !c_parser_next_token_is (parser, type);
-}
-
-/* Return true if the next token from PARSER is the indicated
- KEYWORD. */
-
-static inline bool
-c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
-{
- return c_parser_peek_token (parser)->keyword == keyword;
-}
-
/* Return a pointer to the next-but-one token from PARSER, reading it
in if necessary. The next token is already read in. */
-static c_token *
+c_token *
c_parser_peek_2nd_token (c_parser *parser)
{
if (parser->tokens_avail >= 2)
@@ -582,7 +435,7 @@ c_keyword_starts_typename (enum rid keyword)
/* Return true if TOKEN can start a type name,
false otherwise. */
-static bool
+bool
c_token_starts_typename (c_token *token)
{
switch (token->type)
@@ -613,18 +466,6 @@ c_token_starts_typename (c_token *token)
}
}
-enum c_lookahead_kind {
- /* Always treat unknown identifiers as typenames. */
- cla_prefer_type,
-
- /* Could be parsing a nonabstract declarator. Only treat an identifier
- as a typename if followed by another identifier or a star. */
- cla_nonabstract_decl,
-
- /* Never treat identifiers as typenames. */
- cla_prefer_id
-};
-
/* Return true if the next token from PARSER can start a type name,
false otherwise. LA specifies how to do lookahead in order to
detect unknown type names. If unsure, pick CLA_PREFER_ID. */
@@ -791,7 +632,7 @@ c_token_starts_declaration (c_token *token)
/* Return true if the next token from PARSER can start declaration
specifiers, false otherwise. */
-static inline bool
+bool
c_parser_next_token_starts_declspecs (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
@@ -813,7 +654,7 @@ c_parser_next_token_starts_declspecs (c_parser *parser)
/* Return true if the next tokens from PARSER can start declaration
specifiers or a static assertion, false otherwise. */
-static inline bool
+bool
c_parser_next_tokens_start_declaration (c_parser *parser)
{
c_token *token = c_parser_peek_token (parser);
@@ -841,7 +682,7 @@ c_parser_next_tokens_start_declaration (c_parser *parser)
/* Consume the next token from PARSER. */
-static void
+void
c_parser_consume_token (c_parser *parser)
{
gcc_assert (parser->tokens_avail >= 1);
@@ -934,7 +775,7 @@ c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
this way is not i18n-friendly and some other approach should be
used. */
-static void
+void
c_parser_error (c_parser *parser, const char *gmsgid)
{
c_token *token = c_parser_peek_token (parser);
@@ -977,7 +818,7 @@ c_parser_error (c_parser *parser, const char *gmsgid)
been produced and no message will be produced this time. Returns
true if found, false otherwise. */
-static bool
+bool
c_parser_require (c_parser *parser,
enum cpp_ttype type,
const char *msgid)
@@ -1020,7 +861,7 @@ c_parser_require_keyword (c_parser *parser,
already been produced and no message will be produced this
time. */
-static void
+void
c_parser_skip_until_found (c_parser *parser,
enum cpp_ttype type,
const char *msgid)
@@ -1255,42 +1096,6 @@ restore_extension_diagnostics (int flags)
warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
}
-/* Possibly kinds of declarator to parse. */
-enum c_dtr_syn {
- /* A normal declarator with an identifier. */
- C_DTR_NORMAL,
- /* An abstract declarator (maybe empty). */
- C_DTR_ABSTRACT,
- /* A parameter declarator: may be either, but after a type name does
- not redeclare a typedef name as an identifier if it can
- alternatively be interpreted as a typedef name; see DR#009,
- applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
- following DR#249. For example, given a typedef T, "int T" and
- "int *T" are valid parameter declarations redeclaring T, while
- "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
- abstract declarators rather than involving redundant parentheses;
- the same applies with attributes inside the parentheses before
- "T". */
- C_DTR_PARM
-};
-
-/* The binary operation precedence levels, where 0 is a dummy lowest level
- used for the bottom of the stack. */
-enum c_parser_prec {
- PREC_NONE,
- PREC_LOGOR,
- PREC_LOGAND,
- PREC_BITOR,
- PREC_BITXOR,
- PREC_BITAND,
- PREC_EQ,
- PREC_REL,
- PREC_SHIFT,
- PREC_ADD,
- PREC_MULT,
- NUM_PRECS
-};
-
/* Helper data structure for parsing #pragma acc routine. */
struct oacc_routine_data {
bool error_seen; /* Set if error has been reported. */
@@ -1307,15 +1112,11 @@ static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
bool * = NULL);
static void c_parser_static_assert_declaration_no_semi (c_parser *);
static void c_parser_static_assert_declaration (c_parser *);
-static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
- bool, bool, bool, enum c_lookahead_kind);
static struct c_typespec c_parser_enum_specifier (c_parser *);
static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
static tree c_parser_struct_declaration (c_parser *);
static struct c_typespec c_parser_typeof_specifier (c_parser *);
static tree c_parser_alignas_specifier (c_parser *);
-static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
- bool *);
static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
c_dtr_syn, bool *);
static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
@@ -1355,7 +1156,6 @@ static struct c_expr c_parser_conditional_expression (c_parser *,
struct c_expr *, tree);
static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
tree);
-static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
static struct c_expr c_parser_unary_expression (c_parser *);
static struct c_expr c_parser_sizeof_expression (c_parser *);
static struct c_expr c_parser_alignof_expression (c_parser *);
@@ -1433,30 +1233,6 @@ static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
static void c_parser_cilk_grainsize (c_parser *, bool *);
-/* Gimple parsing functions. */
-static void c_parser_parse_gimple_body (c_parser *);
-static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
-static void c_parser_gimple_label (c_parser *, gimple_seq *);
-static void c_parser_gimple_expression (c_parser *, gimple_seq *);
-static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *);
-static struct c_expr c_parser_gimple_unary_expression (c_parser *);
-static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
-static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
- location_t,
- struct c_expr);
-static void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
-static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
-static void c_parser_gimple_declaration (c_parser *);
-static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
-static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *);
-static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *);
-static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *);
-static void c_finish_gimple_return (location_t, tree);
-static c_expr c_parser_parse_ssa_names (c_parser *);
-static tree c_parser_gimple_paren_condition (c_parser *);
-static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *,
- vec<tree, va_gc> **, vec<location_t> *);
-
/* Parse a translation unit (C90 6.7, C99 6.9).
translation-unit:
@@ -2496,7 +2272,7 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
objc-protocol-refs
*/
-static void
+void
c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
bool scspec_ok, bool typespec_ok, bool start_attr_ok,
bool alignspec_ok, bool auto_type_ok,
@@ -3495,7 +3271,7 @@ c_parser_alignas_specifier (c_parser * parser)
This function also accepts an omitted abstract declarator as being
an abstract declarator, although not part of the formal syntax. */
-static struct c_declarator *
+struct c_declarator *
c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
bool *seen_id)
{
@@ -6946,7 +6722,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
( type-name ) unary-expression
*/
-static struct c_expr
+struct c_expr
c_parser_cast_expression (c_parser *parser, struct c_expr *after)
{
location_t cast_loc = c_parser_peek_token (parser)->location;
@@ -18393,1309 +18169,4 @@ c_parser_array_notation (location_t loc, c_parser *parser, tree initial_index,
return value_tree;
}
-/* Parse the body of a function declaration marked with "__GIMPLE". */
-
-void
-c_parser_parse_gimple_body (c_parser *parser)
-{
- gimple_seq seq = NULL;
- gimple_seq body = NULL;
- tree stmt = push_stmt_list ();
- push_scope ();
- location_t loc1 = c_parser_peek_token (parser)->location;
-
- init_tree_ssa (cfun);
-
- if (! c_parser_gimple_compound_statement (parser, &seq))
- {
- gimple *ret = gimple_build_return (NULL);
- gimple_seq_add_stmt (&seq, ret);
- }
-
- tree block = pop_scope ();
- stmt = pop_stmt_list (stmt);
- stmt = c_build_bind_expr (loc1, block, stmt);
-
- block = DECL_INITIAL (current_function_decl);
- BLOCK_SUBBLOCKS (block) = NULL_TREE;
- BLOCK_CHAIN (block) = NULL_TREE;
- TREE_ASM_WRITTEN (block) = 1;
-
- gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
- BIND_EXPR_BLOCK (stmt));
- gimple_bind_set_body (bind_stmt, seq);
- gimple_seq_add_stmt (&body, bind_stmt);
- gimple_set_body (current_function_decl, body);
- cfun->curr_properties = PROP_gimple_any;
-
- return;
-}
-
-/* Parse a compound statement in gimple function body.
-
- gimple-statement:
- gimple-statement
- gimple-declaration-statement
- gimple-if-statement
- gimple-switch-statement
- gimple-labeled-statement
- gimple-expression-statement
- gimple-goto-statement
- gimple-phi-statement
- gimple-return-statement
-*/
-
-static bool
-c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
-{
- bool return_p = false;
-
- if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- return false;
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- c_parser_consume_token (parser);
- return false;
- }
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- c_parser_error (parser, "expected declaration or statement");
- c_parser_consume_token (parser);
- return false;
- }
-
- while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
- {
- if (parser->error)
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- return return_p;
- }
-
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- c_parser_gimple_label (parser, seq);
-
- else if (c_parser_next_tokens_start_declaration (parser))
- c_parser_gimple_declaration (parser);
-
- else if (c_parser_next_token_is (parser, CPP_EOF))
- {
- c_parser_error (parser, "expected declaration or statement");
- return return_p;
- }
-
- else
- {
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_KEYWORD:
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_IF:
- c_parser_gimple_if_stmt (parser, seq);
- break;
- case RID_SWITCH:
- c_parser_gimple_switch_stmt (parser, seq);
- break;
- case RID_GOTO:
- {
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_gimple_goto_stmt (loc,
- c_parser_peek_token
- (parser)->value,
- seq);
- c_parser_consume_token (parser);
- if (! c_parser_require (parser, CPP_SEMICOLON,
- "expected %<;%>"))
- return return_p;
- }
- }
- break;
- case RID_RETURN:
- return_p = true;
- c_parser_gimple_return_stmt (parser, seq);
- if (! c_parser_require (parser, CPP_SEMICOLON,
- "expected %<;%>"))
- return return_p;
- break;
- default:
- goto expr_stmt;
- }
- break;
- case CPP_SEMICOLON:
- c_parser_consume_token (parser);
- break;
- default:
- expr_stmt:
- c_parser_gimple_expression (parser, seq);
- if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- return return_p;
- }
- }
- }
- c_parser_consume_token (parser);
- return return_p;
-}
-
-/* Parse a gimple expression.
-
- gimple-expression:
- gimple-unary-expression
- gimple-call-statement
- gimple-binary-expression
- gimple-assign-expression
- gimple-cast-expression
-
-*/
-
-static void
-c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
-{
- struct c_expr lhs, rhs;
- gimple *assign = NULL;
- enum tree_code subcode = NOP_EXPR;
- location_t loc;
- tree arg = NULL_TREE;
- auto_vec<tree> vargs;
-
- lhs = c_parser_gimple_unary_expression (parser);
- rhs.value = error_mark_node;
-
- if (c_parser_next_token_is (parser, CPP_EQ))
- c_parser_consume_token (parser);
-
- loc = EXPR_LOCATION (lhs.value);
-
- /* GIMPLE call expression. */
- if (c_parser_next_token_is (parser, CPP_SEMICOLON)
- && TREE_CODE (lhs.value) == CALL_EXPR)
- {
- gimple *call;
- call = gimple_build_call_from_tree (lhs.value);
- gimple_seq_add_stmt (seq, call);
- gimple_set_location (call, loc);
- return;
- }
-
- /* Cast expression. */
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
- {
- /* TODO: have a gimple_cast_expr function. */
- rhs = c_parser_cast_expression (parser, NULL);
- if (lhs.value != error_mark_node &&
- rhs.value != error_mark_node)
- {
- assign = gimple_build_assign (lhs.value, rhs.value);
- gimple_seq_add_stmt (seq, assign);
- gimple_set_location (assign, loc);
- return;
- }
- }
-
- if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
- {
- STRIP_USELESS_TYPE_CONVERSION (rhs.value);
- if (! useless_type_conversion_p (TREE_TYPE (lhs.value),
- TREE_TYPE (rhs.value)))
- rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
- }
-
- /* Pointer expression. */
- if (TREE_CODE (lhs.value) == INDIRECT_REF)
- {
- tree save_expr = lhs.value;
- bool volatilep = TREE_THIS_VOLATILE (lhs.value);
- bool notrap = TREE_THIS_NOTRAP (lhs.value);
- tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0));
-
- lhs.value = fold_indirect_ref_loc (loc, lhs.value);
- if (lhs.value == save_expr)
- {
- lhs.value = fold_build2_loc (input_location, MEM_REF,
- TREE_TYPE (lhs.value),
- TREE_OPERAND (lhs.value, 0),
- build_int_cst (saved_ptr_type, 0));
- TREE_THIS_VOLATILE (lhs.value) = volatilep;
- TREE_THIS_NOTRAP (lhs.value) = notrap;
- }
- }
-
- if (c_parser_next_token_is (parser, CPP_AND)
- || c_parser_next_token_is (parser, CPP_MULT)
- || c_parser_next_token_is (parser, CPP_PLUS)
- || c_parser_next_token_is (parser, CPP_MINUS)
- || c_parser_next_token_is (parser, CPP_COMPL)
- || c_parser_next_token_is (parser, CPP_NOT))
- {
- rhs = c_parser_gimple_unary_expression (parser);
- assign = gimple_build_assign (lhs.value, rhs.value);
- gimple_set_location (assign, loc);
- gimple_seq_add_stmt (seq, assign);
- return;
- }
-
- /* GIMPLE PHI expression. */
- if (c_parser_next_token_is_keyword (parser, RID_PHI))
- {
- c_parser_consume_token (parser);
-
- if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- return;
-
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- c_parser_consume_token (parser);
-
- while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
- {
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- arg = lookup_label_for_goto (loc,
- c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
-
- if (c_parser_next_token_is (parser, CPP_COLON))
- c_parser_consume_token (parser);
- vargs.safe_push (arg);
- }
- else if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- {
- arg = c_parser_parse_ssa_names (parser).value;
- vargs.safe_push (arg);
- }
- }
-
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
-
- /* Build internal function for PHI. */
- gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
- gimple_call_set_lhs (call_stmt, lhs.value);
- gimple_set_location (call_stmt, UNKNOWN_LOCATION);
- gimple_seq_add_stmt (seq, call_stmt);
- return;
- }
-
- /* GIMPLE call with lhs. */
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
- && lookup_name (c_parser_peek_token (parser)->value))
- {
- rhs = c_parser_gimple_unary_expression (parser);
- gimple *call = gimple_build_call_from_tree (rhs.value);
- gimple_call_set_lhs (call, lhs.value);
- gimple_seq_add_stmt (seq, call);
- gimple_set_location (call, loc);
- return;
- }
-
- rhs = c_parser_gimple_binary_expression (parser, &subcode);
-
- if (lhs.value != error_mark_node
- && rhs.value != error_mark_node)
- {
- if (subcode == NOP_EXPR)
- assign = gimple_build_assign (lhs.value, rhs.value);
- else
- assign = gimple_build_assign (lhs.value, subcode,
- TREE_OPERAND (rhs.value, 0),
- TREE_OPERAND (rhs.value, 1));
- gimple_seq_add_stmt (seq, assign);
- gimple_set_location (assign, loc);
- }
- return;
-}
-
-/* Parse gimple binary expr.
-
- gimple-multiplicative-expression:
- gimple-unary-expression * gimple-unary-expression
- gimple-unary-expression / gimple-unary-expression
- gimple-unary-expression % gimple-unary-expression
-
- gimple-additive-expression:
- gimple-unary-expression + gimple-unary-expression
- gimple-unary-expression - gimple-unary-expression
-
- gimple-shift-expression:
- gimple-unary-expression << gimple-unary-expression
- gimple-unary-expression >> gimple-unary-expression
-
- gimple-relational-expression:
- gimple-unary-expression < gimple-unary-expression
- gimple-unary-expression > gimple-unary-expression
- gimple-unary-expression <= gimple-unary-expression
- gimple-unary-expression >= gimple-unary-expression
-
- gimple-equality-expression:
- gimple-unary-expression == gimple-unary-expression
- gimple-unary-expression != gimple-unary-expression
-
- gimple-AND-expression:
- gimple-unary-expression & gimple-unary-expression
-
- gimple-exclusive-OR-expression:
- gimple-unary-expression ^ gimple-unary-expression
-
- gimple-inclusive-OR-expression:
- gimple-unary-expression | gimple-unary-expression
-
- gimple-logical-AND-expression:
- gimple-unary-expression && gimple-unary-expression
-
- gimple-logical-OR-expression:
- gimple-unary-expression || gimple-unary-expression
-
-*/
-
-static c_expr
-c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
-{
- struct {
- /* The expression at this stack level. */
- struct c_expr expr;
- /* The operation on its left. */
- enum tree_code op;
- /* The source location of this operation. */
- location_t loc;
- } stack[2];
- int sp;
- /* Location of the binary operator. */
- location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
-#define POP \
- do { \
- if (sp == 1 \
- && c_parser_peek_token (parser)->type == CPP_SEMICOLON \
- && (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \
- | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \
- && stack[sp].op != TRUNC_MOD_EXPR \
- && stack[0].expr.value != error_mark_node \
- && stack[1].expr.value != error_mark_node) \
- stack[0].expr.value \
- = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \
- stack[0].expr.value, stack[1].expr.value); \
- else \
- stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
- stack[sp].op, \
- stack[sp - 1].expr, \
- stack[sp].expr); \
- sp--; \
- } while (0)
- stack[0].loc = c_parser_peek_token (parser)->location;
- stack[0].expr = c_parser_gimple_unary_expression (parser);
- sp = 0;
- source_range src_range;
- if (parser->error)
- goto out;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_MULT:
- *subcode = MULT_EXPR;
- break;
- case CPP_DIV:
- *subcode = TRUNC_DIV_EXPR;
- break;
- case CPP_MOD:
- *subcode = TRUNC_MOD_EXPR;
- break;
- case CPP_PLUS:
- *subcode = PLUS_EXPR;
- break;
- case CPP_MINUS:
- *subcode = MINUS_EXPR;
- break;
- case CPP_LSHIFT:
- *subcode = LSHIFT_EXPR;
- break;
- case CPP_RSHIFT:
- *subcode = RSHIFT_EXPR;
- break;
- case CPP_LESS:
- *subcode = LT_EXPR;
- break;
- case CPP_GREATER:
- *subcode = GT_EXPR;
- break;
- case CPP_LESS_EQ:
- *subcode = LE_EXPR;
- break;
- case CPP_GREATER_EQ:
- *subcode = GE_EXPR;
- break;
- case CPP_EQ_EQ:
- *subcode = EQ_EXPR;
- break;
- case CPP_NOT_EQ:
- *subcode = NE_EXPR;
- break;
- case CPP_AND:
- *subcode = BIT_AND_EXPR;
- break;
- case CPP_XOR:
- *subcode = BIT_XOR_EXPR;
- break;
- case CPP_OR:
- *subcode = BIT_IOR_EXPR;
- break;
- case CPP_AND_AND:
- *subcode = TRUTH_ANDIF_EXPR;
- break;
- case CPP_OR_OR:
- *subcode = TRUTH_ORIF_EXPR;
- break;
- default:
- /* Not a binary operator, so end of the binary expression. */
- *subcode = NOP_EXPR;
- goto out;
- }
- binary_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- switch (*subcode)
- {
- case TRUTH_ANDIF_EXPR:
- src_range = stack[sp].expr.src_range;
- stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (stack[sp].loc, default_conversion (stack[sp].expr.value));
- set_c_expr_source_range (&stack[sp].expr, src_range);
- break;
- case TRUTH_ORIF_EXPR:
- src_range = stack[sp].expr.src_range;
- stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (stack[sp].loc, default_conversion (stack[sp].expr.value));
- set_c_expr_source_range (&stack[sp].expr, src_range);
- break;
- default:
- break;
- }
- sp++;
- stack[sp].loc = binary_loc;
- stack[sp].expr = c_parser_gimple_unary_expression (parser);
- stack[sp].op = *subcode;
-out:
- while (sp > 0)
- POP;
- return stack[0].expr;
-#undef POP
-}
-
-/* Parse gimple unary expression.
-
- gimple-unary-expression:
- gimple-postfix-expression
- unary-operator cast-expression
-
- unary-operator: one of
- & * + - ~ !
-*/
-
-static c_expr
-c_parser_gimple_unary_expression (c_parser *parser)
-{
- struct c_expr ret, op;
- if (c_parser_peek_token (parser)->value
- && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
- && ! lookup_name (c_parser_peek_token (parser)->value))
- return c_parser_parse_ssa_names (parser);
-
- location_t op_loc = c_parser_peek_token (parser)->location;
- location_t finish;
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_AND:
- c_parser_consume_token (parser);
- op = c_parser_cast_expression (parser, NULL);
- mark_exp_read (op.value);
- return parser_build_unary_op (op_loc, ADDR_EXPR, op);
- case CPP_MULT:
- {
- c_parser_consume_token (parser);
- op = c_parser_cast_expression (parser, NULL);
- finish = op.get_finish ();
- location_t combined_loc = make_location (op_loc, op_loc, finish);
- ret.value = build_indirect_ref (combined_loc, op.value,
- RO_UNARY_STAR);
- ret.src_range.m_start = op_loc;
- ret.src_range.m_finish = finish;
- return ret;
- }
- case CPP_PLUS:
- c_parser_consume_token (parser);
- op = c_parser_cast_expression (parser, NULL);
- return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
- case CPP_MINUS:
- c_parser_consume_token (parser);
- op = c_parser_cast_expression (parser, NULL);
- return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
- case CPP_COMPL:
- c_parser_consume_token (parser);
- op = c_parser_cast_expression (parser, NULL);
- return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
- case CPP_NOT:
- c_parser_consume_token (parser);
- op = c_parser_cast_expression (parser, NULL);
- return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
- default:
- return c_parser_gimple_postfix_expression (parser);
- }
-}
-
-/* Parse gimple ssa names. */
-
-static c_expr
-c_parser_parse_ssa_names (c_parser *parser)
-{
- tree id = NULL_TREE;
- c_expr ret;
- char *var_name = NULL, *var_version = NULL, *token = NULL;
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
-
- /* SSA token string. */
- const char *ssa_token
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- token = new char [strlen (ssa_token) + 1];
- strcpy (token, ssa_token);
-
- /* Separate var name and version. */
- var_version = strrchr (token, '_');
- if (var_version)
- {
- var_name = new char[var_version - token + 1];
- memcpy (var_name, token, var_version - token);
- var_name[var_version - token] = '\0';
- id = get_identifier (var_name);
-
- /* lookup for parent decl. */
- if (lookup_name (id))
- {
- var_version++;
- unsigned int version;
- version = atoi (var_version);
- if (var_version && version)
- {
- ret.value = NULL_TREE;
- if (version < num_ssa_names)
- ret.value = ssa_name (version);
- if (! ret.value)
- ret.value = make_ssa_name_fn (cfun, lookup_name (id),
- gimple_build_nop (), version);
- c_parser_consume_token (parser);
- }
- }
- }
-
- /* For default definition SSA names. */
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- c_parser_consume_token (parser);
- ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (! strcmp ("D", ssa_token))
- {
- set_ssa_default_def (cfun, lookup_name (id), ret.value);
- c_parser_consume_token (parser);
- }
- if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- goto out;
- }
-
- out:
- free (var_name);
- free (token);
- return ret;
-}
-
-/* Parse gimple postfix expression.
-
- gimple-postfix-expression:
- gimple-primary-expression
- gimple-primary-xpression [ gimple-primary-expression ]
- gimple-primary-expression ( gimple-argument-expression-list[opt] )
-
- gimple-argument-expression-list:
- gimple-unary-expression
- gimple-argument-expression-list , gimple-unary-expression
-
- gimple-primary-expression:
- identifier
- constant
- string-literal
-
-*/
-
-static struct c_expr
-c_parser_gimple_postfix_expression (c_parser *parser)
-{
- struct c_expr expr;
- location_t loc = c_parser_peek_token (parser)->location;
- source_range tok_range = c_parser_peek_token (parser)->get_range ();
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_NUMBER:
- expr.value = c_parser_peek_token (parser)->value;
- set_c_expr_source_range (&expr, tok_range);
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- break;
- case CPP_CHAR:
- case CPP_CHAR16:
- case CPP_CHAR32:
- case CPP_WCHAR:
- expr.value = c_parser_peek_token (parser)->value;
- set_c_expr_source_range (&expr, tok_range);
- c_parser_consume_token (parser);
- break;
- case CPP_STRING:
- case CPP_STRING16:
- case CPP_STRING32:
- case CPP_WSTRING:
- case CPP_UTF8STRING:
- expr.value = c_parser_peek_token (parser)->value;
- set_c_expr_source_range (&expr, tok_range);
- expr.original_code = STRING_CST;
- c_parser_consume_token (parser);
- break;
- case CPP_NAME:
- if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
- {
- tree id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- expr.value = build_external_ref (loc, id,
- (c_parser_peek_token (parser)->type
- == CPP_OPEN_PAREN),
- &expr.original_type);
- set_c_expr_source_range (&expr, tok_range);
- break;
- }
- else
- {
- c_parser_error (parser, "expected expression");
- expr.set_error ();
- break;
- }
- break;
- default:
- c_parser_error (parser, "expected expression");
- expr.set_error ();
- break;
- }
- return c_parser_gimple_postfix_expression_after_primary
- (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
-}
-
-/* Parse a gimple postfix expression after the initial primary or compound
- literal. */
-
-static struct c_expr
-c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
- location_t expr_loc,
- struct c_expr expr)
-{
- struct c_expr orig_expr;
- vec<tree, va_gc> *exprlist;
- vec<tree, va_gc> *origtypes = NULL;
- vec<location_t> arg_loc = vNULL;
- location_t start;
- location_t finish;
-
- location_t op_loc = c_parser_peek_token (parser)->location;
-
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_OPEN_SQUARE:
- {
- c_parser_consume_token (parser);
- tree idx = c_parser_gimple_unary_expression (parser).value;
-
- if (! c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
- break;
-
- start = expr.get_start ();
- finish = parser->tokens_buf[0].location;
- expr.value = build_array_ref (op_loc, expr.value, idx);
- set_c_expr_source_range (&expr, start, finish);
-
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- break;
- }
- case CPP_OPEN_PAREN:
- {
- /* Function call. */
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- exprlist = NULL;
- else
- exprlist = c_parser_gimple_expr_list (parser, &origtypes,
- &arg_loc);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- orig_expr = expr;
- start = expr.get_start ();
- finish = parser->tokens_buf[0].get_finish ();
- expr.value = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
- exprlist, origtypes);
- set_c_expr_source_range (&expr, start, finish);
-
- expr.original_code = ERROR_MARK;
- if (TREE_CODE (expr.value) == INTEGER_CST
- && TREE_CODE (orig_expr.value) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
- expr.original_code = C_MAYBE_CONST_EXPR;
- expr.original_type = NULL;
- if (exprlist)
- {
- release_tree_vector (exprlist);
- release_tree_vector (origtypes);
- }
- arg_loc.release ();
- break;
- default:
- return expr;
- }
- }
- return expr;
-}
-
-/* Parse expression list.
-
- gimple-expr-list:
- gimple-unary-expression
- gimple-expr-list , gimple-unary-expression
-
- */
-
-static vec<tree, va_gc> *
-c_parser_gimple_expr_list (c_parser *parser, vec<tree, va_gc> **p_orig_types,
- vec<location_t> *locations)
-{
- vec<tree, va_gc> *ret;
- vec<tree, va_gc> *orig_types;
- struct c_expr expr;
- location_t loc = c_parser_peek_token (parser)->location;
-
- ret = make_tree_vector ();
- if (p_orig_types == NULL)
- orig_types = NULL;
- else
- orig_types = make_tree_vector ();
-
- expr = c_parser_gimple_unary_expression (parser);
- vec_safe_push (ret, expr.value);
- if (orig_types)
- vec_safe_push (orig_types, expr.original_type);
- if (locations)
- locations->safe_push (loc);
- while (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- loc = c_parser_peek_token (parser)->location;
- expr = c_parser_gimple_unary_expression (parser);
- vec_safe_push (ret, expr.value);
- if (orig_types)
- vec_safe_push (orig_types, expr.original_type);
- if (locations)
- locations->safe_push (loc);
- }
- if (orig_types)
- *p_orig_types = orig_types;
- return ret;
-}
-
-/* Parse gimple label.
-
- gimple-label:
- identifier :
- case constant-expression :
- default :
-
-*/
-
-static void
-c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
-{
- tree name = c_parser_peek_token (parser)->value;
- location_t loc1 = c_parser_peek_token (parser)->location;
- gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
- c_parser_consume_token (parser);
- gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
- c_parser_consume_token (parser);
- tree label = define_label (loc1, name);
- gimple_seq_add_stmt (seq, gimple_build_label (label));
- return;
-}
-
-/* Parse gimple pass list.
-
- gimple-pass-list:
- startwith("pass-name")
- */
-
-static void
-c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
- bool *startwith_p)
-{
- if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- return;
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- return;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
- if (! strcmp (op, "startwith"))
- {
- *pass = c_parser_gimple_pass_list_params (parser, pass);
- if (! *pass)
- return;
-
- *startwith_p = true;
- if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- return;
- }
- else
- {
- error_at (c_parser_peek_token (parser)->location,
- "invalid operation");
- return;
- }
- }
- else if (c_parser_next_token_is (parser, CPP_EOF))
- {
- c_parser_error (parser, "expected parameters");
- return;
- }
-
- return;
-}
-
-/* Support function for c_parser_gimple_pass_list. */
-
-static opt_pass *
-c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
-{
- opt_pass *pass_start = NULL, *new_pass;
- if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- return NULL;
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- return NULL;
-
- while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
- {
- if (c_parser_next_token_is (parser, CPP_EOF))
- {
- error_at (c_parser_peek_token (parser)->location,
- "expected pass names");
- return NULL;
- }
-
- if (c_parser_next_token_is (parser, CPP_STRING))
- {
- const char *name = NULL;
- name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
- new_pass = g->get_passes ()->get_pass_by_name (name);
-
- if (! new_pass)
- {
- error_at (c_parser_peek_token (parser)->location,
- "invalid pass name");
- parser->error = true;
- c_parser_consume_token (parser);
- return NULL;
- }
- if (*pass)
- {
- (*pass)->next = new_pass;
- (*pass) = (*pass)->next;
- }
- else
- {
- *pass = new_pass;
- pass_start = *pass;
- }
- }
- else if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- {
- error_at (c_parser_peek_token (parser)->location,
- "invalid pass name");
- c_parser_consume_token (parser);
- return NULL;
- }
- }
- return pass_start;
-}
-
-/* Parse gimple local declaration.
-
- declaration-specifiers:
- storage-class-specifier declaration-specifiers[opt]
- type-specifier declaration-specifiers[opt]
- type-qualifier declaration-specifiers[opt]
- function-specifier declaration-specifiers[opt]
- alignment-specifier declaration-specifiers[opt]
-
- storage-class-specifier:
- typedef
- extern
- static
- auto
- register
-
- type-specifier:
- void
- char
- short
- int
- long
- float
- double
- signed
- unsigned
- _Bool
- _Complex
-
- type-qualifier:
- const
- restrict
- volatile
- address-space-qualifier
- _Atomic
-
- */
-
-static void
-c_parser_gimple_declaration (c_parser *parser)
-{
- struct c_declarator *declarator;
- struct c_declspecs *specs = build_null_declspecs ();
- c_parser_declspecs (parser, specs, true, true, true,
- true, true, cla_nonabstract_decl);
- finish_declspecs (specs);
-
- /* Provide better error recovery. Note that a type name here is usually
- better diagnosed as a redeclaration. */
- if (c_parser_next_token_starts_declspecs (parser)
- && ! c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected %<;%>");
- parser->error = false;
- return;
- }
-
- bool dummy = false;
- declarator = c_parser_declarator (parser,
- specs->typespec_kind != ctsk_none,
- C_DTR_NORMAL, &dummy);
-
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- tree postfix_attrs = NULL_TREE;
- tree all_prefix_attrs = specs->attrs;
- specs->attrs = NULL;
- tree decl = start_decl (declarator, specs, false,
- chainon (postfix_attrs, all_prefix_attrs));
- if (decl)
- finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, NULL_TREE);
- }
- else
- {
- c_parser_error (parser, "expected %<;%>");
- return;
- }
-}
-
-/* Parse gimple goto statement. */
-
-static void
-c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
-{
- tree decl = lookup_label_for_goto (loc, label);
- gimple_seq_add_stmt (seq, gimple_build_goto (decl));
- return;
-}
-
-/* Parse a parenthesized condition.
- gimple-condition:
- ( gimple-binary-expression ) */
-
-static tree
-c_parser_gimple_paren_condition (c_parser *parser)
-{
- enum tree_code subcode = NOP_EXPR;
- location_t loc = c_parser_peek_token (parser)->location;
- if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- return error_mark_node;
- tree cond = c_parser_gimple_binary_expression (parser, &subcode).value;
- cond = c_objc_common_truthvalue_conversion (loc, cond);
- if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- return error_mark_node;
- return cond;
-}
-
-/* Parse gimple if-else statement.
-
- if-statement:
- if ( gimple-binary-expression ) gimple-goto-statement
- if ( gimple-binary-expression ) gimple-goto-statement \
- else gimple-goto-statement
- */
-
-static void
-c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
-{
- tree t_label, f_label, label;
- location_t loc;
- c_parser_consume_token (parser);
- tree cond = c_parser_gimple_paren_condition (parser);
-
- if (c_parser_next_token_is_keyword (parser, RID_GOTO))
- {
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- label = c_parser_peek_token (parser)->value;
- t_label = lookup_label_for_goto (loc, label);
- c_parser_consume_token (parser);
- if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- return;
- }
- else
- {
- c_parser_error (parser, "expected goto expression");
- return;
- }
-
- if (c_parser_next_token_is_keyword (parser, RID_ELSE))
- c_parser_consume_token (parser);
- else
- {
- c_parser_error (parser, "expected else statement");
- return;
- }
-
- if (c_parser_next_token_is_keyword (parser, RID_GOTO))
- {
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- label = c_parser_peek_token (parser)->value;
- f_label = lookup_label_for_goto (loc, label);
- c_parser_consume_token (parser);
- if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- return;
- }
- else
- {
- c_parser_error (parser, "expected goto expression");
- return;
- }
-
- gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
- f_label));
-}
-
-/* Parse gimple switch-statement.
-
- gimple-switch-statement:
- switch (gimple-unary-expression) gimple-case-statement
-
- gimple-case-statement:
- gimple-case-statement
- gimple-label-statement : gimple-goto-statment
-*/
-
-static void
-c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
-{
- c_expr cond_expr;
- tree case_label, label;
- auto_vec<tree> labels;
- tree default_label = NULL_TREE;
- gimple_seq switch_body = NULL;
- location_t loc;
- c_parser_consume_token (parser);
-
- if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- {
- cond_expr = c_parser_gimple_unary_expression (parser);
- if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- return;
- }
-
- if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- {
- while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
- {
- if (c_parser_next_token_is (parser, CPP_EOF))
- {
- c_parser_error (parser, "expected statement");
- return;
- }
-
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_CASE:
- {
- c_expr exp1;
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
-
- if (c_parser_next_token_is (parser, CPP_NAME)
- || c_parser_peek_token (parser)->type == CPP_NUMBER)
- exp1 = c_parser_gimple_unary_expression (parser);
- else
- c_parser_error (parser, "expected expression");
-
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- label = create_artificial_label (loc);
- case_label = build_case_label (exp1.value, NULL_TREE,
- label);
- labels.safe_push (case_label);
- gimple_seq_add_stmt (&switch_body,
- gimple_build_label
- (CASE_LABEL (case_label)));
- }
- else if (! c_parser_require (parser, CPP_SEMICOLON,
- "expected %<:%>"))
- return;
- break;
- }
- case RID_DEFAULT:
- {
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- default_label = build_case_label (NULL_TREE, NULL_TREE,
- create_artificial_label
- (UNKNOWN_LOCATION));
- gimple_seq_add_stmt (&switch_body,
- gimple_build_label
- (CASE_LABEL (default_label)));
- }
- else if (! c_parser_require (parser, CPP_SEMICOLON,
- "expected %<:%>"))
- return;
- break;
- }
- case RID_GOTO:
- {
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_gimple_goto_stmt (loc,
- c_parser_peek_token
- (parser)->value,
- &switch_body);
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- c_parser_consume_token (parser);
- else
- {
- c_parser_error (parser, "expected semicolon");
- return;
- }
- }
- else if (! c_parser_require (parser, CPP_NAME,
- "expected label"))
- return;
- break;
- }
- default:
- c_parser_error (parser, "expected case label or goto statement");
- return;
- }
-
- }
- }
- if (! c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
- return;
- gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
- default_label, labels));
- gimple_seq_add_seq (seq, switch_body);
- labels.release();
-}
-
-/* Parse gimple return statement. */
-
-static void
-c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- gimple *ret = NULL;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- c_finish_gimple_return (loc, NULL_TREE);
- ret = gimple_build_return (NULL);
- gimple_seq_add_stmt (seq, ret);
- }
- else
- {
- location_t xloc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_gimple_unary_expression (parser);
- c_finish_gimple_return (xloc, expr.value);
- ret = gimple_build_return (expr.value);
- gimple_seq_add_stmt (seq, ret);
- }
-}
-
-/* Support function for c_parser_gimple_return_stmt. */
-
-static void
-c_finish_gimple_return (location_t loc, tree retval)
-{
- tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
-
- /* Use the expansion point to handle cases such as returning NULL
- in a function returning void. */
- source_location xloc = expansion_point_location_if_in_system_header (loc);
-
- if (TREE_THIS_VOLATILE (current_function_decl))
- warning_at (xloc, 0,
- "function declared %<noreturn%> has a %<return%> statement");
-
- if (! retval)
- current_function_returns_null = 1;
- else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
- {
- current_function_returns_null = 1;
- if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
- {
- error_at
- (xloc, "%<return%> with a value, in function returning void");
- inform (DECL_SOURCE_LOCATION (current_function_decl),
- "declared here");
- }
- }
- else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
- {
- error_at
- (xloc, "invalid conversion in return statement");
- inform (DECL_SOURCE_LOCATION (current_function_decl),
- "declared here");
- }
- return;
-}
-
#include "gt-c-c-parser.h"
new file mode 100644
@@ -0,0 +1,230 @@
+/* Declarations for the parser for C and Objective-C.
+ Copyright (C) 1987-2016 Free Software Foundation, Inc.
+
+ Parser actions based on the old Bison parser; structure somewhat
+ influenced by and fragments based on the C++ parser.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_C_PARSER_H
+#define GCC_C_PARSER_H
+
+/* The C lexer intermediates between the lexer in cpplib and c-lex.c
+ and the C parser. Unlike the C++ lexer, the parser structure
+ stores the lexer information instead of using a separate structure.
+ Identifiers are separated into ordinary identifiers, type names,
+ keywords and some other Objective-C types of identifiers, and some
+ look-ahead is maintained.
+
+ ??? It might be a good idea to lex the whole file up front (as for
+ C++). It would then be possible to share more of the C and C++
+ lexer code, if desired. */
+
+/* More information about the type of a CPP_NAME token. */
+enum c_id_kind {
+ /* An ordinary identifier. */
+ C_ID_ID,
+ /* An identifier declared as a typedef name. */
+ C_ID_TYPENAME,
+ /* An identifier declared as an Objective-C class name. */
+ C_ID_CLASSNAME,
+ /* An address space identifier. */
+ C_ID_ADDRSPACE,
+ /* Not an identifier. */
+ C_ID_NONE
+};
+
+/* A single C token after string literal concatenation and conversion
+ of preprocessing tokens to tokens. */
+typedef struct GTY (()) c_token {
+ /* The kind of token. */
+ ENUM_BITFIELD (cpp_ttype) type : 8;
+ /* If this token is a CPP_NAME, this value indicates whether also
+ declared as some kind of type. Otherwise, it is C_ID_NONE. */
+ ENUM_BITFIELD (c_id_kind) id_kind : 8;
+ /* If this token is a keyword, this value indicates which keyword.
+ Otherwise, this value is RID_MAX. */
+ ENUM_BITFIELD (rid) keyword : 8;
+ /* If this token is a CPP_PRAGMA, this indicates the pragma that
+ was seen. Otherwise it is PRAGMA_NONE. */
+ ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
+ /* The location at which this token was found. */
+ location_t location;
+ /* The value associated with this token, if any. */
+ tree value;
+ /* Token flags. */
+ unsigned char flags;
+
+ source_range get_range () const
+ {
+ return get_range_from_loc (line_table, location);
+ }
+
+ location_t get_finish () const
+ {
+ return get_range ().m_finish;
+ }
+} c_token_;
+
+/* A parser structure recording information about the state and
+ context of parsing. Includes lexer information with up to two
+ tokens of look-ahead; more are not needed for C. */
+struct GTY(()) c_parser {
+ /* The look-ahead tokens. */
+ struct c_token * GTY((skip)) tokens;
+ /* Buffer for look-ahead tokens. */
+ struct c_token GTY(()) tokens_buf[4];
+ /* How many look-ahead tokens are available (0 - 4, or
+ more if parsing from pre-lexed tokens). */
+ unsigned int tokens_avail;
+ /* True if a syntax error is being recovered from; false otherwise.
+ c_parser_error sets this flag. It should clear this flag when
+ enough tokens have been consumed to recover from the error. */
+ BOOL_BITFIELD error : 1;
+ /* True if we're processing a pragma, and shouldn't automatically
+ consume CPP_PRAGMA_EOL. */
+ BOOL_BITFIELD in_pragma : 1;
+ /* True if we're parsing the outermost block of an if statement. */
+ BOOL_BITFIELD in_if_block : 1;
+ /* True if we want to lex an untranslated string. */
+ BOOL_BITFIELD lex_untranslated_string : 1;
+
+ /* Objective-C specific parser/lexer information. */
+
+ /* True if we are in a context where the Objective-C "PQ" keywords
+ are considered keywords. */
+ BOOL_BITFIELD objc_pq_context : 1;
+ /* True if we are parsing a (potential) Objective-C foreach
+ statement. This is set to true after we parsed 'for (' and while
+ we wait for 'in' or ';' to decide if it's a standard C for loop or an
+ Objective-C foreach loop. */
+ BOOL_BITFIELD objc_could_be_foreach_context : 1;
+ /* The following flag is needed to contextualize Objective-C lexical
+ analysis. In some cases (e.g., 'int NSObject;'), it is
+ undesirable to bind an identifier to an Objective-C class, even
+ if a class with that name exists. */
+ BOOL_BITFIELD objc_need_raw_identifier : 1;
+ /* Nonzero if we're processing a __transaction statement. The value
+ is 1 | TM_STMT_ATTR_*. */
+ unsigned int in_transaction : 4;
+ /* True if we are in a context where the Objective-C "Property attribute"
+ keywords are valid. */
+ BOOL_BITFIELD objc_property_attr_context : 1;
+
+ /* Cilk Plus specific parser/lexer information. */
+
+ /* Buffer to hold all the tokens from parsing the vector attribute for the
+ SIMD-enabled functions (formerly known as elemental functions). */
+ vec <c_token_, va_gc> *cilk_simd_fn_tokens;
+};
+
+/* Possibly kinds of declarator to parse. */
+enum c_dtr_syn {
+ /* A normal declarator with an identifier. */
+ C_DTR_NORMAL,
+ /* An abstract declarator (maybe empty). */
+ C_DTR_ABSTRACT,
+ /* A parameter declarator: may be either, but after a type name does
+ not redeclare a typedef name as an identifier if it can
+ alternatively be interpreted as a typedef name; see DR#009,
+ applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
+ following DR#249. For example, given a typedef T, "int T" and
+ "int *T" are valid parameter declarations redeclaring T, while
+ "int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
+ abstract declarators rather than involving redundant parentheses;
+ the same applies with attributes inside the parentheses before
+ "T". */
+ C_DTR_PARM
+};
+
+/* The binary operation precedence levels, where 0 is a dummy lowest level
+ used for the bottom of the stack. */
+enum c_parser_prec {
+ PREC_NONE,
+ PREC_LOGOR,
+ PREC_LOGAND,
+ PREC_BITOR,
+ PREC_BITXOR,
+ PREC_BITAND,
+ PREC_EQ,
+ PREC_REL,
+ PREC_SHIFT,
+ PREC_ADD,
+ PREC_MULT,
+ NUM_PRECS
+};
+
+enum c_lookahead_kind {
+ /* Always treat unknown identifiers as typenames. */
+ cla_prefer_type,
+
+ /* Could be parsing a nonabstract declarator. Only treat an identifier
+ as a typename if followed by another identifier or a star. */
+ cla_nonabstract_decl,
+
+ /* Never treat identifiers as typenames. */
+ cla_prefer_id
+};
+
+
+extern c_token * c_parser_peek_token (c_parser *parser);
+extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
+ const char *msgid);
+extern void c_parser_error (c_parser *parser, const char *gmsgid);
+extern void c_parser_consume_token (c_parser *parser);
+extern void c_parser_skip_until_found (c_parser *parser, enum cpp_ttype type,
+ const char *msgid);
+extern bool c_parser_next_token_starts_declspecs (c_parser *parser);
+extern c_token * c_parser_peek_2nd_token (c_parser *parser);
+bool c_parser_next_tokens_start_declaration (c_parser *parser);
+bool c_token_starts_typename (c_token *token);
+
+/* Return true if the next token from PARSER has the indicated
+ TYPE. */
+
+static inline bool
+c_parser_next_token_is (c_parser *parser, enum cpp_ttype type)
+{
+ return c_parser_peek_token (parser)->type == type;
+}
+
+/* Return true if the next token from PARSER does not have the
+ indicated TYPE. */
+
+static inline bool
+c_parser_next_token_is_not (c_parser *parser, enum cpp_ttype type)
+{
+ return !c_parser_next_token_is (parser, type);
+}
+
+/* Return true if the next token from PARSER is the indicated
+ KEYWORD. */
+
+static inline bool
+c_parser_next_token_is_keyword (c_parser *parser, enum rid keyword)
+{
+ return c_parser_peek_token (parser)->keyword == keyword;
+}
+
+extern struct c_declarator *
+c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
+ bool *seen_id);
+extern void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
+ bool, bool, bool, enum c_lookahead_kind);
+extern struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
+
+#endif
@@ -29,4 +29,4 @@ compilers="cc1\$(exeext)"
target_libs=
-gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h"
+gtfiles="\$(srcdir)/c/c-lang.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/c/c-objc-common.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-lang.h"
new file mode 100644
@@ -0,0 +1,1385 @@
+/* Parser for GIMPLE.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "function.h"
+#include "c-tree.h"
+#include "timevar.h"
+#include "stringpool.h"
+#include "cgraph.h"
+#include "attribs.h"
+#include "stor-layout.h"
+#include "varasm.h"
+#include "trans-mem.h"
+#include "c-family/c-pragma.h"
+#include "c-lang.h"
+#include "c-family/c-objc.h"
+#include "plugin.h"
+#include "omp-low.h"
+#include "builtins.h"
+#include "gomp-constants.h"
+#include "c-family/c-indentation.h"
+#include "gimple-expr.h"
+#include "context.h"
+#include "gcc-rich-location.h"
+#include "c-parser.h"
+#include "tree-vrp.h"
+#include "tree-pass.h"
+#include "tree-pretty-print.h"
+#include "tree.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "gimple-pretty-print.h"
+#include "tree-ssa.h"
+#include "pass_manager.h"
+#include "tree-ssanames.h"
+#include "gimple-ssa.h"
+#include "tree-dfa.h"
+
+
+/* Gimple parsing functions. */
+static bool c_parser_gimple_compound_statement (c_parser *, gimple_seq *);
+static void c_parser_gimple_label (c_parser *, gimple_seq *);
+static void c_parser_gimple_expression (c_parser *, gimple_seq *);
+static struct c_expr c_parser_gimple_binary_expression (c_parser *, enum tree_code *);
+static struct c_expr c_parser_gimple_unary_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression (c_parser *);
+static struct c_expr c_parser_gimple_postfix_expression_after_primary (c_parser *,
+ location_t,
+ struct c_expr);
+static opt_pass *c_parser_gimple_pass_list_params (c_parser *, opt_pass **);
+static void c_parser_gimple_declaration (c_parser *);
+static void c_parser_gimple_goto_stmt (location_t, tree, gimple_seq *);
+static void c_parser_gimple_if_stmt (c_parser *, gimple_seq *);
+static void c_parser_gimple_switch_stmt (c_parser *, gimple_seq *);
+static void c_parser_gimple_return_stmt (c_parser *, gimple_seq *);
+static void c_finish_gimple_return (location_t, tree);
+static c_expr c_parser_parse_ssa_names (c_parser *);
+static tree c_parser_gimple_paren_condition (c_parser *);
+static vec<tree, va_gc> *c_parser_gimple_expr_list (c_parser *,
+ vec<tree, va_gc> **, vec<location_t> *);
+
+
+/* Parse the body of a function declaration marked with "__GIMPLE". */
+
+void
+c_parser_parse_gimple_body (c_parser *parser)
+{
+ gimple_seq seq = NULL;
+ gimple_seq body = NULL;
+ tree stmt = push_stmt_list ();
+ push_scope ();
+ location_t loc1 = c_parser_peek_token (parser)->location;
+
+ init_tree_ssa (cfun);
+
+ if (! c_parser_gimple_compound_statement (parser, &seq))
+ {
+ gimple *ret = gimple_build_return (NULL);
+ gimple_seq_add_stmt (&seq, ret);
+ }
+
+ tree block = pop_scope ();
+ stmt = pop_stmt_list (stmt);
+ stmt = c_build_bind_expr (loc1, block, stmt);
+
+ block = DECL_INITIAL (current_function_decl);
+ BLOCK_SUBBLOCKS (block) = NULL_TREE;
+ BLOCK_CHAIN (block) = NULL_TREE;
+ TREE_ASM_WRITTEN (block) = 1;
+
+ gbind *bind_stmt = gimple_build_bind (BIND_EXPR_VARS (stmt), NULL,
+ BIND_EXPR_BLOCK (stmt));
+ gimple_bind_set_body (bind_stmt, seq);
+ gimple_seq_add_stmt (&body, bind_stmt);
+ gimple_set_body (current_function_decl, body);
+ cfun->curr_properties = PROP_gimple_any;
+
+ return;
+}
+
+/* Parse a compound statement in gimple function body.
+
+ gimple-statement:
+ gimple-statement
+ gimple-declaration-statement
+ gimple-if-statement
+ gimple-switch-statement
+ gimple-labeled-statement
+ gimple-expression-statement
+ gimple-goto-statement
+ gimple-phi-statement
+ gimple-return-statement
+*/
+
+static bool
+c_parser_gimple_compound_statement (c_parser *parser, gimple_seq *seq)
+{
+ bool return_p = false;
+
+ if (! c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ return false;
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ c_parser_consume_token (parser);
+ return false;
+ }
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
+ {
+ c_parser_error (parser, "expected declaration or statement");
+ c_parser_consume_token (parser);
+ return false;
+ }
+
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+ {
+ if (parser->error)
+ {
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
+ return return_p;
+ }
+
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ c_parser_gimple_label (parser, seq);
+
+ else if (c_parser_next_tokens_start_declaration (parser))
+ c_parser_gimple_declaration (parser);
+
+ else if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ c_parser_error (parser, "expected declaration or statement");
+ return return_p;
+ }
+
+ else
+ {
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_KEYWORD:
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_IF:
+ c_parser_gimple_if_stmt (parser, seq);
+ break;
+ case RID_SWITCH:
+ c_parser_gimple_switch_stmt (parser, seq);
+ break;
+ case RID_GOTO:
+ {
+ location_t loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_gimple_goto_stmt (loc,
+ c_parser_peek_token
+ (parser)->value,
+ seq);
+ c_parser_consume_token (parser);
+ if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<;%>"))
+ return return_p;
+ }
+ }
+ break;
+ case RID_RETURN:
+ return_p = true;
+ c_parser_gimple_return_stmt (parser, seq);
+ if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<;%>"))
+ return return_p;
+ break;
+ default:
+ goto expr_stmt;
+ }
+ break;
+ case CPP_SEMICOLON:
+ c_parser_consume_token (parser);
+ break;
+ default:
+ expr_stmt:
+ c_parser_gimple_expression (parser, seq);
+ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ return return_p;
+ }
+ }
+ }
+ c_parser_consume_token (parser);
+ return return_p;
+}
+
+/* Parse a gimple expression.
+
+ gimple-expression:
+ gimple-unary-expression
+ gimple-call-statement
+ gimple-binary-expression
+ gimple-assign-expression
+ gimple-cast-expression
+
+*/
+
+static void
+c_parser_gimple_expression (c_parser *parser, gimple_seq *seq)
+{
+ struct c_expr lhs, rhs;
+ gimple *assign = NULL;
+ enum tree_code subcode = NOP_EXPR;
+ location_t loc;
+ tree arg = NULL_TREE;
+ auto_vec<tree> vargs;
+
+ lhs = c_parser_gimple_unary_expression (parser);
+ rhs.value = error_mark_node;
+
+ if (c_parser_next_token_is (parser, CPP_EQ))
+ c_parser_consume_token (parser);
+
+ loc = EXPR_LOCATION (lhs.value);
+
+ /* GIMPLE call expression. */
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON)
+ && TREE_CODE (lhs.value) == CALL_EXPR)
+ {
+ gimple *call;
+ call = gimple_build_call_from_tree (lhs.value);
+ gimple_seq_add_stmt (seq, call);
+ gimple_set_location (call, loc);
+ return;
+ }
+
+ /* Cast expression. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
+ && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
+ {
+ /* TODO: have a gimple_cast_expr function. */
+ rhs = c_parser_cast_expression (parser, NULL);
+ if (lhs.value != error_mark_node &&
+ rhs.value != error_mark_node)
+ {
+ assign = gimple_build_assign (lhs.value, rhs.value);
+ gimple_seq_add_stmt (seq, assign);
+ gimple_set_location (assign, loc);
+ return;
+ }
+ }
+
+ if (POINTER_TYPE_P (TREE_TYPE (lhs.value)))
+ {
+ STRIP_USELESS_TYPE_CONVERSION (rhs.value);
+ if (! useless_type_conversion_p (TREE_TYPE (lhs.value),
+ TREE_TYPE (rhs.value)))
+ rhs.value = fold_convert_loc (loc, TREE_TYPE (lhs.value), rhs.value);
+ }
+
+ /* Pointer expression. */
+ if (TREE_CODE (lhs.value) == INDIRECT_REF)
+ {
+ tree save_expr = lhs.value;
+ bool volatilep = TREE_THIS_VOLATILE (lhs.value);
+ bool notrap = TREE_THIS_NOTRAP (lhs.value);
+ tree saved_ptr_type = TREE_TYPE (TREE_OPERAND (lhs.value, 0));
+
+ lhs.value = fold_indirect_ref_loc (loc, lhs.value);
+ if (lhs.value == save_expr)
+ {
+ lhs.value = fold_build2_loc (input_location, MEM_REF,
+ TREE_TYPE (lhs.value),
+ TREE_OPERAND (lhs.value, 0),
+ build_int_cst (saved_ptr_type, 0));
+ TREE_THIS_VOLATILE (lhs.value) = volatilep;
+ TREE_THIS_NOTRAP (lhs.value) = notrap;
+ }
+ }
+
+ if (c_parser_next_token_is (parser, CPP_AND)
+ || c_parser_next_token_is (parser, CPP_MULT)
+ || c_parser_next_token_is (parser, CPP_PLUS)
+ || c_parser_next_token_is (parser, CPP_MINUS)
+ || c_parser_next_token_is (parser, CPP_COMPL)
+ || c_parser_next_token_is (parser, CPP_NOT))
+ {
+ rhs = c_parser_gimple_unary_expression (parser);
+ assign = gimple_build_assign (lhs.value, rhs.value);
+ gimple_set_location (assign, loc);
+ gimple_seq_add_stmt (seq, assign);
+ return;
+ }
+
+ /* GIMPLE PHI expression. */
+ if (c_parser_next_token_is_keyword (parser, RID_PHI))
+ {
+ c_parser_consume_token (parser);
+
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return;
+
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ c_parser_consume_token (parser);
+
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+ {
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ {
+ arg = lookup_label_for_goto (loc,
+ c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ c_parser_consume_token (parser);
+ vargs.safe_push (arg);
+ }
+ else if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ {
+ arg = c_parser_parse_ssa_names (parser).value;
+ vargs.safe_push (arg);
+ }
+ }
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+
+ /* Build internal function for PHI. */
+ gcall *call_stmt = gimple_build_call_internal_vec (IFN_PHI, vargs);
+ gimple_call_set_lhs (call_stmt, lhs.value);
+ gimple_set_location (call_stmt, UNKNOWN_LOCATION);
+ gimple_seq_add_stmt (seq, call_stmt);
+ return;
+ }
+
+ /* GIMPLE call with lhs. */
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
+ && lookup_name (c_parser_peek_token (parser)->value))
+ {
+ rhs = c_parser_gimple_unary_expression (parser);
+ gimple *call = gimple_build_call_from_tree (rhs.value);
+ gimple_call_set_lhs (call, lhs.value);
+ gimple_seq_add_stmt (seq, call);
+ gimple_set_location (call, loc);
+ return;
+ }
+
+ rhs = c_parser_gimple_binary_expression (parser, &subcode);
+
+ if (lhs.value != error_mark_node
+ && rhs.value != error_mark_node)
+ {
+ if (subcode == NOP_EXPR)
+ assign = gimple_build_assign (lhs.value, rhs.value);
+ else
+ assign = gimple_build_assign (lhs.value, subcode,
+ TREE_OPERAND (rhs.value, 0),
+ TREE_OPERAND (rhs.value, 1));
+ gimple_seq_add_stmt (seq, assign);
+ gimple_set_location (assign, loc);
+ }
+ return;
+}
+
+/* Parse gimple binary expr.
+
+ gimple-multiplicative-expression:
+ gimple-unary-expression * gimple-unary-expression
+ gimple-unary-expression / gimple-unary-expression
+ gimple-unary-expression % gimple-unary-expression
+
+ gimple-additive-expression:
+ gimple-unary-expression + gimple-unary-expression
+ gimple-unary-expression - gimple-unary-expression
+
+ gimple-shift-expression:
+ gimple-unary-expression << gimple-unary-expression
+ gimple-unary-expression >> gimple-unary-expression
+
+ gimple-relational-expression:
+ gimple-unary-expression < gimple-unary-expression
+ gimple-unary-expression > gimple-unary-expression
+ gimple-unary-expression <= gimple-unary-expression
+ gimple-unary-expression >= gimple-unary-expression
+
+ gimple-equality-expression:
+ gimple-unary-expression == gimple-unary-expression
+ gimple-unary-expression != gimple-unary-expression
+
+ gimple-AND-expression:
+ gimple-unary-expression & gimple-unary-expression
+
+ gimple-exclusive-OR-expression:
+ gimple-unary-expression ^ gimple-unary-expression
+
+ gimple-inclusive-OR-expression:
+ gimple-unary-expression | gimple-unary-expression
+
+ gimple-logical-AND-expression:
+ gimple-unary-expression && gimple-unary-expression
+
+ gimple-logical-OR-expression:
+ gimple-unary-expression || gimple-unary-expression
+
+*/
+
+static c_expr
+c_parser_gimple_binary_expression (c_parser *parser, enum tree_code *subcode)
+{
+ struct {
+ /* The expression at this stack level. */
+ struct c_expr expr;
+ /* The operation on its left. */
+ enum tree_code op;
+ /* The source location of this operation. */
+ location_t loc;
+ } stack[2];
+ int sp;
+ /* Location of the binary operator. */
+ location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
+#define POP \
+ do { \
+ if (sp == 1 \
+ && c_parser_peek_token (parser)->type == CPP_SEMICOLON \
+ && (((1 << PREC_BITOR) | (1 << PREC_BITXOR) | (1 << PREC_BITAND) \
+ | (1 << PREC_SHIFT) | (1 << PREC_ADD) | (1 << PREC_MULT))) \
+ && stack[sp].op != TRUNC_MOD_EXPR \
+ && stack[0].expr.value != error_mark_node \
+ && stack[1].expr.value != error_mark_node) \
+ stack[0].expr.value \
+ = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \
+ stack[0].expr.value, stack[1].expr.value); \
+ else \
+ stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
+ stack[sp].op, \
+ stack[sp - 1].expr, \
+ stack[sp].expr); \
+ sp--; \
+ } while (0)
+ stack[0].loc = c_parser_peek_token (parser)->location;
+ stack[0].expr = c_parser_gimple_unary_expression (parser);
+ sp = 0;
+ source_range src_range;
+ if (parser->error)
+ goto out;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_MULT:
+ *subcode = MULT_EXPR;
+ break;
+ case CPP_DIV:
+ *subcode = TRUNC_DIV_EXPR;
+ break;
+ case CPP_MOD:
+ *subcode = TRUNC_MOD_EXPR;
+ break;
+ case CPP_PLUS:
+ *subcode = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ *subcode = MINUS_EXPR;
+ break;
+ case CPP_LSHIFT:
+ *subcode = LSHIFT_EXPR;
+ break;
+ case CPP_RSHIFT:
+ *subcode = RSHIFT_EXPR;
+ break;
+ case CPP_LESS:
+ *subcode = LT_EXPR;
+ break;
+ case CPP_GREATER:
+ *subcode = GT_EXPR;
+ break;
+ case CPP_LESS_EQ:
+ *subcode = LE_EXPR;
+ break;
+ case CPP_GREATER_EQ:
+ *subcode = GE_EXPR;
+ break;
+ case CPP_EQ_EQ:
+ *subcode = EQ_EXPR;
+ break;
+ case CPP_NOT_EQ:
+ *subcode = NE_EXPR;
+ break;
+ case CPP_AND:
+ *subcode = BIT_AND_EXPR;
+ break;
+ case CPP_XOR:
+ *subcode = BIT_XOR_EXPR;
+ break;
+ case CPP_OR:
+ *subcode = BIT_IOR_EXPR;
+ break;
+ case CPP_AND_AND:
+ *subcode = TRUTH_ANDIF_EXPR;
+ break;
+ case CPP_OR_OR:
+ *subcode = TRUTH_ORIF_EXPR;
+ break;
+ default:
+ /* Not a binary operator, so end of the binary expression. */
+ *subcode = NOP_EXPR;
+ goto out;
+ }
+ binary_loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ switch (*subcode)
+ {
+ case TRUTH_ANDIF_EXPR:
+ src_range = stack[sp].expr.src_range;
+ stack[sp].expr.value = c_objc_common_truthvalue_conversion
+ (stack[sp].loc, default_conversion (stack[sp].expr.value));
+ set_c_expr_source_range (&stack[sp].expr, src_range);
+ break;
+ case TRUTH_ORIF_EXPR:
+ src_range = stack[sp].expr.src_range;
+ stack[sp].expr.value = c_objc_common_truthvalue_conversion
+ (stack[sp].loc, default_conversion (stack[sp].expr.value));
+ set_c_expr_source_range (&stack[sp].expr, src_range);
+ break;
+ default:
+ break;
+ }
+ sp++;
+ stack[sp].loc = binary_loc;
+ stack[sp].expr = c_parser_gimple_unary_expression (parser);
+ stack[sp].op = *subcode;
+out:
+ while (sp > 0)
+ POP;
+ return stack[0].expr;
+#undef POP
+}
+
+/* Parse gimple unary expression.
+
+ gimple-unary-expression:
+ gimple-postfix-expression
+ unary-operator cast-expression
+
+ unary-operator: one of
+ & * + - ~ !
+*/
+
+static c_expr
+c_parser_gimple_unary_expression (c_parser *parser)
+{
+ struct c_expr ret, op;
+ if (c_parser_peek_token (parser)->value
+ && TREE_CODE (c_parser_peek_token (parser)->value) == IDENTIFIER_NODE
+ && ! lookup_name (c_parser_peek_token (parser)->value))
+ return c_parser_parse_ssa_names (parser);
+
+ location_t op_loc = c_parser_peek_token (parser)->location;
+ location_t finish;
+ ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_AND:
+ c_parser_consume_token (parser);
+ op = c_parser_cast_expression (parser, NULL);
+ mark_exp_read (op.value);
+ return parser_build_unary_op (op_loc, ADDR_EXPR, op);
+ case CPP_MULT:
+ {
+ c_parser_consume_token (parser);
+ op = c_parser_cast_expression (parser, NULL);
+ finish = op.get_finish ();
+ location_t combined_loc = make_location (op_loc, op_loc, finish);
+ ret.value = build_indirect_ref (combined_loc, op.value,
+ RO_UNARY_STAR);
+ ret.src_range.m_start = op_loc;
+ ret.src_range.m_finish = finish;
+ return ret;
+ }
+ case CPP_PLUS:
+ c_parser_consume_token (parser);
+ op = c_parser_cast_expression (parser, NULL);
+ return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
+ case CPP_MINUS:
+ c_parser_consume_token (parser);
+ op = c_parser_cast_expression (parser, NULL);
+ return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
+ case CPP_COMPL:
+ c_parser_consume_token (parser);
+ op = c_parser_cast_expression (parser, NULL);
+ return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
+ case CPP_NOT:
+ c_parser_consume_token (parser);
+ op = c_parser_cast_expression (parser, NULL);
+ return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
+ default:
+ return c_parser_gimple_postfix_expression (parser);
+ }
+}
+
+/* Parse gimple ssa names. */
+
+static c_expr
+c_parser_parse_ssa_names (c_parser *parser)
+{
+ tree id = NULL_TREE;
+ c_expr ret;
+ char *var_name = NULL, *var_version = NULL, *token = NULL;
+ ret.original_code = ERROR_MARK;
+ ret.original_type = NULL;
+
+ /* SSA token string. */
+ const char *ssa_token
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ token = new char [strlen (ssa_token) + 1];
+ strcpy (token, ssa_token);
+
+ /* Separate var name and version. */
+ var_version = strrchr (token, '_');
+ if (var_version)
+ {
+ var_name = new char[var_version - token + 1];
+ memcpy (var_name, token, var_version - token);
+ var_name[var_version - token] = '\0';
+ id = get_identifier (var_name);
+
+ /* lookup for parent decl. */
+ if (lookup_name (id))
+ {
+ var_version++;
+ unsigned int version;
+ version = atoi (var_version);
+ if (var_version && version)
+ {
+ ret.value = NULL_TREE;
+ if (version < num_ssa_names)
+ ret.value = ssa_name (version);
+ if (! ret.value)
+ ret.value = make_ssa_name_fn (cfun, lookup_name (id),
+ gimple_build_nop (), version);
+ c_parser_consume_token (parser);
+ }
+ }
+ }
+
+ /* For default definition SSA names. */
+ if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+ {
+ c_parser_consume_token (parser);
+ ssa_token = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (! strcmp ("D", ssa_token))
+ {
+ set_ssa_default_def (cfun, lookup_name (id), ret.value);
+ c_parser_consume_token (parser);
+ }
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ goto out;
+ }
+
+ out:
+ free (var_name);
+ free (token);
+ return ret;
+}
+
+/* Parse gimple postfix expression.
+
+ gimple-postfix-expression:
+ gimple-primary-expression
+ gimple-primary-xpression [ gimple-primary-expression ]
+ gimple-primary-expression ( gimple-argument-expression-list[opt] )
+
+ gimple-argument-expression-list:
+ gimple-unary-expression
+ gimple-argument-expression-list , gimple-unary-expression
+
+ gimple-primary-expression:
+ identifier
+ constant
+ string-literal
+
+*/
+
+static struct c_expr
+c_parser_gimple_postfix_expression (c_parser *parser)
+{
+ struct c_expr expr;
+ location_t loc = c_parser_peek_token (parser)->location;
+ source_range tok_range = c_parser_peek_token (parser)->get_range ();
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_NUMBER:
+ expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_CHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
+ case CPP_WCHAR:
+ expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
+ c_parser_consume_token (parser);
+ break;
+ case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
+ case CPP_WSTRING:
+ case CPP_UTF8STRING:
+ expr.value = c_parser_peek_token (parser)->value;
+ set_c_expr_source_range (&expr, tok_range);
+ expr.original_code = STRING_CST;
+ c_parser_consume_token (parser);
+ break;
+ case CPP_NAME:
+ if (c_parser_peek_token (parser)->id_kind == C_ID_ID)
+ {
+ tree id = c_parser_peek_token (parser)->value;
+ c_parser_consume_token (parser);
+ expr.value = build_external_ref (loc, id,
+ (c_parser_peek_token (parser)->type
+ == CPP_OPEN_PAREN),
+ &expr.original_type);
+ set_c_expr_source_range (&expr, tok_range);
+ break;
+ }
+ else
+ {
+ c_parser_error (parser, "expected expression");
+ expr.set_error ();
+ break;
+ }
+ break;
+ default:
+ c_parser_error (parser, "expected expression");
+ expr.set_error ();
+ break;
+ }
+ return c_parser_gimple_postfix_expression_after_primary
+ (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
+}
+
+/* Parse a gimple postfix expression after the initial primary or compound
+ literal. */
+
+static struct c_expr
+c_parser_gimple_postfix_expression_after_primary (c_parser *parser,
+ location_t expr_loc,
+ struct c_expr expr)
+{
+ struct c_expr orig_expr;
+ vec<tree, va_gc> *exprlist;
+ vec<tree, va_gc> *origtypes = NULL;
+ vec<location_t> arg_loc = vNULL;
+ location_t start;
+ location_t finish;
+
+ location_t op_loc = c_parser_peek_token (parser)->location;
+
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_OPEN_SQUARE:
+ {
+ c_parser_consume_token (parser);
+ tree idx = c_parser_gimple_unary_expression (parser).value;
+
+ if (! c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>"))
+ break;
+
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].location;
+ expr.value = build_array_ref (op_loc, expr.value, idx);
+ set_c_expr_source_range (&expr, start, finish);
+
+ expr.original_code = ERROR_MARK;
+ expr.original_type = NULL;
+ break;
+ }
+ case CPP_OPEN_PAREN:
+ {
+ /* Function call. */
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ exprlist = NULL;
+ else
+ exprlist = c_parser_gimple_expr_list (parser, &origtypes,
+ &arg_loc);
+ c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
+ "expected %<)%>");
+ orig_expr = expr;
+ start = expr.get_start ();
+ finish = parser->tokens_buf[0].get_finish ();
+ expr.value = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
+ exprlist, origtypes);
+ set_c_expr_source_range (&expr, start, finish);
+
+ expr.original_code = ERROR_MARK;
+ if (TREE_CODE (expr.value) == INTEGER_CST
+ && TREE_CODE (orig_expr.value) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
+ && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+ expr.original_code = C_MAYBE_CONST_EXPR;
+ expr.original_type = NULL;
+ if (exprlist)
+ {
+ release_tree_vector (exprlist);
+ release_tree_vector (origtypes);
+ }
+ arg_loc.release ();
+ break;
+ default:
+ return expr;
+ }
+ }
+ return expr;
+}
+
+/* Parse expression list.
+
+ gimple-expr-list:
+ gimple-unary-expression
+ gimple-expr-list , gimple-unary-expression
+
+ */
+
+static vec<tree, va_gc> *
+c_parser_gimple_expr_list (c_parser *parser, vec<tree, va_gc> **p_orig_types,
+ vec<location_t> *locations)
+{
+ vec<tree, va_gc> *ret;
+ vec<tree, va_gc> *orig_types;
+ struct c_expr expr;
+ location_t loc = c_parser_peek_token (parser)->location;
+
+ ret = make_tree_vector ();
+ if (p_orig_types == NULL)
+ orig_types = NULL;
+ else
+ orig_types = make_tree_vector ();
+
+ expr = c_parser_gimple_unary_expression (parser);
+ vec_safe_push (ret, expr.value);
+ if (orig_types)
+ vec_safe_push (orig_types, expr.original_type);
+ if (locations)
+ locations->safe_push (loc);
+ while (c_parser_next_token_is (parser, CPP_COMMA))
+ {
+ c_parser_consume_token (parser);
+ loc = c_parser_peek_token (parser)->location;
+ expr = c_parser_gimple_unary_expression (parser);
+ vec_safe_push (ret, expr.value);
+ if (orig_types)
+ vec_safe_push (orig_types, expr.original_type);
+ if (locations)
+ locations->safe_push (loc);
+ }
+ if (orig_types)
+ *p_orig_types = orig_types;
+ return ret;
+}
+
+/* Parse gimple label.
+
+ gimple-label:
+ identifier :
+ case constant-expression :
+ default :
+
+*/
+
+static void
+c_parser_gimple_label (c_parser *parser, gimple_seq *seq)
+{
+ tree name = c_parser_peek_token (parser)->value;
+ location_t loc1 = c_parser_peek_token (parser)->location;
+ gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
+ c_parser_consume_token (parser);
+ gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
+ c_parser_consume_token (parser);
+ tree label = define_label (loc1, name);
+ gimple_seq_add_stmt (seq, gimple_build_label (label));
+ return;
+}
+
+/* Parse gimple pass list.
+
+ gimple-pass-list:
+ startwith("pass-name")
+ */
+
+void
+c_parser_gimple_pass_list (c_parser *parser, opt_pass **pass,
+ bool *startwith_p)
+{
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return;
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ return;
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ if (! strcmp (op, "startwith"))
+ {
+ *pass = c_parser_gimple_pass_list_params (parser, pass);
+ if (! *pass)
+ return;
+
+ *startwith_p = true;
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return;
+ }
+ else
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "invalid operation");
+ return;
+ }
+ }
+ else if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ c_parser_error (parser, "expected parameters");
+ return;
+ }
+
+ return;
+}
+
+/* Support function for c_parser_gimple_pass_list. */
+
+static opt_pass *
+c_parser_gimple_pass_list_params (c_parser *parser, opt_pass **pass)
+{
+ opt_pass *pass_start = NULL, *new_pass;
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return NULL;
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ return NULL;
+
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+ {
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "expected pass names");
+ return NULL;
+ }
+
+ if (c_parser_next_token_is (parser, CPP_STRING))
+ {
+ const char *name = NULL;
+ name = TREE_STRING_POINTER (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ new_pass = g->get_passes ()->get_pass_by_name (name);
+
+ if (! new_pass)
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "invalid pass name");
+ parser->error = true;
+ c_parser_consume_token (parser);
+ return NULL;
+ }
+ if (*pass)
+ {
+ (*pass)->next = new_pass;
+ (*pass) = (*pass)->next;
+ }
+ else
+ {
+ *pass = new_pass;
+ pass_start = *pass;
+ }
+ }
+ else if (c_parser_next_token_is (parser, CPP_COMMA))
+ c_parser_consume_token (parser);
+ else
+ {
+ error_at (c_parser_peek_token (parser)->location,
+ "invalid pass name");
+ c_parser_consume_token (parser);
+ return NULL;
+ }
+ }
+ return pass_start;
+}
+
+/* Parse gimple local declaration.
+
+ declaration-specifiers:
+ storage-class-specifier declaration-specifiers[opt]
+ type-specifier declaration-specifiers[opt]
+ type-qualifier declaration-specifiers[opt]
+ function-specifier declaration-specifiers[opt]
+ alignment-specifier declaration-specifiers[opt]
+
+ storage-class-specifier:
+ typedef
+ extern
+ static
+ auto
+ register
+
+ type-specifier:
+ void
+ char
+ short
+ int
+ long
+ float
+ double
+ signed
+ unsigned
+ _Bool
+ _Complex
+
+ type-qualifier:
+ const
+ restrict
+ volatile
+ address-space-qualifier
+ _Atomic
+
+ */
+
+static void
+c_parser_gimple_declaration (c_parser *parser)
+{
+ struct c_declarator *declarator;
+ struct c_declspecs *specs = build_null_declspecs ();
+ c_parser_declspecs (parser, specs, true, true, true,
+ true, true, cla_nonabstract_decl);
+ finish_declspecs (specs);
+
+ /* Provide better error recovery. Note that a type name here is usually
+ better diagnosed as a redeclaration. */
+ if (c_parser_next_token_starts_declspecs (parser)
+ && ! c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_error (parser, "expected %<;%>");
+ parser->error = false;
+ return;
+ }
+
+ bool dummy = false;
+ declarator = c_parser_declarator (parser,
+ specs->typespec_kind != ctsk_none,
+ C_DTR_NORMAL, &dummy);
+
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ tree postfix_attrs = NULL_TREE;
+ tree all_prefix_attrs = specs->attrs;
+ specs->attrs = NULL;
+ tree decl = start_decl (declarator, specs, false,
+ chainon (postfix_attrs, all_prefix_attrs));
+ if (decl)
+ finish_decl (decl, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, NULL_TREE);
+ }
+ else
+ {
+ c_parser_error (parser, "expected %<;%>");
+ return;
+ }
+}
+
+/* Parse gimple goto statement. */
+
+static void
+c_parser_gimple_goto_stmt (location_t loc, tree label, gimple_seq *seq)
+{
+ tree decl = lookup_label_for_goto (loc, label);
+ gimple_seq_add_stmt (seq, gimple_build_goto (decl));
+ return;
+}
+
+/* Parse a parenthesized condition.
+ gimple-condition:
+ ( gimple-binary-expression ) */
+
+static tree
+c_parser_gimple_paren_condition (c_parser *parser)
+{
+ enum tree_code subcode = NOP_EXPR;
+ location_t loc = c_parser_peek_token (parser)->location;
+ if (! c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return error_mark_node;
+ tree cond = c_parser_gimple_binary_expression (parser, &subcode).value;
+ cond = c_objc_common_truthvalue_conversion (loc, cond);
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return error_mark_node;
+ return cond;
+}
+
+/* Parse gimple if-else statement.
+
+ if-statement:
+ if ( gimple-binary-expression ) gimple-goto-statement
+ if ( gimple-binary-expression ) gimple-goto-statement \
+ else gimple-goto-statement
+ */
+
+static void
+c_parser_gimple_if_stmt (c_parser *parser, gimple_seq *seq)
+{
+ tree t_label, f_label, label;
+ location_t loc;
+ c_parser_consume_token (parser);
+ tree cond = c_parser_gimple_paren_condition (parser);
+
+ if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+ {
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ label = c_parser_peek_token (parser)->value;
+ t_label = lookup_label_for_goto (loc, label);
+ c_parser_consume_token (parser);
+ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ return;
+ }
+ else
+ {
+ c_parser_error (parser, "expected goto expression");
+ return;
+ }
+
+ if (c_parser_next_token_is_keyword (parser, RID_ELSE))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_parser_error (parser, "expected else statement");
+ return;
+ }
+
+ if (c_parser_next_token_is_keyword (parser, RID_GOTO))
+ {
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ label = c_parser_peek_token (parser)->value;
+ f_label = lookup_label_for_goto (loc, label);
+ c_parser_consume_token (parser);
+ if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
+ return;
+ }
+ else
+ {
+ c_parser_error (parser, "expected goto expression");
+ return;
+ }
+
+ gimple_seq_add_stmt (seq, gimple_build_cond_from_tree (cond, t_label,
+ f_label));
+}
+
+/* Parse gimple switch-statement.
+
+ gimple-switch-statement:
+ switch (gimple-unary-expression) gimple-case-statement
+
+ gimple-case-statement:
+ gimple-case-statement
+ gimple-label-statement : gimple-goto-statment
+*/
+
+static void
+c_parser_gimple_switch_stmt (c_parser *parser, gimple_seq *seq)
+{
+ c_expr cond_expr;
+ tree case_label, label;
+ auto_vec<tree> labels;
+ tree default_label = NULL_TREE;
+ gimple_seq switch_body = NULL;
+ location_t loc;
+ c_parser_consume_token (parser);
+
+ if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ cond_expr = c_parser_gimple_unary_expression (parser);
+ if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return;
+ }
+
+ if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
+ {
+ if (c_parser_next_token_is (parser, CPP_EOF))
+ {
+ c_parser_error (parser, "expected statement");
+ return;
+ }
+
+ switch (c_parser_peek_token (parser)->keyword)
+ {
+ case RID_CASE:
+ {
+ c_expr exp1;
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ || c_parser_peek_token (parser)->type == CPP_NUMBER)
+ exp1 = c_parser_gimple_unary_expression (parser);
+ else
+ c_parser_error (parser, "expected expression");
+
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ label = create_artificial_label (loc);
+ case_label = build_case_label (exp1.value, NULL_TREE,
+ label);
+ labels.safe_push (case_label);
+ gimple_seq_add_stmt (&switch_body,
+ gimple_build_label
+ (CASE_LABEL (case_label)));
+ }
+ else if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<:%>"))
+ return;
+ break;
+ }
+ case RID_DEFAULT:
+ {
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_COLON))
+ {
+ c_parser_consume_token (parser);
+ default_label = build_case_label (NULL_TREE, NULL_TREE,
+ create_artificial_label
+ (UNKNOWN_LOCATION));
+ gimple_seq_add_stmt (&switch_body,
+ gimple_build_label
+ (CASE_LABEL (default_label)));
+ }
+ else if (! c_parser_require (parser, CPP_SEMICOLON,
+ "expected %<:%>"))
+ return;
+ break;
+ }
+ case RID_GOTO:
+ {
+ loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ c_parser_gimple_goto_stmt (loc,
+ c_parser_peek_token
+ (parser)->value,
+ &switch_body);
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ c_parser_consume_token (parser);
+ else
+ {
+ c_parser_error (parser, "expected semicolon");
+ return;
+ }
+ }
+ else if (! c_parser_require (parser, CPP_NAME,
+ "expected label"))
+ return;
+ break;
+ }
+ default:
+ c_parser_error (parser, "expected case label or goto statement");
+ return;
+ }
+
+ }
+ }
+ if (! c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
+ return;
+ gimple_seq_add_stmt (seq, gimple_build_switch (cond_expr.value,
+ default_label, labels));
+ gimple_seq_add_seq (seq, switch_body);
+ labels.release();
+}
+
+/* Parse gimple return statement. */
+
+static void
+c_parser_gimple_return_stmt (c_parser *parser, gimple_seq *seq)
+{
+ location_t loc = c_parser_peek_token (parser)->location;
+ gimple *ret = NULL;
+ c_parser_consume_token (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ {
+ c_finish_gimple_return (loc, NULL_TREE);
+ ret = gimple_build_return (NULL);
+ gimple_seq_add_stmt (seq, ret);
+ }
+ else
+ {
+ location_t xloc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_gimple_unary_expression (parser);
+ c_finish_gimple_return (xloc, expr.value);
+ ret = gimple_build_return (expr.value);
+ gimple_seq_add_stmt (seq, ret);
+ }
+}
+
+/* Support function for c_parser_gimple_return_stmt. */
+
+static void
+c_finish_gimple_return (location_t loc, tree retval)
+{
+ tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl));
+
+ /* Use the expansion point to handle cases such as returning NULL
+ in a function returning void. */
+ source_location xloc = expansion_point_location_if_in_system_header (loc);
+
+ if (TREE_THIS_VOLATILE (current_function_decl))
+ warning_at (xloc, 0,
+ "function declared %<noreturn%> has a %<return%> statement");
+
+ if (! retval)
+ current_function_returns_null = 1;
+ else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
+ {
+ current_function_returns_null = 1;
+ if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+ {
+ error_at
+ (xloc, "%<return%> with a value, in function returning void");
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "declared here");
+ }
+ }
+ else if (TREE_CODE (valtype) != TREE_CODE (TREE_TYPE (retval)))
+ {
+ error_at
+ (xloc, "invalid conversion in return statement");
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "declared here");
+ }
+ return;
+}
new file mode 100644
@@ -0,0 +1,27 @@
+/* Declarations for the parser for GIMPLE.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_GIMPLE_PARSER_H
+#define GCC_GIMPLE_PARSER_H
+
+/* Gimple parsing functions. */
+extern void c_parser_parse_gimple_body (c_parser *);
+extern void c_parser_gimple_pass_list (c_parser *, opt_pass **, bool *);
+
+#endif
@@ -35,4 +35,4 @@ lang_requires="c"
# Order is important. If you change this list, make sure you test
# building without C++ as well; that is, remove the gcc/cp directory,
# and build with --enable-languages=c,objc.
-gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
+gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c/c-parser.h \$(srcdir)/c/c-parser.c \$(srcdir)/c/c-tree.h \$(srcdir)/c/c-decl.c \$(srcdir)/c/c-lang.h \$(srcdir)/c/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"