aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2009-09-14 13:17:24 -0700
committerRichard Henderson <rth@gcc.gnu.org>2009-09-14 13:17:24 -0700
commit1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c (patch)
treed43d66a4da24c2d77ee8f88fc747f6a2f149435f /gcc/cp/parser.c
parent40c88b9403ef1e2b2e93ff70a5fb794916027665 (diff)
downloadgcc-1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c.zip
gcc-1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c.tar.gz
gcc-1c384bf142c81baaad7f04c5d3fdaebcbafc5b0c.tar.bz2
builtins.c (expand_builtin_synchronize): Use gimple_build_asm_vec.
* builtins.c (expand_builtin_synchronize): Use gimple_build_asm_vec. * cfgbuild.c (make_edges): Handle asm goto. * cfglayout.c (fixup_reorder_chain): Likewise. * cfgrtl.c (patch_jump_insn): Likewise. * gimple-pretty-print.c (dump_gimple_asm): Likewise. * gimple.c (gimple_build_asm_1): Add and use nlabels parameter. (gimple_build_asm_vec): Add and use labels parameter. (gimple_build_asm): Remove. (walk_gimple_asm): Walk labels too. * gimple.def (GIMPLE_ASM): Update docs. * gimple.h: Update decls. (struct gimple_statement_asm): Change nc to use unsigned char; add nl member. (gimple_asm_nlabels): New. (gimple_asm_label_op, gimple_asm_set_label_op): New. * gimplify.c (gimplify_asm_expr): Copy labels from ASM_EXPR into gimple_build_asm_vec. * jump.c (mark_jump_label_asm): New. (mark_jump_label): Use it. (redirect_jump_1): Handle asm goto. (invert_jump_1): Soft fail if X is null. * recog.c (extract_asm_operands): New. (asm_noperands): Use it; handle asm labels. (decode_asm_operands): Use extract_asm_operands. (asm_operand_ok): Properly handle empty string. * reg-stack.c (get_asm_operands_in_out): Rename from get_asm_operand_n_inputs; use extract_asm_operands; return both inputs and outputs by reference; update all callers. * rtl.def (ASM_OPERANDS): Add label vector as operand 6. * rtl.h (ASM_OPERANDS_LABEL_VEC): New. (ASM_OPERANDS_LABEL_LENGTH, ASM_OPERANDS_LABEL): New. (ASM_OPERANDS_SOURCE_LOCATION): Renumber. (extract_asm_operands): Declare. * stmt.c (expand_asm_operands): Add and use labels parameter. (check_unique_operand_names): Likewise. (resolve_asm_operand_names, resolve_operand_name_1): Likewise. (expand_asm_stmt): Handle asm labels. * tree-cfg.c (make_gimple_asm_edges): New. (make_edges): Use it. (cleanup_dead_labels): Handle asm labels. (is_ctrl_altering_stmt): Likewise. (gimple_redirect_edge_and_branch): Likewise. * tree.def (ASM_EXPR): Add 5th operand. * tree.h (ASM_LABELS): New. (resolve_asm_operand_names): Update decl. * c-parser.c (c_parser_asm_statement): Parse asm goto. (c_parser_asm_goto_operands): New. * c-tree.h (build_asm_expr): Update decl. * c-typeck.c (build_asm_expr): Add and use labels parameter. * doc/extend.texi: Document asm goto. gcc/ada/ * gcc-interface/trans.c (Pragma_to_gnu): Use build5 for ASM_EXPR. gcc/cp/ * cp-tree.h (finish_asm_stmt): Update decl. * parser.c (cp_parser_asm_definition): Parse asm goto. (cp_parser_asm_label_list): New. * pt.c (tsubst_copy_asm_operands): Don't recurse on labels. (tsubst_expr): Handle asm labels. * semantics.c (finish_asm_stmt): Add and use labels parameter. gcc/testsuite/ * c-c++-common/asmgoto-1.c, c-c++-common/asmgoto-2.c, c-c++-common/asmgoto-3.c, gcc.c-torture/compile/asmgoto-1.c, gcc.dg/tree-ssa/asmgoto-1.c: New files. Co-Authored-By: Jakub Jelinek <jakub@redhat.com> From-SVN: r151701
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c99
1 files changed, 94 insertions, 5 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 14733b8..55effed 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1859,6 +1859,8 @@ static tree cp_parser_asm_operand_list
(cp_parser *);
static tree cp_parser_asm_clobber_list
(cp_parser *);
+static tree cp_parser_asm_label_list
+ (cp_parser *);
static tree cp_parser_attributes_opt
(cp_parser *);
static tree cp_parser_attribute_list
@@ -12531,7 +12533,10 @@ cp_parser_using_directive (cp_parser* parser)
: asm-operand-list [opt] ) ;
asm volatile [opt] ( string-literal : asm-operand-list [opt]
: asm-operand-list [opt]
- : asm-operand-list [opt] ) ; */
+ : asm-clobber-list [opt] ) ;
+ asm volatile [opt] goto ( string-literal : : asm-operand-list [opt]
+ : asm-clobber-list [opt]
+ : asm-goto-list ) ; */
static void
cp_parser_asm_definition (cp_parser* parser)
@@ -12540,11 +12545,14 @@ cp_parser_asm_definition (cp_parser* parser)
tree outputs = NULL_TREE;
tree inputs = NULL_TREE;
tree clobbers = NULL_TREE;
+ tree labels = NULL_TREE;
tree asm_stmt;
bool volatile_p = false;
bool extended_p = false;
bool invalid_inputs_p = false;
bool invalid_outputs_p = false;
+ bool goto_p = false;
+ const char *missing = NULL;
/* Look for the `asm' keyword. */
cp_parser_require_keyword (parser, RID_ASM, "%<asm%>");
@@ -12557,6 +12565,15 @@ cp_parser_asm_definition (cp_parser* parser)
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
}
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && parser->in_function_body
+ && cp_lexer_next_token_is_keyword (parser->lexer, RID_GOTO))
+ {
+ /* Remember that we saw the `goto' keyword. */
+ goto_p = true;
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ }
/* Look for the opening `('. */
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return;
@@ -12581,6 +12598,7 @@ cp_parser_asm_definition (cp_parser* parser)
{
bool inputs_p = false;
bool clobbers_p = false;
+ bool labels_p = false;
/* The extended syntax was used. */
extended_p = true;
@@ -12596,7 +12614,8 @@ cp_parser_asm_definition (cp_parser* parser)
&& cp_lexer_next_token_is_not (parser->lexer,
CPP_SCOPE)
&& cp_lexer_next_token_is_not (parser->lexer,
- CPP_CLOSE_PAREN))
+ CPP_CLOSE_PAREN)
+ && !goto_p)
outputs = cp_parser_asm_operand_list (parser);
if (outputs == error_mark_node)
@@ -12618,6 +12637,8 @@ cp_parser_asm_definition (cp_parser* parser)
if (cp_lexer_next_token_is_not (parser->lexer,
CPP_COLON)
&& cp_lexer_next_token_is_not (parser->lexer,
+ CPP_SCOPE)
+ && cp_lexer_next_token_is_not (parser->lexer,
CPP_CLOSE_PAREN))
inputs = cp_parser_asm_operand_list (parser);
@@ -12632,16 +12653,41 @@ cp_parser_asm_definition (cp_parser* parser)
if (clobbers_p
|| cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
+ clobbers_p = true;
/* Consume the `:' or `::'. */
cp_lexer_consume_token (parser->lexer);
/* Parse the clobbers. */
if (cp_lexer_next_token_is_not (parser->lexer,
- CPP_CLOSE_PAREN))
+ CPP_COLON)
+ && cp_lexer_next_token_is_not (parser->lexer,
+ CPP_CLOSE_PAREN))
clobbers = cp_parser_asm_clobber_list (parser);
}
+ else if (goto_p
+ && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
+ /* The labels are coming next. */
+ labels_p = true;
+
+ /* Look for labels. */
+ if (labels_p
+ || (goto_p && cp_lexer_next_token_is (parser->lexer, CPP_COLON)))
+ {
+ labels_p = true;
+ /* Consume the `:' or `::'. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the labels. */
+ labels = cp_parser_asm_label_list (parser);
+ }
+
+ if (goto_p && !labels_p)
+ missing = clobbers_p ? "%<:%>" : "%<:%> or %<::%>";
}
+ else if (goto_p)
+ missing = "%<:%> or %<::%>";
+
/* Look for the closing `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+ if (!cp_parser_require (parser, missing ? CPP_COLON : CPP_CLOSE_PAREN,
+ missing ? missing : "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
@@ -12652,7 +12698,7 @@ cp_parser_asm_definition (cp_parser* parser)
if (parser->in_function_body)
{
asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
- inputs, clobbers);
+ inputs, clobbers, labels);
/* If the extended syntax was not used, mark the ASM_EXPR. */
if (!extended_p)
{
@@ -16866,6 +16912,49 @@ cp_parser_asm_clobber_list (cp_parser* parser)
return clobbers;
}
+/* Parse an asm-label-list.
+
+ asm-label-list:
+ identifier
+ asm-label-list , identifier
+
+ Returns a TREE_LIST, indicating the labels in the order that they
+ appeared. The TREE_VALUE of each node is a label. */
+
+static tree
+cp_parser_asm_label_list (cp_parser* parser)
+{
+ tree labels = NULL_TREE;
+
+ while (true)
+ {
+ tree identifier, label, name;
+
+ /* Look for the identifier. */
+ identifier = cp_parser_identifier (parser);
+ if (!error_operand_p (identifier))
+ {
+ label = lookup_label (identifier);
+ if (TREE_CODE (label) == LABEL_DECL)
+ {
+ TREE_USED (label) = 1;
+ check_goto (label);
+ name = build_string (IDENTIFIER_LENGTH (identifier),
+ IDENTIFIER_POINTER (identifier));
+ labels = tree_cons (name, label, labels);
+ }
+ }
+ /* If the next token is not a `,', then the list is
+ complete. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+ break;
+ /* Consume the `,' token. */
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ return nreverse (labels);
+}
+
/* Parse an (optional) series of attributes.
attributes: