diff options
author | Jason Merrill <jason@redhat.com> | 2015-10-04 15:17:19 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2015-10-04 15:17:19 -0400 |
commit | b8fd7909c04a29e82fb3ebace161801f949ad4f5 (patch) | |
tree | b68c53c0fcfa672f4c0e3577083662356ee4953d /gcc/cp/parser.c | |
parent | bd841941ec9b1864216573f4426e694f806dd4bf (diff) | |
download | gcc-b8fd7909c04a29e82fb3ebace161801f949ad4f5.zip gcc-b8fd7909c04a29e82fb3ebace161801f949ad4f5.tar.gz gcc-b8fd7909c04a29e82fb3ebace161801f949ad4f5.tar.bz2 |
Implement N4514, C++ Extensions for Transactional Memory.
gcc/
* builtins.def (BUILT_IN_ABORT): Add transaction_pure attribute.
gcc/c-family/
* c-common.c (c_common_reswords): Add C++ TM TS keywords.
(c_common_attribute_table): Add transaction_safe_dynamic.
transaction_safe now affects type identity.
(handle_tm_attribute): Handle transaction_safe_dynamic.
* c-common.h (enum rid): Add RID_ATOMIC_NOEXCEPT,
RID_ATOMIC_CANCEL, RID_SYNCHRONIZED.
(OBJC_IS_CXX_KEYWORD): Add RID_SYNCHRONIZED.
(D_TRANSMEM): New.
* c-cppbuiltin.c (c_cpp_builtins): Define __cpp_transactional_memory.
* c-pretty-print.c (pp_c_attributes_display): Don't print
transaction_safe in C++.
gcc/c/
* c-parser.c (c_lex_one_token): Handle @synchronized.
* c-decl.c (match_builtin_function_types): A declaration of a built-in
can change whether the function is transaction_safe.
gcc/cp/
* cp-tree.h (struct cp_declarator): Add tx_qualifier field.
(BCS_NORMAL, BCS_TRANSACTION): New enumerators.
* lex.c (init_reswords): Limit TM kewords to -fgnu-tm.
* parser.c (cp_lexer_get_preprocessor_token): Fix @synchronized.
(make_call_declarator): Take tx_qualifier.
(cp_parser_tx_qualifier_opt): New.
(cp_parser_lambda_declarator_opt): Use it.
(cp_parser_direct_declarator): Likewise.
(cp_parser_statement): Handle atomic_noexcept, atomic_cancel.
(cp_parser_compound_statement): Change in_try parameter to bcs_flags.
(cp_parser_std_attribute): Map optimize_for_synchronized to
transaction_callable.
(cp_parser_transaction): Take the token. Handle atomic_noexcept.
* lambda.c (maybe_add_lambda_conv_op): Handle transaction-safety.
* call.c (enum conversion_kind): Add ck_tsafe.
(standard_conversion): Handle transaction-safety conversion.
(convert_like_real, resolve_address_of_overloaded_function): Likewise.
(check_methods): Diagnose transaction_safe_dynamic on non-virtual
function.
(look_for_tm_attr_overrides): Don't inherit transaction_safe_dynamic.
* cvt.c (tx_safe_fn_type_p, tx_unsafe_fn_variant)
(can_convert_tx_safety): New.
* typeck.c (composite_pointer_type): Handle transaction-safety.
* name-lookup.h (enum scope_kind): Add sk_transaction.
* name-lookup.c (begin_scope): Handle it.
* semantics.c (begin_compound_stmt): Pass it.
* decl.c (check_previous_goto_1): Check it.
(struct named_label_entry): Add in_transaction_scope.
(poplevel_named_label_1): Set it.
(check_goto): Check it.
(duplicate_decls): A specialization can be transaction_safe
independently of its template.
(grokdeclarator): Handle tx-qualifier.
* rtti.c (ptr_initializer): Handle transaction-safe.
* search.c (check_final_overrider): Check transaction_safe_dynamic.
Don't check transaction_safe.
* mangle.c (write_function_type): Mangle transaction_safe here.
(write_CV_qualifiers_for_type): Not here.
(write_type): Preserve transaction_safe when stripping attributes.
* error.c (dump_type_suffix): Print transaction_safe.
libiberty/
* cp-demangle.c (d_cv_qualifiers): Dx means transaction_safe.
(cplus_demangle_type): Let d_cv_qualifiers handle it.
(d_dump, d_make_comp, has_return_type, d_encoding)
(d_count_templates_scopes, d_print_comp_inner)
(d_print_mod_list, d_print_mod, d_print_function_type)
(is_ctor_or_dtor): Handle DEMANGLE_COMPONENT_TRANSACTION_SAFE.
From-SVN: r228462
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 123 |
1 files changed, 94 insertions, 29 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 46aff88..ffed595 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -829,6 +829,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token) case RID_THROW: token->keyword = RID_AT_THROW; break; case RID_TRY: token->keyword = RID_AT_TRY; break; case RID_CATCH: token->keyword = RID_AT_CATCH; break; + case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break; default: token->keyword = C_RID_CODE (token->u.value); } } @@ -1343,7 +1344,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) VAR_DECLs or FUNCTION_DECLs) should do that directly. */ static cp_declarator *make_call_declarator - (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, tree, tree, tree); + (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, tree, tree, tree, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1521,6 +1522,7 @@ make_call_declarator (cp_declarator *target, cp_cv_quals cv_qualifiers, cp_virt_specifiers virt_specifiers, cp_ref_qualifier ref_qualifier, + tree tx_qualifier, tree exception_specification, tree late_return_type, tree requires_clause) @@ -1533,6 +1535,7 @@ make_call_declarator (cp_declarator *target, declarator->u.function.qualifiers = cv_qualifiers; declarator->u.function.virt_specifiers = virt_specifiers; declarator->u.function.ref_qualifier = ref_qualifier; + declarator->u.function.tx_qualifier = tx_qualifier; declarator->u.function.exception_specification = exception_specification; declarator->u.function.late_return_type = late_return_type; declarator->u.function.requires_clause = requires_clause; @@ -2029,7 +2032,7 @@ static void cp_parser_label_for_labeled_statement static tree cp_parser_expression_statement (cp_parser *, tree); static tree cp_parser_compound_statement - (cp_parser *, tree, bool, bool); + (cp_parser *, tree, int, bool); static void cp_parser_statement_seq_opt (cp_parser *, tree); static tree cp_parser_selection_statement @@ -2139,6 +2142,8 @@ static cp_virt_specifiers cp_parser_virt_specifier_seq_opt (cp_parser *); static cp_ref_qualifier cp_parser_ref_qualifier_opt (cp_parser *); +static tree cp_parser_tx_qualifier_opt + (cp_parser *); static tree cp_parser_late_return_type_opt (cp_parser *, cp_declarator *, tree &, cp_cv_quals); static tree cp_parser_declarator_id @@ -2346,7 +2351,7 @@ static tree cp_parser_nested_requirement /* Transactional Memory Extensions */ static tree cp_parser_transaction - (cp_parser *, enum rid); + (cp_parser *, cp_token *); static tree cp_parser_transaction_expression (cp_parser *, enum rid); static bool cp_parser_function_transaction @@ -4262,7 +4267,7 @@ cp_parser_statement_expr (cp_parser *parser) /* Start the statement-expression. */ tree expr = begin_stmt_expr (); /* Parse the compound-statement. */ - cp_parser_compound_statement (parser, expr, false, false); + cp_parser_compound_statement (parser, expr, BCS_NORMAL, false); /* Finish up. */ expr = finish_stmt_expr (expr, false); /* Consume the ')'. */ @@ -9630,6 +9635,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) tree attributes = NULL_TREE; tree exception_spec = NULL_TREE; tree template_param_list = NULL_TREE; + tree tx_qual = NULL_TREE; /* The template-parameter-list is optional, but must begin with an opening angle if present. */ @@ -9680,6 +9686,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1; } + tx_qual = cp_parser_tx_qualifier_opt (parser); + /* Parse optional exception specification. */ exception_spec = cp_parser_exception_specification_opt (parser); @@ -9727,6 +9735,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) declarator = make_call_declarator (declarator, param_list, quals, VIRT_SPEC_UNSPECIFIED, REF_QUAL_NONE, + tx_qual, exception_spec, /*late_return_type=*/NULL_TREE, /*requires_clause*/NULL_TREE); @@ -10043,7 +10052,10 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, case RID_TRANSACTION_ATOMIC: case RID_TRANSACTION_RELAXED: - statement = cp_parser_transaction (parser, keyword); + case RID_SYNCHRONIZED: + case RID_ATOMIC_NOEXCEPT: + case RID_ATOMIC_CANCEL: + statement = cp_parser_transaction (parser, token); break; case RID_TRANSACTION_CANCEL: statement = cp_parser_transaction_cancel (parser); @@ -10072,7 +10084,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, } /* Anything that starts with a `{' must be a compound-statement. */ else if (token->type == CPP_OPEN_BRACE) - statement = cp_parser_compound_statement (parser, NULL, false, false); + statement = cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); /* CPP_PRAGMA is a #pragma inside a function body, which constitutes a statement all its own. */ else if (token->type == CPP_PRAGMA) @@ -10327,7 +10339,7 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) static tree cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, - bool in_try, bool function_body) + int bcs_flags, bool function_body) { tree compound_stmt; @@ -10339,7 +10351,7 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, pedwarn (input_location, OPT_Wpedantic, "compound-statement in constexpr function"); /* Begin the compound-statement. */ - compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0); + compound_stmt = begin_compound_stmt (bcs_flags); /* If the next keyword is `__label__' we have a label declaration. */ while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL)) cp_parser_label_declaration (parser); @@ -11500,7 +11512,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p, } /* if a compound is opened, we simply parse the statement directly. */ else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) - statement = cp_parser_compound_statement (parser, NULL, false, false); + statement = cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); /* If the token is not a `{', then we must take special action. */ else { @@ -18451,6 +18463,8 @@ cp_parser_direct_declarator (cp_parser* parser, cv_quals = cp_parser_cv_qualifier_seq_opt (parser); /* Parse the ref-qualifier. */ ref_qual = cp_parser_ref_qualifier_opt (parser); + /* Parse the tx-qualifier. */ + tree tx_qual = cp_parser_tx_qualifier_opt (parser); /* And the exception-specification. */ exception_specification = cp_parser_exception_specification_opt (parser); @@ -18489,6 +18503,7 @@ cp_parser_direct_declarator (cp_parser* parser, cv_quals, virt_specifiers, ref_qual, + tx_qual, exception_specification, late_return, requires_clause); @@ -19101,6 +19116,41 @@ cp_parser_ref_qualifier_opt (cp_parser* parser) return ref_qual; } +/* Parse an optional tx-qualifier. + + tx-qualifier: + transaction_safe + transaction_safe_dynamic */ + +static tree +cp_parser_tx_qualifier_opt (cp_parser *parser) +{ + cp_token *token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_NAME) + { + tree name = token->u.value; + const char *p = IDENTIFIER_POINTER (name); + const int len = strlen ("transaction_safe"); + if (!strncmp (p, "transaction_safe", len)) + { + p += len; + if (*p == '\0' + || !strcmp (p, "_dynamic")) + { + cp_lexer_consume_token (parser->lexer); + if (!flag_tm) + { + error ("%E requires %<-fgnu-tm%>", name); + return NULL_TREE; + } + else + return name; + } + } + } + return NULL_TREE; +} + /* Parse an (optional) virt-specifier-seq. virt-specifier-seq: @@ -20109,7 +20159,9 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) static void cp_parser_function_body (cp_parser *parser, bool in_function_try_block) { - cp_parser_compound_statement (parser, NULL, in_function_try_block, true); + cp_parser_compound_statement (parser, NULL, (in_function_try_block + ? BCS_TRY_BLOCK : BCS_NORMAL), + true); } /* Parse a ctor-initializer-opt followed by a function-body. Return @@ -22598,7 +22650,7 @@ cp_parser_try_block (cp_parser* parser) error ("%<try%> in %<constexpr%> function"); try_block = begin_try_block (); - cp_parser_compound_statement (parser, NULL, true, false); + cp_parser_compound_statement (parser, NULL, BCS_TRY_BLOCK, false); finish_try_block (try_block); cp_parser_handler_seq (parser); finish_handler_sequence (try_block); @@ -22675,7 +22727,7 @@ cp_parser_handler (cp_parser* parser) declaration = cp_parser_exception_declaration (parser); finish_handler_parms (declaration, handler); cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); - cp_parser_compound_statement (parser, NULL, false, false); + cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); finish_handler (handler); } @@ -23354,6 +23406,14 @@ cp_parser_std_attribute (cp_parser *parser) " use %<gnu::deprecated%>"); TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu"); } + /* Transactional Memory TS optimize_for_synchronized attribute is + equivalent to GNU transaction_callable. */ + else if (is_attribute_p ("optimize_for_synchronized", attr_id)) + TREE_PURPOSE (attribute) + = get_identifier ("transaction_callable"); + /* Transactional Memory attributes are GNU attributes. */ + else if (tm_attr_to_mask (attr_id)) + TREE_PURPOSE (attribute) = attr_id; } /* Now parse the optional argument clause of the attribute. */ @@ -28391,7 +28451,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false, false); + cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); objc_begin_try_stmt (location, pop_stmt_list (stmt)); while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH)) @@ -28447,7 +28507,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) forget about the closing parenthesis and keep going. */ } objc_begin_catch_clause (parameter_declaration); - cp_parser_compound_statement (parser, NULL, false, false); + cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); objc_finish_catch_clause (); } if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY)) @@ -28457,7 +28517,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false, false); + cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); objc_build_finally_clause (location, pop_stmt_list (stmt)); } @@ -28488,7 +28548,7 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false, false); + cp_parser_compound_statement (parser, NULL, BCS_NORMAL, false); return objc_build_synchronized (location, lock, pop_stmt_list (stmt)); } @@ -33964,8 +34024,8 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok) attribute [ [ identifier ] ] - ??? Simplify this when C++0x bracket attributes are - implemented properly. */ + We use this instead of cp_parser_attributes_opt for transactions to avoid + the pedwarn in C++98 mode. */ static tree cp_parser_txn_attribute_opt (cp_parser *parser) @@ -34012,21 +34072,17 @@ cp_parser_txn_attribute_opt (cp_parser *parser) */ static tree -cp_parser_transaction (cp_parser *parser, enum rid keyword) +cp_parser_transaction (cp_parser *parser, cp_token *token) { unsigned char old_in = parser->in_transaction; unsigned char this_in = 1, new_in; - cp_token *token; + enum rid keyword = token->keyword; tree stmt, attrs, noex; - gcc_assert (keyword == RID_TRANSACTION_ATOMIC - || keyword == RID_TRANSACTION_RELAXED); - token = cp_parser_require_keyword (parser, keyword, - (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC - : RT_TRANSACTION_RELAXED)); - gcc_assert (token != NULL); + cp_lexer_consume_token (parser->lexer); - if (keyword == RID_TRANSACTION_RELAXED) + if (keyword == RID_TRANSACTION_RELAXED + || keyword == RID_SYNCHRONIZED) this_in |= TM_STMT_ATTR_RELAXED; else { @@ -34036,7 +34092,16 @@ cp_parser_transaction (cp_parser *parser, enum rid keyword) } /* Parse a noexcept specification. */ - noex = cp_parser_noexcept_specification_opt (parser, true, NULL, true); + if (keyword == RID_ATOMIC_NOEXCEPT) + noex = boolean_true_node; + else if (keyword == RID_ATOMIC_CANCEL) + { + /* cancel-and-throw is unimplemented. */ + sorry ("atomic_cancel"); + noex = NULL_TREE; + } + else + noex = cp_parser_noexcept_specification_opt (parser, true, NULL, true); /* Keep track if we're in the lexical scope of an outer transaction. */ new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); @@ -34044,7 +34109,7 @@ cp_parser_transaction (cp_parser *parser, enum rid keyword) stmt = begin_transaction_stmt (token->location, NULL, this_in); parser->in_transaction = new_in; - cp_parser_compound_statement (parser, NULL, false, false); + cp_parser_compound_statement (parser, NULL, BCS_TRANSACTION, false); parser->in_transaction = old_in; finish_transaction_stmt (stmt, NULL, this_in, noex); |